пятница, июля 29, 2005

Alt-drag in Windows

Unix window managers let you move windows around by pressing the Alt key, clicking on any area within the window and moving the mouse around.

It is a feature I miss in Windows ever since I started using Linux extensively a year ago. Enlightened by how quickly I could hack up a Cmd key remapper for my Apple keyboard, I'm now exploring the possibility of implementing alt-drag in Windows.

I discovered Win32WM, a GPL program by Matti Jagula that lets you drag and resize windows with the alt key plus implements some shortcuts for Window manipulation, like Win+V = Maximize vertically.

Alas, its implementation of Alt-drag is far from perfect. He polls the state of the Alt key continuously and then updates the window's position with SetWindowPos. The application still receives the alt press and the button click, and it doesn't work in all cases.

I'm looking for a solution that uses standard Windows dragging routines and hides the mouse click & drag from the application. If I could intercept the WM_LBUTTONDOWN or maybe WM_NCHITTEST before it reaches the application and send back my own reply, that would be ideal. But how?

There's SetWindowsHookEx (WH_CALLWNDPROC, ...). But it only lets you watch the messages as they go by, not modify them. I could use SetWindowsHookEx(WH_MOUSE_LL, ...) to intercept the mouse button press and hide it from the application, but how do I tell Windows to initiate a drag?

Of course I could always fall back to home-grown dragging routines based on SetWindowPos/MoveWindow, but that's a big hack and it will ignore your "Show window contents while dragging" preference (not that I use it even on remote desktops).