Wm_nchittest has 21 kinds of values, commonly used with htcaption,htclient,htborder,htsysmenu,httransparent, lists all the use of the VCL in the case

Source: Internet
Author: User

I used the WM_NCHITTEST message to move a form without a title bar, which is probably as follows:

In general, we drag the title bar of the dialog window to move the window, but sometimes we want to move the window by dragging the mouse over the client area.

An easy-to-think scenario is to handle mouse messages Wm_lbuttondown and wm_lbuttonup. In the OnLButtonUp function to calculate the change in the mouse position, call MoveWindow to implement the window movement.

Note that when you drag the title bar to move the window, a rectangular box appears, prompting the current position of the window to move. When the left mouse button is released, the window moves to the position of the rectangle box. We do not have this capability in our implementation scenario.

To implement this function, we have to draw these rectangles ourselves.

In fact, we don't have to do it ourselves, because Windows has done it for us.

Imagine if I could cheat windows and tell it now that the mouse is dragging the title bar instead of the client area, then Windows will do the work.

To deceive windows is not as difficult as imagined, even very simple.

We use a message: Wm_nchittest.

The MSDN explanation for it is:

The wm_nchittest message is sent to a window when the cursor moves, or if a mouse button is pressed or released . If the mouse is not captured, the message was sent to the window beneath the cursor. Otherwise, the message is sent to the window, which has captured the mouse.

The message is sent when the mouse moves or the mouse button is pressed.

What does windows do with this message? "HITTEST" is the meaning of "hit test", the WM_NCHITTEST message is used to get the position of the mouse's current hit.

WM_NCHITTEST's message response function determines which part of the window the mouse is hitting according to the current coordinates of the mouse, and the return value of the message response function indicates the location, for example, it may return htcaption, or htclient, and so on. (There are many return values, please refer to MSDN).

For the sake of understanding, let me first describe the response process of Windows to mouse button presses:

1. Determines which window the mouse button is clicked on. Windows uses the table to record the area coordinates of each window on the current screen, and when the mouse driver notifies windows that the mouse button is pressed, Windows determines which window it clicks based on the coordinates of the mouse.

2. Determines which part of the window the mouse button is clicked on. Windows sends a WM_NCHITTEST message to the mouse-clicked window to ask what part of the window the mouse button clicked on. (The return value of the WM_NCHITTEST message response function notifies Windows). Generally speaking, wm_nchittest messages are handled by the system, and the user generally does not take the initiative to deal with it (that is, the WM_NCHITTEST message response function usually takes the Windows default handler function).

3. According to the mouse button click on the part of the window to send the corresponding message. For example, if the return value of the WM_NCHITTEST message response function is htclient, indicating that the mouse is clicked on the client area, Windows sends a WM_LBUTTONDOWN message to the window if wm_ The return value of Nchittest's message response function is not htclient (possibly Htcaption, htclose, Htmaxbutton, etc.), which is the non-client area of the mouse click, and Windows sends a WM_NCLBUTTONDOWN message to the window.

We need to discuss it in detail: if the return value of Wm_nchittest's message response function is htcaption, that indicates that the mouse clicked on the title bar, and then what about Windows processing?

As mentioned above, next, Windows sends a WM_NCLBUTTONDOWN message to the window.

MSDN's description of the Wm_nclbuttondown message is as follows:

Wm_nclbuttondown

Nhittest = (INT) WParam; Hit-test value

pts = makepoints (LParam); Position of cursor

Wm_nclbuttondown's wparam indicates the window part of the mouse click, lparam indicates the current mouse coordinates.

If the application does not respond to the message, it is handled by the system by default.

What does the system default handle? System Discovery wparam indicates that the mouse click is the title bar, it will identify the current window is in a "drag state" (Windows internal records the status information of each window). Since the "drag state" is identified, your mouse movement condition is completely tracked by Windows until the mouse button is released from this moment. It moves the window "synchronously", depending on the movement of the mouse.

Note that during this process, the window does not receive the Wm_ncmousemove message because the window and mouse are "synchronized" and your mouse is still relative to the window.

But the problem also appeared, I would like to right-click on this form to pop up a menu, when I finished msg_wm_rbuttondown this message, found that the form does not receive this message, the implementation of the WM_NCHITTEST message can be removed, see a reason is:

Because you processed the mouse message in the wm_nchittest, positioning him as a htcaption, that is, the mouse in the title bar, and the title bar belongs to the non-client area (NC);
Event messages for non-client areas begin with WM_NC. In other words, when your wm_nchittest returns to Htcaption, you can use WM_LBUTTONUP to process the message, you can only use Wm_nclbuttonup to handle.

Workaround:

Handles Wm_nchittest and wm_ncrbuttonup simultaneously, without processing wm_rbuttonup

Http://www.cnblogs.com/GnagWang/archive/2010/09/12/1824394.html

-----------------------------------------------------------------------

· Htborder on the border of a window that does not have a variable-size border.
· Htbottom the bottom of the horizontal border of the window.
· Htbottomleft in the lower-left corner of the window border.
· Htbottomright in the lower-right corner of the window border.
· Htcaption in the title bar.
· Htclient is in the customer area.
· Hterror on the divider between the screen background or window (same as Htnowhere, except that the Defwndproc function in Windows produces a system beep to indicate an error).
· Htgrowbox in the Dimensions box.
· Hthscroll on the horizontal scroll bar.
· Htleft on the left border of the window.
· Htmaxbutton on the Maximize button.
· Htmenu in the menu area.
· Htminbutton on the Minimize button.
· Htnowhere the divider between the screen background or window.
· Htreduce on the Minimize button.
· Htright on the right border of the window.
· Htsize in the Dimensions box. (Same as Htgrowbox)
· Htsysmenu on the Close button of the Control menu or child window.
· The httop is above the horizontal border of the window.
· Httopleft in the upper-left corner of the window border.
· Httopright in the upper-right corner of the window border.
· The httransparent is in a window that is covered by another window.
· The Htvscroll is in the vertical scroll bar.
· Htzoom on the Maximize button.

