在Delphi中可以禁用W7中的任务切换键盘快捷方式吗?

10

我的应用程序已经有了一个模式多年,客户可以“禁用对操作系统的访问”。显然,这种功能违反了潮流(至少在Windows方面如此),但是有些安装中,我的应用程序是唯一应该对机器操作员可见的程序,在这种情况下,这样的功能非常有用。

我使用的技巧由几个“层”构成:

  1. 隐藏任务栏和按钮。
  2. 禁用任务切换。
  3. 禁用我的主窗体系统图标。

为了禁用任务栏,我使用了:

// Get a handle to the taskbar and its button..
Taskbar := FindWindow('Shell_TrayWnd', Nil);
StartButton := FindWindow('Button', Nil);

// Hide the taskbar and button
if Taskbar <> 0 then
  ShowWindow( Taskbar, SW_HIDE );
if StartButton <> 0 then
  ShowWindow( StartButton, SW_HIDE );

// Set the work area to the whole screen
R := Rect( 0,0,Screen.Width,Screen.Height );
SystemParametersInfo(
  SPI_SETWORKAREA,
  0,
  @R,
  0 );

这在W7上运行良好,看起来依然可用。几年前,研究如何禁用任务切换时,唯一的技术是“假装”你的应用程序是屏幕保护程序(除了像将应用程序重命名为“explorer.exe”并引导到它之类的可怕事情):

procedure EnableTaskSwitching( AState : boolean );
// Enables / disables task switching
begin
  SystemParametersInfo(
    SPI_SCREENSAVERRUNNING,
    Cardinal( not AState),
    nil,
    0 );
end;

毫不奇怪的是这种方法在Windows 7中似乎没有效果(我认为它在XP等其他版本中有效)。 有没有人知道另一种更好的方法来禁用/启用Alt-Tab(和其他特殊的Windows键)?


2
那么Ctrl-Alt-Del呢? - Remko
4个回答

12

如果找到解决方案:

function LowLevelKeyboardProc(nCode: integer; wParam: WPARAM; lParam: LPARAM):
  LRESULT; stdcall;
type
  PKBDLLHOOKSTRUCT = ^TKBDLLHOOKSTRUCT;
  TKBDLLHOOKSTRUCT = record
    vkCode: cardinal;
    scanCode: cardinal;
    flags: cardinal;
    time: cardinal;
    dwExtraInfo: Cardinal;
  end;

  PKeyboardLowLevelHookStruct = ^TKeyboardLowLevelHookStruct;
  TKeyboardLowLevelHookStruct = TKBDLLHOOKSTRUCT;
const
  LLKHF_ALTDOWN = $20;
var
  hs: PKeyboardLowLevelHookStruct;
  ctrlDown: boolean;
begin

  if nCode = HC_ACTION then
  begin

    hs := PKeyboardLowLevelHookStruct(lParam);
    ctrlDown := GetAsyncKeyState(VK_CONTROL) and $8000 <> 0;
    if (hs^.vkCode = VK_ESCAPE) and ctrlDown then
      Exit(1);
    if (hs^.vkCode = VK_TAB) and ((hs^.flags and LLKHF_ALTDOWN) <> 0) then
      Exit(1);
    if (hs^.vkCode = VK_ESCAPE) and ((hs^.flags and LLKHF_ALTDOWN) <> 0) then
      Exit(1);
    if (hs^.vkCode = VK_LWIN) or (hs^.vkCode = VK_RWIN) then
      Exit(1);

  end;

  result := CallNextHookEx(0, nCode, wParam, lParam);

end;

procedure TForm1.FormShow(Sender: TObject);
begin
  SetWindowsHookEx(WH_KEYBOARD_LL, @LowLevelKeyboardProc, 0, 0);
end;

这将禁用(正如您所看到的!)

  • Ctrl+Esc(显示开始菜单)
  • Alt+Tab(任务切换)
  • Alt+Esc(任务切换)
  • Win(显示开始菜单)
  • Win+Tab(3D任务切换)
  • Win+D,Win+M,Win+Space,Win+Arrows,Win+P,Win+U,Win+E,Win+F,Win+Digit,...
  • 几乎包括Windows键的任何组合(但不是全部,例如Win+L)

1
@Andreas,你有检查所有Win+键的组合吗?根据我的经验,有些组合是无法拦截的(例如Win-L)。 - Eugene Mayevski 'Callback
1
@Eugene:哦,我的错。出于安全原因,Win+L当然会被处理得不同。但是我的建议仍然成立,只需用“几乎全部”替换“全部”。感谢您指出这一点! - Andreas Rejbrand
1
@Andreas:该代码无法捕获Ctrl-Alt-Del,而这可以用来启动任务管理器,进而启动其他应用程序来关闭您的良好钩子。 - Jeroen Wiert Pluimers
@Jeroen:我知道。但至少它回答了这个问题的标题... - Andreas Rejbrand
1
难道没有“组策略”设置来处理很多这些问题吗?Brian,请查看Server Fault,了解系统管理员如何使用操作系统设置锁定计算机,而不是依靠软件供应商为每个软件包单独进行设置。 - Rob Kennedy
现在我已经连续收到了四个踩的反对。显然我让某人不高兴了。很抱歉,但由于我不知道你是谁,我也不知道我做错了什么。 - Andreas Rejbrand

6

正如David所指出的,这被称为“Kiosk Mode”(展示模式)。关于此主题有一些不错的文章(第一部分第二部分)可以在About.com上找到。


使用第一个链接中的技巧不起作用:Windows 7 不再允许您以那种方式捕获 Ctrl-Alt-Del。第二个链接要求您替换 Gina.dll,这将替换完整的登录界面(包括任何第三方工具,例如启用指纹登录),这可能会带来很大的问题。 - Jeroen Wiert Pluimers
@Jeroen,“kiosk mode”通常意味着对系统的完全控制,因此替换GINA dll不是问题。然而,正如事实证明的那样,OP并不需要kiosk模式。 - Eugene Mayevski 'Callback

1

1
谢谢,我知道WE(全屏浏览器模式)。我的需求不是完整的“亭”模式,而只是防止好奇或愚蠢的手指。 - Brian Frost

0

dWinLock 也提供了一种解决方案。如果我没记错的话,他们安装了一个服务来阻止 Ctrl+Alt+Del。


我认为dwinLock在Win7上工作不正常。虽然他们现在声称支持Win7,所以我猜应该有一个新版本。我已经使用过它了,非常流畅。 - Warren P
@Warren:一个有用的解决方案。我看到他们提到了“32位”。不清楚这是对操作系统还是应用程序的限制,所以我已经给他们发了电子邮件。 - Brian Frost
@Warren:是的,它支持在W7/64下运行的Delphi 32位应用程序。 - Brian Frost

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接