65.9K
CodeProject 正在变化。 阅读更多。
Home

ScreenHopper

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.96/5 (7投票s)

2013年6月15日

CPOL

6分钟阅读

viewsIcon

23948

downloadIcon

472

一个 CodeProject 聚合器,提供热键,可在多显示器系统上将光标从一个屏幕跳转到另一个屏幕。

Image of ScreenHopper tool

有什么用

当您厌倦了在两个或更多大屏幕之间来回拖动鼠标,并且您根本不想通过 Alt-Tab 切换无数个应用程序时,您可能会发现此工具可以更轻松地一次性跨越巨大的光标距离。默认的“最后位置”模式将在按下热键切换回屏幕时将光标移动到上次所在的位置。“相同位置”模式将在按下热键时将光标移动到当前屏幕上下一个监视器屏幕(向右或向左)上的相对相同或接近的位置。

“向右跳”和“向左跳”仅在您的桌面扩展到三个或更多显示器时才显示出行为差异。由于我只是个穷人,没有那么多硬件,所以您可以第一个告诉我们这个工具是否适用于 3 个或更多显示器的系统。我认为它应该可以工作。

尽职调查

请告诉我我是否浪费了时间。我认为我是一个不错的谷歌搜索者,而且我没有找到任何 Windows 技巧或免费工具可以做到这一点。不过,我确实发现了一些我以前没见过的快捷方式

  • 桌面出版论坛:Windows 快捷方式和热键 作者:Dohadwala 2007 年 6 月 5 日。
  • Win+B:将焦点移至系统托盘图标。您可以使用左右箭头键在图标之间移动。“Enter”用于左键单击菜单。
  • Ctl+Alt+向下箭头:屏幕旋转 180 度,Ctl+Alt+向上箭头:屏幕旋转回来。真的吗?!!这些是玩笑吗?有什么用?您可以看出我不是平板电脑用户(请记住 - 没有那么多硬件)。在带有光标的屏幕上操作。
  • Windows 7 的有用新热键/键盘快捷键 2009 年 1 月 29 日。
  • 以下是一些值得注意的快捷方式
    • Win+左:吸附到左侧,Win+右:吸附到右侧。还挺不错的。在 Win8 上效果很好,但此功能在我的 Win7 系统上不起作用。Aero Flip 3D (Ctl+Win+TAB) 在我的 Win7 机器上可用,但我无法让 Aero Snaps 起作用。
    • Win+Shift+左:跳到左侧显示器,Win+Shift+右:跳到右侧显示器。嗯。差不多了。现在只留下活动窗口,然后移动光标,您就得到了我想要的。当活动窗口跨越屏幕时,效果很好。最左侧的左侧会循环回到最右侧,反之亦然。
    • Ctl+Esc:转到 Win8 开始屏幕。我目前最喜欢的快捷方式。如果您在开始屏幕上,Ctl+Esc 会返回您之前正在查看的内容。这很可能在 Windows 8.1 中仍然有用,微软承认在 Windows 8.1 中取消桌面开始球是一个错误。
    • Win+Page Up,Win+Page Down:将 Metro 切换到其他屏幕。我仍在尝试找到如何在屏幕之间扩展 Metro。我不确定我是否真的想要,但我可能会少滚很多鼠标滚轮(向上/向下)。

零件和组件

我开始这个工具是找到了这个链接。我不想有任何窗体、窗口或页面在后台运行。我想要尽可能小的桌面显示,能够通过热键控制光标在屏幕之间跳转,能够控制“屏幕到屏幕”的含义,并且在我需要时可以悄悄地消失(退出)。这个应用程序的 ProcessIcon 类加上 ContextMenus 类基本上就是这些,除了热键。有点不寻常的是这个项目中的初步步骤

  1. 创建一个新的 Windows 窗体应用程序。
  2. 从项目中删除 Form1.cs
  3. 打开 Program.cs - 删除那行写着 Application.Run(new Form1()); 的代码。

与其运行一个窗体,不如让 Program.cs 模块显示一个 ProcessIconNotifyIcon(系统托盘图标),并启动一个消息循环来处理上下文菜单选择(没有参数的 Application.Run())。Mark Merrens 使用一个 using 语句来创建 ProcessIcon 实例,并且由于该类实现了 IDisposable,因此在应用程序退出时会清理资源。这是该项目中 Program.cs 的主要部分

// Show the system tray icon.
using (ProcessIcon pi = new ProcessIcon())
{
	pi.Display();

	// Make sure the application runs!
	Application.Run();
}

