MFC Windows 程序设计->实现客户区拖动

 

One problem with a window without a title bar is that it can't be repositioned with the mouse. Windows are dragged by their title bars, and when there's no title bar, the user has nothing to grab onto. Clock solves this little dilemma by playing a trick with the window's WM_NCHITTEST handler so that the window can be dragged by its client area, a feature Windows programmers call client-area drag.

In Windows, every mouse message is preceded by a WM_NCHITTEST message containing screen coordinates identifying the cursor location. The message is normally handled by ::DefWindowProc, which returns a code that tells Windows what part of the window the cursor is over. Windows uses the return value to decide what type of mouse message to send. For example, if the left mouse button is clicked over the window's title bar, ::DefWindowProc's WM_NCHITTEST handler returns HTCAPTION and Windows sends the window a WM_NCLBUTTONDOWN message. If ::DefWindowProc returns HTCLIENT instead, Windows converts the cursor coordinates from screen coordinates to client coordinates and passes them to the window in a WM_LBUTTONDOWN message.

The fact that an application sees mouse messages in raw form makes for some interesting possibilities. The following OnNcHitTest handler implements client-area drag by fooling Windows into thinking that the mouse is over the title bar when in fact it's over the window's client area:

 

With this OnNcHitTest handler in place, a window is as easily dragged by its client area as by its title bar. And it works even if the window doesn't have a title bar. Try it: click the left mouse button in Clock's client area, and move the mouse with the button held down. The window should go wherever the mouse goes.

Clock uses an OnNcHitTest handler similar to the one shown above. The only difference is that Clock verifies that the left mouse button is down before replacing an HTCLIENT return code with HTCAPTION so that other mouse messages—particularly right-button mouse messages that precede WM_CONTEXTMENU messages—will get through unscathed:

 

The call to ::GetAsyncKeyState checks the left mouse button and returns a negative value if the button is currently down.

 

posted @ 2011-04-02 18:01  好好学习,天天进步  阅读(286)  评论(0编辑  收藏  举报