Help for Tune Smithy Koch snowflake icon.gif

How to let user click and drag anywhere on window or dialog to move it

From Tune Smithy

(Difference between revisions)
Jump to: navigation, search
Line 1: Line 1:
 +
[[C-code]]
 +
Here the idea is you have a dialog or window with no title bar and want user to be able to move it around on the screen with click and drag. Or maybe it has a title bar but you still want user to be able to use click and drag anywhere on the window to move it.
Here the idea is you have a dialog or window with no title bar and want user to be able to move it around on the screen with click and drag. Or maybe it has a title bar but you still want user to be able to use click and drag anywhere on the window to move it.

Revision as of 09:39, 23 February 2010

C-code

Here the idea is you have a dialog or window with no title bar and want user to be able to move it around on the screen with click and drag. Or maybe it has a title bar but you still want user to be able to use click and drag anywhere on the window to move it.

This is dead simple when you know how, though you can struggle for ages if you don't know the trick.

Windows sends your window or dialog a WM_NCHITTEST to detect the various parts of the window such as the resizing borders, or title bar etc. To let the user move the window with click and drag, just tell Windows that everything is the title bar.

For a normal window made using e.g. CreateWindow with a DefWindowProc(..) you do it like this:

switch (message)
 {
 case WM_NCHITTEST:
  {
    POINT pt;
    RECT rcClient;
    GetCursorPos(&pt);
    GetClientRect(hDlg,&rcClient);
    ClientToScreenRect(hDlg,&rcClient);
    if(PtInRect(&rcClient,pt))
     return HTCAPTION;
  }
  break;
 }

Or alternatively call DefWindowProc for the message, and check to see if its return value is HTCLIENT and if so return HTCAPTION.

You might think you could just return HTCAPTION whatever happens - but there are many other possible return values to show e.g. that the mouse is in the Close button, or over one of the resizing borders of the dialog etc.

If it is a dialog you need to do it like this:

switch(message)
 {
 case WM_NCHITTEST:
  {
   POINT pt;
   RECT rcClient;
   GetCursorPos(&pt);
   GetClientRect(hDlg,&rcClient);
   ClientToScreenRect(hDlg,&rcClient);
   if(PtInRect(&rcClient,pt))
   {
    //Because it is a dialog need to do it this way and return 1
    SetWindowLong(hDlg,DWL_MSGRESULT,HTCAPTION);
    return 1;
    // For a normal window would use:
    // return HTCAPTION;
   }
  }
  break;
 }

That's because you just return 1 to show that the message is processed, and with no DefWindowProc you need to use SetWindowLong with DWL_MSGRESULT to supply Windows with the return value.

The click and drag will only work for static text areas of the window or blank background areas - as you would want it to - you don't want the window to move when the user just wants to click and drag to highlight text for instance.

You don't need to worry about any editable text areas or buttons or other controls e.g. custom controls or whatever in the window - as they are on top of it, then they will catch the WM_NCHITTEST before it gets to the dialog proc.

Personal tools
Namespaces
Variants
Actions
Navigation
How to use the wiki
More
Toolbox