What's It For
When you get tired of dragging the mouse back and forth between two or more big screens and you really don't care to Alt-Tab your way around umpteen applications, you
may find this tool an easier way to cover vast cursor distances in a single bound. The default "Last Position" mode will move the cursor to the last position it was at when
jumping back to a screen when a hotkey is hit. The "Same Position" mode moves the cursor on the current screen to the relative same position, or near the same position, on
the next monitor screen to the right or left when the hotkey is hit.
"Jump Right" and "Jump Left" only show a difference in behavior when you have a desktop extended across more than two monitors.
Since I am just a poor man and don't have freakish amounts of hardware, you can be the first to tell us whether this tool works on a 3 or more monitor systems. I think
it should work.
PLEASE tell me if I've wasted my time. I think I'm a fair Googler and I haven't found any Windows trick or free tool to do this. Although,
I did uncover a few shortcuts I hadn't seen before:
Desktop publishing forum: Windows Short Cuts & Hot Keys by: Dohadwala June 5, 2007.
- Win+B: Move focus to systray icons. You can use Left and Right arrow keys to move between icons. 'Enter' for left-click menu.
- Ctl+Alt+Down arrow: Rotate screen 180, Ctl+Alt+Up arrow: Rotate screen back. Really?!! Are these a gag? What is the use of these? You can tell I'm not a tablet user (remember - no freakish amounts of hardware). Operates on the screen with the cursor.
- Useful New Windows 7 HOTKEYS-Keyboard Shortcuts January 29, 2009.
- Here are a few notable shortcuts:
- Win+Left : Snap to left, Win+Right : Snap to right. Kind of neat. Works great on Win8 but this feature doesn't work on my Win7 system. Aero Flip 3D (Ctl+Win+TAB) works on my Win7 machine but I can't get Aero Snaps to work for anything.
- Win+Shift+Left : Jump to left monitor, Win+Shift+Right : Jump to right monitor. Nnnngh. Almost. Now just leave the active window behind and move the cursor instead and you have what I want. Works sensibly when the active window spans screens. Left of leftmost cycles back to rightmost and vice versa.
- Ctl+Esc : Go to Win8 Start screen. My current favorite shortcut. If you are on the Start screen, Ctl+Esc will return you to whatever you were viewing before. This will probably remain useful even in Windows 8.1, wherein Microsoft admits it was a mistake to eliminate the desktop Start ball.
Win+Page Up, Win+Page Down : Switch Metro to other screens. I am still trying to find how to extend Metro across screens. I am not sure I really want to, but I would
probably be scrolling the mousewheel Up(aka Left) and Down(aka Right) a lot less.
Parts and Pieces
I started this tool by finding
this link. I don't want a Form, Window, or Page hanging around. I wanted the smallest
desktop manifestation possible that would allow controlling a hot key to use in jumping the cursor from screen to screen, allow control of what "screen to
screen" means, and would quietly go away (Exit) when I want. This application's
ProcessIcon class plus
ContextMenus class is pretty much
all that minus the hotkey. What is a little unusual is the initial steps in this project:
- Create a new Windows Forms Application.
- Delete Form1.cs from the project.
- Open Program.cs - remove the line that reads
In place of running a Form, the Program.cs module displays a
NotifyIcon (system tray icon) and starts a
message pump to handle context menu selections (
Application.Run() with no parameter). Mark Merrens uses a
using statement to create
ProcessIcon instance and, since this class implements
IDisposable, to clean up
resources when the application exits. Here is the main part of Program.cs in that project:
using (ProcessIcon pi = new ProcessIcon())
In my case, I detect during the
ProcessIcon constructor whether the system has at least two monitor screens. If not,
terminate is set to
true. For one monitor or more than one, the
NotifyIcon is instantiated since we know
Dispose() will always
be called on exit. Here is the same section in
using (ProcessIcon pi = new ProcessIcon())
The other main part of
ScreenHopper is the hotkey used to jump the cursor. I wanted something that didn't require taking your hand off the mouse, but I couldn't use plain
mouse clicks since they are claimed by most applications and regular desktop use. Most right-handed people can locate the Left Control key without looking so I chose
Control as the default modifier. The other choices of modifier are
Alt or any combination of these you choose except the "no modifier" case
(Right Click the ScreenHopper systray icon, choose the
Hotkey menu item). The
Win key can also be a modifier but I didn't want to tempt fate.
Win key up is definitely more than a modifier.
The hotkey trigger can be any "modified" mouse button. I chose the mousewheel (middle mouse button) as default since most mice have a wheel switch
now and its use is otherwise less common.
The hotkey library I found is well-described
here. This library is perfect since it handles both global keyboard and global
mouse events (vs clicks and presses for an active, focused, non-systray app).
The most recent version (Version 3) is actually hosted on CodePlex here, but I am calling it a CodeProject project since it appeared here first (How could you leave us,
George Mamaladze? Weren't we good for you?)
A Pressing Matter
From examining the library, you would think you could detect mouse key presses in a
KeyboardHookManager. Something like:
private void HookManager_KeyDown(object sender, KeyEventArgs e)
if (e.KeyCode == Keys.LButton || e.KeyCode == Keys.MButton || e.KeyCode == Keys.RButton)
Alas, I couldn't get this to detect mouse presses. From what I can tell, keyboard hooks and mouse hooks are completely separate. You can't detect mouse buttons in
KeyEventArgs and you can't detect Ctl/Alt/Shift/ modifiers in
MouseEventArgs. What to do? Well, obviously you handle Control key, Alt key,
and Shift key
KeyUp events to set a few global variables and then use their setting when processing
MouseEventArgs. Below is my
HookManager_KeyUp handler and my
HookManager_KeyDown is the same as
HookManager_KeyUp except for setting the three globals:
altDown. The assignment statement for
modifiersDown is the same in both keyboard hook handlers. We don't need a
HookManager_MouseUp handler since we take the jump only on
detecting mouse button down events. I tried to keep processing as light as possible since these are global for all keys and mouse button events.
private void HookManager_KeyUp(object sender, KeyEventArgs e)
if (e.KeyCode == Keys.LShiftKey || e.KeyCode == Keys.RShiftKey)
shiftDown = false;
else if (e.KeyCode == Keys.LControlKey || e.KeyCode == Keys.RControlKey)
controlDown = false;
else if (e.KeyCode == Keys.LMenu || e.KeyCode == Keys.RMenu)
altDown = false;
modifiersDown = (shiftDown == shiftChecked) &&
(controlDown == controlChecked) && (altDown == altChecked);
private void HookManager_MouseDown(object sender, MouseEventArgs e)
if ((e.Button == MouseButtons.Left && mouseLeftSelected) ||
(e.Button == MouseButtons.Middle && mouseWheelSelected) ||
(e.Button == MouseButtons.Right && mouseRightSelected))
I would go over the
JumpCursor method, but it's really just a bunch of
else's. This project at least shows how to handle combining mouse and
keyboard events to effect mouse clicks with modifiers. I've found the "Last Position" mode more natural to me. If you prefer
the "Same Position" mode as the default, change the initial assignment of
You can start more than one
ScreenHopper. Nothing bad happens but they make confusing hops or no hop (Same same).
ScreenHopper works when one monitor is desktop
and one is Metro.
- First submission to CodeProject, June 2013
- Update submitted Jun 21, 2013. Failed to imagine negative screen bounds. Fixed for primary screen on right.