在我的情况下,我在 ProcessIcon 构造函数中检测系统是否至少有两个显示器屏幕。如果没有,则将 public 成员 terminate 设置为 true。对于一个或多个显示器,会实例化 NotifyIcon,因为我们知道退出时总是会调用 Dispose()。这是 ScreenHopperProgram.cs 中相同的部分

// Show the system tray icon.
using (ProcessIcon pi = new ProcessIcon())
{
	if (pi.terminate)
	{
		return;
	}
	pi.Display();

	// Make sure the application runs!
	Application.Run();
}

ScreenHopper 的另一个主要部分是用于跳转光标的热键。我想要一些不需要把手从鼠标上移开的东西,但我无法使用纯鼠标点击,因为它们被大多数应用程序和常规桌面使用所占用。大多数习惯用右手的人可以在不看的情况下找到左 Control 键,所以我选择 Control 作为默认修饰键。其他修饰键的选择是 ShiftAlt,或者您可以选择它们的任何组合,但排除“无修饰键”的情况(右键单击 ScreenHopper 系统托盘图标,选择 Hotkey 菜单项)。Win 键也可以是修饰键,但我不想冒险。Win 键按下绝对不仅仅是修饰键。

热键触发可以是任何“修饰过的”鼠标按钮。我选择鼠标滚轮(中键)作为默认值,因为大多数鼠标现在都有滚轮开关,而且它的使用通常较少。

我找到的热键库在这里得到了很好的描述。这个库非常完美,因为它同时处理全局键盘和全局鼠标事件(而不是针对活动的、有焦点的、非系统托盘应用程序的单击和按下事件)。

最新版本(第 3 版)实际上托管在 CodePlex 这里,但我称之为 CodeProject 项目,因为它首先出现在这里(你怎么能离开我们,George Mamaladze?我们对你不好吗?)

紧迫的问题

通过检查该库,您会认为您可以在 KeyboardHookManager 中检测鼠标按键。类似这样

private void HookManager_KeyDown(object sender, KeyEventArgs e)
{
    if (e.KeyCode == Keys.LButton || e.KeyCode == Keys.MButton || e.KeyCode == Keys.RButton)
        DoSomething();
}

唉,我无法让它检测鼠标按键。据我所知,键盘钩子和鼠标钩子是完全独立的。您无法在 KeyEventArgs 中检测鼠标按钮,也无法在 MouseEventArgs 中检测 Ctl/Alt/Shift/ 修饰键。该怎么办?好吧,显然您处理 Control 键、Alt 键和 Shift 键的 KeyDown KeyUp 事件来设置一些全局变量,然后在处理 MouseEventArgs 时使用它们。下面是我的 HookManager_KeyUp 处理程序和我的 HookManager_MouseDown 处理程序。HookManager_KeyDownHookManager_KeyUp 相同,只是设置三个全局变量:shiftDowncontrolDownaltDownmodifiersDown 的赋值语句在两个键盘钩子处理程序中都相同。我们不需要 HookManager_MouseUp 处理程序,因为我们只在检测到鼠标按钮按下事件时进行跳转。我尽量保持处理尽可能轻量,因为这些是所有按键和鼠标按钮事件的全局事件。

// Handles all Key Up events.  Filter modifier changes.  Evaluate modifiersDown for mouse clicks
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) //for Menu read Alt
        altDown = false;
    else
        return;

    modifiersDown = (shiftDown == shiftChecked) &&
    (controlDown == controlChecked) && (altDown == altChecked);
}

private void HookManager_MouseDown(object sender, MouseEventArgs e)
{
    if (!modifiersDown)
        return;
    if ((e.Button == MouseButtons.Left && mouseLeftSelected) ||
        (e.Button == MouseButtons.Middle && mouseWheelSelected) ||
        (e.Button == MouseButtons.Right && mouseRightSelected))
    {
        JumpCursor();
    }
}

摘要

我本可以详细介绍 JumpCursor 方法,但它实际上只是一堆 if-then-else 语句。这个项目至少展示了如何处理组合鼠标和键盘事件来实现带修饰键的鼠标点击。我发现“最后位置”模式对我来说更自然。如果您更喜欢将“相同位置”模式作为默认设置,请将 lastPosition 的初始赋值更改为 false

您可以启动多个 ScreenHopper。不会发生什么坏事,但它们会进行令人困惑的跳转或不跳转(相同相同)。ScreenHopper 在其中一个显示器是桌面而另一个是 Metro 时工作。

历史

  • 首次提交到 CodeProject,2013 年 6 月
  • 2013 年 6 月 21 日提交更新。  未能想象负屏幕边界。已修复主屏幕在右侧的情况。
© . All rights reserved.