Можно ли отключить сочетания клавиш для переключения задач в W7 с помощью Delphi?

У моего приложения в течение многих лет был режим, когда клиент может "отключить доступ к ОС". Очевидно, что эта функция идет вразрез (по крайней мере, в том, что касается 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;

Неудивительно, что в W7 это никак не сказывается (я думаю, что это работает в XP и т. Д.). Кто-нибудь знает другой, лучший, способ включения / отключения Alt-Tab (и других специальных клавиш Windows) от работы?

4 ответа

Решение

Если найдено решение:

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 + Пробел, Win + Стрелки, Win+P, Win+U, Win+E, Win+F, Win+Digit, ...
  • Почти любая комбинация, включая ключ Windows (но не все, например, Win+L)

Как отметил Дэвид, это называется "Режим киоска". Несколько хороших статей ( часть 1 и часть 2) можно найти на About.com.

Существует Windows Embedded Standard 7, которую можно упаковать так, чтобы в ней был настоящий режим киоска.

dWinLock также предоставляет решение. IIRC, они устанавливают сервис, который может остановить Ctrl+Alt+Del.

Другие вопросы по тегам