http://blog.csdn.net/harvic880925/article/details/9785439
http://zhouqingfeidie.blog.163.com/blog/static/301717722011112005828716/

---------------------------------------------------------------------

Use of VCL:

procedureTcontrol.cmhittest (varmessage:tcmhittest);beginMessage.result:=htclient; //usually forwarded to Tcontrol, are located in the customer area End;procedureTwincontrol.wmnchittest (varmessage:twmnchittest);begin   withMessage Do    if(csdesigninginchComponentstate) and(Fparent <>Nil) ThenResult:= when the htclient//component is in the design state, it is counted as the customer area Else      inherited;End;procedureTwincontrol.wndproc (varmessage:tmessage);varForm:tcustomform;begin   CaseMessage.msg ofWm_setfocus:beginForm:=getparentform (self); if(Form <>Nil) and  notForm.setfocusedcontrol (self) ThenExit; End; Wm_killfocus:ifCsfocusinginchControlState ThenExit; Wm_nchittest:begin        inheritedWndProc (Message); //General delegate to parent class function processing if(Message.result = httransparent) and(Controlatpos (ScreenToClient (Smallpointtopoint) (Twmnchittest (Message). Pos)), False)<>Nil) ThenMessage.result:=htclient;        //But if the parent class's processing result is transparent, it is re-tested and counted in the customer area      Exit; End; Wm_mousefirst. Wm_mouselast:begin        ifMessage.msg = Wm_lbuttonup Then        begintag:= -; End; ifIscontrolmousemsg (Twmmouse (Message)) Then      begin        {Check handleallocated because Iscontrolmousemsg might have freed the window if user code executed something Like Parent: = nil. }        if(Message.result =0) andhandleallocated ThenDefWindowProc (Handle, Message.msg, Message.wparam, Message.lparam);      Exit; End; End; Wm_keyfirst. Wm_keylast:ifDragging ThenExit; Wm_cancelmode:if(GetCapture = Handle) and(Capturecontrol <>Nil) and(Capturecontrol.parent= self) ThenCapturecontrol.perform (Wm_cancelmode,0,0); End; inheritedWndProc (Message);End;procedureTwincontrol.wmsetcursor (varmessage:twmsetcursor);varCursor:tcursor;  Control:tcontrol; P:tpoint;begin   withMessage Do    ifCursorwnd = Fhandle Then       CaseSmallint (HitTest)of //where hittest is the word type data that comes with the TWMSETCURSOR message structure htclient: //If located in the customer area, a series of processing, including changing the cursor and further testing beginCursor:=Screen.cursor; ifCursor = Crdefault Then            beginGetCursorPos (P); Control:=Controlatpos (ScreenToClient (P), False); if(Control <>Nil) Then                ifCsdesigninginchControl.componentstate ThenCursor:=CrarrowElseCursor:=Control.fcursor; ifCursor = Crdefault Then                ifCsdesigninginchComponentstate ThenCursor:=CrarrowElseCursor:=Fcursor; End; ifCursor <> Crdefault Then            beginwindows.setcursor (Screen.cursors[cursor]); Result:=1;            Exit; End; End; Hterror: //If the test is wrong, set the current program to the front window and exit the test (to facilitate further testing) if(mousemsg = wm_lbuttondown) and(Application.handle <>0) and(GetForegroundWindow<> Getlastactivepopup (Application.handle)) Then          beginApplication.bringtofront;          Exit; End; End; inherited;End;procedureTwincontrol.cmcursorchanged (varmessage:tmessage);varP:tpoint;begin  ifGetCapture =0  Then  beginGetCursorPos (P); ifFinddragtarget (P, False) = self ThenPerform (Wm_setcursor, Handle, htclient); //When the mobile destination control is the current win control, it sends the message that sets the focus, and passes handle and htclient for further processing End;End;

There are also cases of cm_hittest treatment:

functionTwincontrol.controlatpos (ConstPos:tpoint; Allowdisabled, Allowwincontrols:boolean): Tcontrol;varI:integer;  P:tpoint;  Lcontrol:tcontrol; functionGetcontrolatpos (Acontrol:tcontrol): Boolean; begin     withAcontrol Do    beginP:= Point (Pos.x-left, Pos.y-Top); Result:= PtInRect (Clientrect, P) and((csdesigninginchComponentstate) and(Visibleor                 not(csnodesignvisibleinchControlStyle))or(Visible and(Enabledorallowdisabled) and(Perform (Cm_hittest,0, Longint (Pointtosmallpoint (P))) <>0))); //In the VCL internal test, whether the current test point is in the current control area (using the function return value) ifResult ThenLcontrol:=Acontrol; End; End;beginLcontrol:=Nil; ifAllowwincontrols and(Fwincontrols<>Nil) Then     forI: = Fwincontrols.count-1 Downto 0  Do      ifGetcontrolatpos (Fwincontrols[i]) ThenBreak ; if(Fcontrols <>Nil) and(Lcontrol=Nil) Then     forI: = Fcontrols.count-1 Downto 0  Do      ifGetcontrolatpos (Fcontrols[i]) ThenBreak ; Result:=Lcontrol;End;

A further summary is needed ...

Wm_nchittest has 21 kinds of values, commonly used htcaption,htclient,htborder,htsysmenu,httransparent, list all the VCL in the use of the situation

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.