在处理WM_NCLBUTTONDOWN消息的时候,Windows有时自动过滤了WM_NCLBUTTONUP消息,导致后续的ReleaseCapture() 不被执行,所以窗口一直都扑获鼠标,就不响应其他了,但当切换到其他窗口的时候,操作系统自动使该Window 失去Capture() 所以回来时又正常了

解决方案 »

  1.   

    你应该在WM_LBUTTONUP下加入ReleaseCapture()
    因为你一旦设置了SetCapture()鼠标消息将被Post到用户窗口
      

  2.   

    呵呵,谢谢两位朋友的提醒,我当然在 WM_NCLBUTTONUP 里面加了 ReleaseCapture(),可是看那种表现好象程序根本就收不到 WM_NCLBUTTONUP,所以加了也没用,我很奇怪这是为什么?有什么道理吗?
      

  3.   

    请 blue_flash(蓝色闪电) 再详细解释一下好吗?
      

  4.   

    你可以用"WM_NCLBUTTONUP"或"WM_NCLBUTTONUP WM_NCPAINT"在google中搜索,有些文章讲过这方面的问题.
      

  5.   

    对,其实已经解决了标题栏按钮的问题了,但是还有一点点瑕疵(几乎察觉不到),考虑了很久认为还是用捕获鼠标做比较好。谢谢 cline(营营),我找找看。也希望各位高手继续讨论。
      

  6.   

    很多软件也有那个瑕疵,比如QQ2000。给你一点自信,可看看http://www.csdn.net/cnshare/soft/10/10802.shtm
      

  7.   

    很多软件也有那个瑕疵,比如QQ2000。给你一点自信,可看看http://www.csdn.net/cnshare/soft/10/10802.shtm
      

  8.   

    这个不太懂,以前的程序我也是在别人的基础胡乱改出的,逻辑也不太明了(哪个程序没用SetCapture)。 这个东东好像很难控制的,因为DefWindowProc不但处理消息,还做了一些绘画的工作;实际上是很难分离的,如果能参考Windows的源码,可能就好多了。
    你多尝试了。
      

  9.   

    to: 2ndboy (丢丢)
    确切的说是看了你的问题后自己建了个测试程序,调试了一下得出的一半结果,另一半是平常开发软件积累的知识了。
      

  10.   

    很简单,调试MFC,如果找不到答案,用WINICE调试API就成
      

  11.   

    那么也就是说可以得出这么一个结论:在处理WM_NCLBUTTONDOWN消息时捕获鼠标,其结果将导致收不到WM_NCLBUTTONUP,对吗?回答“是”或“不是”就给分。
      

  12.   

    This article was contributed by Robert Wiejak. 
     Environment: MFC, Windows 95, 98, Me, NT 3.51, 4.0, 5.0 If you spend time investigating what happens when you click and release the left button over the title bar, you will find out that instead of getting "non-client left button up" message, you just get "left button up". One could actually work with it, if the message found it's way into the application. It does not.I was in a middle of writing an application when I discovered this. I looked all over the internet for articles regarding WM_NCLBUTTONUP problem, but the only thing I could find were questions about the problem. After some more investigating I have come up with a patch that could be adopted by each application requiring such notification.The patch consists of installing a "windows hook" that will intercept all mouse messages for this application before they enter into the message pump. To do that you need to call SetWindowsHookEx(...) function, soon after the main window is created. Here is the call: hMHook = SetWindowsHookEx( 
                         // hook type: 
                    WH_MOUSE,
                         // hook procedure: 
                    (HOOKPROC) MouseHookProc,
                         // handle to application instance: 
                    AfxGetInstanceHandle(),
                         // thread identifier: 
                    AfxGetThread()->m_nThreadID
                );
    It is very important that you supply handle to application instance and thread identifier, otherwise every application running on your computer will attempt to hook it's mouse messages through your program and it could be disastrous. By supplying these two parameters you will insure that only messages from your application will end up in your callback function. Equally important is a call to remove the hook before your application terminates. The UnhookWindowsHookEx(...) function removes a hook procedure installed in a hook chain. Most likely you will call it somewhere in OnDestroy(), like this:    if(hMHook != NULL)
          UnhookWindowsHookEx(hMHook);
    The callback function is where you will receive WM_NCLBUTTONDOWN message and the next time you receive WM_LBUTTONUP message you will post WM_NCLBUTTONUP directly into the application message pump. Therefore, no special handling will be required to service these messages. You will simply write your code inside of OnNcLButtonUp(...), just like you would for any other message. Here is the callback code: // ////////////////////////////////////////////////////
    // handle to the mouse hook
    HHOOK hMHook = NULL;// status of non-client left button down
    BOOL bNcLButtonDown = FALSE;  // /////////////////////////////////////////////////////
    // Mouse hook processLRESULT CALLBACK MouseHookProc( int nCode, 
                                    WPARAM wParam,
                                    LPARAM lParam) 

      if(nCode == HC_ACTION) 
      { 
        // get a pointer to the mouse hook struct. 
        PMOUSEHOOKSTRUCT mhs = (PMOUSEHOOKSTRUCT) lParam; 
        
        // intercept messages for left button down and up
        switch(wParam) 
        { 
            case WM_NCLBUTTONDOWN: 
             {
                 // get the pointer to the main window 
                 CWnd *pWnd =  AfxGetMainWnd();              // if the message is from your window and 
                 // the hit test indicates title bar 
                 if((mhs->hwnd == pWnd->GetSafeHwnd()) 
                     && (mhs->wHitTestCode == HTCAPTION))
                 { 
                     // then indicate non-client left button down 
                     bNcLButtonDown = TRUE; 
                    
                    //  there is no problem with this message 
                    // so you don't have to do anything else 
                 } 
            } 
            break; 
            
            case WM_NCLBUTTONUP: 
                // you will get this message if you double-click 
                //     on the title bar 
                // reset the status 
                bNcLButtonDown = FALSE;  
                break;        case WM_LBUTTONUP: 
              {
                  //  get the pointer to the main window 
                  CWnd *pWnd = AfxGetMainWnd();               // if the message is from your window and 
                  // non-client left button is down
                  if((mhs->hwnd == pWnd->GetSafeHwnd()) 
                      && (bNcLButtonDown == TRUE)) 
                  {
                     // then post WM_NCLBUTTONUP message directly 
                     // into your window message pump 
                     // Note: I'm hardcoding HTCAPTION because the 
                     // left button was down, and while it is down,
                     // the mouse does not move in respect to the 
                     // window, but it does in respect to the screen,
                     // so the mouse should still be over the caption
                     // bar of your window when you release the button.
                     pWnd->PostMessage(WM_NCLBUTTONUP, HTCAPTION, 
                                    MAKELONG(mhs->pt.x,mhs->pt.y));                 // reset non-client left button down 
                     bNcLButtonDown = FALSE;
                  }
              } 
              break;         default: 
                break; 
        } 
      } 
      // let the messages through to the next hook 
     return CallNextHookEx(hMHook, nCode, wParam, lParam); 
    }I am including two sample projects. The "nclbxExample" is technical, and the "AlphaDialogExample" is more practical. The "nclbxExample" is better documented so you can see how and were I have implemented the code. NOTE: If you are going to use mousepatch.cpp the way I'm using it, DO NOT add it to your project. Downloads
    Download nclbxExample project - 38 Kb
    Download AlphaDialogExample project - 118 Kb (will only work in Win2K)
    Download source - 2 Kb 
    History
    Date Posted: Jun 26, 2001Add Comment 
      

  13.   

    上面的代码来至http://www.codeguru.com
      

  14.   

    Finally, the message map of CMyWnd is set to include, among other messages, the WM_NCPAINT message. CMyWnd's OnNcPaint handler function calls MyPaint, which does my nonclient painting. Figure 2 shows what windows look like under the version of MyPaint that I use. Notice that the frame has a 3-D look, the title-bar font is different, and the nonclient area buttons use new visuals and are no longer in their default positions. Because the title bar, borders, caption-bar buttons, and so on, no longer conform to the Windows defaults, the message map needs to add the WM_NCHITTEST message, and the corresponding handler, OnNcHitTest, must return the correct value (HTCAPTION, HTMINBUTTON, and so on) to indicate the position of the cursor on our window's nonclient area. We also need to detect mouse clicks over our repositioned, nonclient area buttons ourselves, so the message map includes the WM_NCLBUTTONDOWN and WM_LBUTTONUP messages. To do this, I check in CMyWnd's OnNcLButtonDown handler to see if the mouse-down was on one of the repositioned buttons; if so, I set a flag and capture the mouse. In the OnLButtonUp handler function, I check if the mouse-up occurred on a button, and from the flags value, I determine if the mouse-up occurred on the same button that we recorded the mouse-down on. If it did, a mouse click occurred, so I do whatever is appropriate for that button. The code for MyPaint and the OnNcHitTest, OnNcLButtonDown, and OnLButtonUp handler functions is not shown in the listings, but you can customize these functions to create any window look or nonclient button positions (and functionality) of your own choice.
      

  15.   

    在处理WM_NCLBUTTONDOWN消息时捕获鼠标,其结果将导致收不到WM_NCLBUTTONUP,不对.
    WM_NCLBUTTONDOWN与WM_LBUTTONDOWN唯一的区别是消息ID中的字母NC不同.
    还有一点不同是WM_NCxBUTTONDBLCLK消息无论窗口注册了CS_DBLCLKS与否都要发送.
    看一看你的WM_NCLBUTTONDOWN消息是否处理了CPoint参数,是否用
    CWnd::ScreenToClient函数将屏幕坐标变换为客户区坐标.
      

  16.   

    非常感谢 cline(营营) 提供的资料,一段话点醒梦中人!让我终于完全的明白了其中道理!!!==========================================================
    本着对这个问题负责的意思,我在这儿做个总结发言:
    在我们捕获了鼠标的时候,所有的鼠标消息都被泵到我们自己的窗口处理函数中了(在 Win32 平台下其它窗口还是可以在鼠标移入的时候得到消息的,除非捕获鼠标后按键就根本没有释放),而此时(捕获鼠标后)非客户区鼠标消息将不再生成(由 Spy 观察得到),直至“捕获”被释放。
    这个机制不能不说是 Windows 消息机制的败笔,我认为完美的捕获实现应该将捕获后本该属于此窗口的所有消息都发给它。当然这可能是由于任务栏由 Windows 负责了很多工作有关。
      

  17.   

    基于以上原理,可以得到两种解决方案:
    (1)用处理 WM_MOUSEMOVE 代替处理 WM_NCMOUSEMOVE;用处理 WM_LBUTTONUP 代替处理 WM_NCLBUTTONUP。
    其实说代替也不准确,因为干脆就收不到那两个消息。不过要注意的就是,因为在非客户区中时纵坐标是负的,所以最好不要使用消息夹带的鼠标坐标,而是用 GetCursorPos 得到。
    (2)用上面 cline(营营) 提供的方法,使用局部线程 Hook,这样的好处是形式上比较优雅,而且在相应的消息中处理对应的事也比较符合逻辑。所以推荐使用这种方法!
      

  18.   

    呵呵,真的很感谢 cline(营营) 和 blue_flash(蓝色闪电)!其实一场精彩的讨论比弄清一个问题来的更痛快!希望以后可以有再多一些的机会交流!!!本贴的分数全部属于 blue_flash(蓝色闪电) 了,至于 cline(营营) 嘛............决定另开一个 200 分的帖子给分!再次感谢!!!
      

  19.   

    2ndboy(丢丢) :
    不用另开贴给分了!如果能给我的帖子一点关注,或者帮我写一两篇就好了。http://www.csdn.net/expert/topic/680/680626.xml?temp=.3119623