Jump to content

Dragging a window from it's client area (without loosing mouse event processing)


Recommended Posts

I have created a window using CreateWindowEx that is borderless and has no caption. I would like to be able to move the window by left-click + hold the mouse over the client area of that window (that is to be able to drag it).

I have added the following code to the WindProc of this window:

static LRESULT hittest;

...

case WM_LBUTTONDBLCLK:

DestroyWindow(hWnd);

break;



case WM_NCHITTEST:

hittest = DefWindowProc(hWnd, message, wParam, lParam);

if (hittest == HTCLIENT)

return HTCAPTION;

else

return hittest;

break;

...

Although the previous code let me drag the window correctly I have lost the ability to process any other mouse events (like double clicking, clcik, etc.). Whithout the case WM_NCHITTEST statement the window does let to close the window by double clicking on it; but, if I add the case WM_NCHITTEST then the WM_LBUTTONDBLCLK is never sent to the window.

What I intend to do is:

- Being able to drag the window from anywhere inside it's client area.

- Spawn an application (via ShellExcecuteEx) when the user clicks on an image (drawn) inside the windows's client area.

- Close the window when the user double-clicks on anywhere inside the window's client area.

Is there a way to enable the drag without loosing mouse message processing? I have read a bit about Mouse Capturing but I have not been able to successfully implement that.

Are threre any tutorials or docs I can take a look at as to implement the desired behaviour I am looking for?

Link to post

You can try this instead:

- On mouse down, store X and Y.

- On mouse move, manually SetWindowPos your window.

- On mouse up, check if X and Y changed. Or maybe you can set a flag on mouse move.

int drag_x, drag_y, drag, can_drag = 0; // global variables

...
case WM_LBUTTONDOWN:
drag = 0;
drag_x = LOWORD(lParam);
drag_y = HIWORD(lParam);
can_drag = 1; // Maybe he'll drag the window
break;

case WM_MOUSEMOVE:
if (can_drag) { // Did he press mouse button?
// Yes? then he's dragging the window
drag = 1;
RECT rect;
GetWindowRect (hwnd, &rect);
SetWindowPos (hwnd, 0, rect.Left-drag_x+LOWORD(lParam), rect.Top-drag_y+HIWORD(lParam), 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
}
break;

case WM_LBUTTONUP:
can_drag = 0;
if (!drag) {
// Hey it's just a click! do something
}

...

You should incorporate mouse capture in LBUTTONDOWN and release the capture in LBUTTONUP. I'm not sure if using mouse capture will impede you from receiving double clicks. If such thing happens, you'll need a timer instead (or a separate thread) monitoring the mouse with GetCursorPos.

Link to post

@matonga,

Thanks again for your help... your code worked just fine... specially since I decided not to go for the click/double click behaviour. Again this is for my dilbert docklet and after giving a second thought it seemed unnatural to doubleclick to close the window... I will do that by clicking on the docklets icon again.

@herd, thanks for your commentary... do you happen to know a link that explains that API a bit clearer? I read the MSDN docs but could not get the whole picture there... Is this function supposed to replace all manual code as in matonga's sample?

Thank you both... you have been now... and in the past a great help!

Link to post

DragDetect simplifies matonga's code somewhat.

You'll still need to handle mousemove.

However, not every click stays on the same pixel, so there is a margin of error tweaked at the control panel to tell a wobbly click from a real drag attempt or a wobbly double-click. DragDetect will take care of that by asking GetSystemMetrics for the width and height of the drag rectangle, monitor if the mouse stays inside this wobbliness allowance rectangle (for any amount of time) and (if I remember correctly) consume the mouseup event to return FALSE in both of these cases. Once the mouse leaves this rectangle, it'll return TRUE, you'll get mousemove events and a mouseup event.

Of course, if you answer the hittest with "I entirely consist of a caption bar" the system will indeed consume the double-click for its own everyday purposes.

Answer for yourself: What does a caption bar do when you do a double-click on it? (Hint: resizable window)

hth,

herd

Link to post

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
×
×
  • Create New...