This is a small application which emulates the behaviour of the mouse in KDE. It uses global window hooks and WTL.
In KDE (a desktop environment for UNIX operating systems), Windows can be moved and resized without having to click on Window edges or going through menus. To move a Window, simply press ALT and press left mouse button and reposition the Window by moving the mouse. To resize a Window, press the right mouse button instead, and adjust the position of the bottom right corner by moving the mouse.
I chose not to write a lengthy article about this tool mainly because the techniques I have used have already been covered on Code Project and elsewhere. The main technique I utilize is the hooking mechanism provided by Windows. A search for
SetWindowsHookEx() will give you plenty of material on that topic. When you start the application, a tray icon will appear. The icon is an image of a typical basic Microsoft mouse with a scroll wheel. You can't miss it. Right click it for Enable, Disable, About and Quit. The provided zip file contains the source code as well as precompiled binaries. The binaries have been compiled in release mode.
The application will only manipulate top level Windows, which have the
WS_THICKFRAME style set. Your child Windows and unresizable dialogs are thus safe.
New Functionality as of August 25th 2006
- ALT and scrollwheel up/forward maximizes a Window
- ALT and scrollwheel down/backward restores a Window
- ALT and middle mouse button closes a Window (
WM_CLOSE is sent)
New Functionality as of August 28th 2006
- ALT is no longer hard coded. A combination of ALT, CTRL and SHIFT is now configurable
- Windows being resized or moved may now be activated (raised to foreground), if the application has been configured for that
- Resizing is now relative to where the mouse cursor is. If you grab the top left corner, the Window will resize by moving that corner. Grab the middle of the top side, and the Window will resize by moving the top edge.
Since I'm using global hooks, antivirus programs may tell you that this application is a trojan. While I assert that it is not, you can check for yourself - the sources are in the zip file. There is a small bug, which you normally don't notice in most apps. Since I "consume" mouse clicks when the ALT-button is pressed, you will not be able to use such combinations in applications. Photoshop is one such application - you will not be able to use the ALT-button as a shortcut for zooming. I am contemplating a partial solution for it though. The plan is to see if the mouse has moved between
WM_xBUTTONUP. If it has not, I'll regenerate the first mouse
WM_xBUTTONDOWN message, followed by
WM_xBUTTONUP. This still won't help applications which want ALT + button + mouse move. There is a certain risk of addiction associated with this mouse behaviour. Once you go KDE mouse, you won't go back (unless you're a Photoshop user).
Room For Improvements
There is of course room for improvements. Apart from the "bug" described above, there are many other things one could implement. Configurability comes to mind: key bindings and "ignore lists" (to make the application ignore apps like Photoshop) would be nice. Although I'm satisfied with this application, I'd be delighted to receive enhancements.
This application and its source code is hereby put in the public domain. The icon which comes with the application is however NOT in public domain. I do not own the copyright for it.
I used Robert Edward Caldecott's excellent code for easy handling of tray icons and associated menus. You can find his article here.
- 2006-08-25: Updated source code per MrARSoft's request: Unmaximize maximized Windows when moved or resized
- 2006-08-25: Added extra functionality - scroll wheel and middle mouse button
- 2006-08-28: Configurability
- 2006-09-30: New feature: Snapping edges. Many thanks to Thomas Freudenberg for this!
Request For Help
When implementing the ability to configure the application at runtime, I discovered unwanted behaviour of shared data segments. It would seem that PODs (plain old datatypes) are initialized once in shared data segments. If I declare
int x = 0,
x is initialized with the value
0 only once. All other processes which attach to the DLL will see whatever the current state of
x is. With non-PODs, you can observe quite a different behaviour. If you declare an object variable in a shared data segment, it seems that the constructor for that object is executed for every attaching thread. It's either that or objects simply aren't shared. If you happen to know what's going on, I would appreciate a message in the message board below.
I did come up with a workaround for this little problem, but it is very inelegant, and I would love to rewrite the code, without having to resort to C-style functions.