ZoomPowr: Full screen zooming/inverting utility

In a past blog entry I briefly mentioned a full screen zoomer that I’d written to replace the hardware zoom I enjoyed when I had a Matrox card in my system a few years back.

After some email showing interest in it, I’ve cleaned it up and named it zoompowr (thanks for the name Dave). It now has global hotkey support and lives in the system tray rather than launching “on demand” from a shortcut key.

Its very easy to use. CTRL-ALT-Z cycles the zoom level and CTRL-ALT-A toggles invert. I’ve set my Logitech MX400 mouse to send a CTRL-ALT-Z when I depress the scroll wheel. This then cycles between 3 zoom levels and no zoom. I’ve found that pressing “A” while holding the scroll wheel down is enough to toggle the invert.

How It Works

Whilst adding semi-transparent window support to Planimate® a few years back, I’d discovered that windows with the WS_EX_LAYERED style did not appear in software like VNC. It was like they were not there. This intrigued me.

It turns out that transparent windows are composited in a separate buffer to the desktop window and the two are then combined to the actual display hardware. I’d thought only Vista did that.

This got me thinking – what if I cover the desktop with an opaque window with the WS_EX_LAYERED style and then periodically blit from GetDesktopWindow() to my window.

The result was that I had a “real time” zoomer. A bit of code to track the mouse cursor (see below), set up hotkeys and alter the blit for invert was all that was needed to whip up a zooming app.

The technique does have a few drawbacks:

  • Applications which use transparent windows (or set the WS_EX_LAYERED flag for no good reason…) wont appear when zooming/inverting.
  • Popup menus appear briefly “real size” before they get zoomed. I have my zoomer continually resetting itself as the foreground window but as popup menus are drawn in the foreground, they briefly flicker when popping up.
  • Task bar tool tips don’t get zoomed (probably the OS transparency for them).
  • This technique isn’t supported by Win2K.
  • I’ve set a slow update rate of about 10 frames/second to avoid hogging the CPU – not suitable for games.
  • This does not zoom the overlay buffer used for video playback.

Most of these issues are mitigated for me given all I do on the host is run virtual machines. All the contents of the VM windows then zoom perfectly, even full screen console windows.

To avoid mouse cursor complexities, I set up the zooming so the zoomed region is positioned such as the mouse cursor is in the same screen position at any zoom level. The co-ordinate math for this ended up being easier than I expected and it means you can change zoom levels without the mouse “jumping” or losing its relative position to the content it has been positioned over.

An interesting issue I had with it was a flicker when the WS_EX_LAYERED flag was first applied. This would create a single frame of junk due to the offscreen buffer for the window being in an indeterminate state. I fixed this by setting the window transparency to 0 (fully transparent) for the first “frame” before setting WS_EX_LAYERED for the window, then setting its transparency to 255 (opaque). This made transitioning from non zoomed to zoomed modes flickerless.

I turn off the layering if there is no zoom or invert so the zoomer has negligble system impact when sitting idle. I’ve had experience with other apps that turn on layering even if they are not using transparency at the time. This is very frustrating as it wastes a lot of CPU and video bus time. This is not good if the application is doing something realtime … say VOIP.

I’ve placed a copy of my app here if you want to try it. Please note that this is freeware and I take no responsibility for what this app might do on your system. Take usual precautions when downloading applications from the internet.