How can I make a system-modal window?

浪子不回头ぞ 提交于 2020-01-14 13:56:27

问题


Is it possible to make the main form of an application system modal? My application will FTP a file from a remote company PC. Users should not be allowed to interact with the desktop while this process is in progress.

Application.MainFormOnTaskbar := True;
Application.ShowMainForm := False;
...
FormChild.ShowModal;

回答1:


It doesn't make sense to make the main form modal. Indeed, if you have an ordinary application with a (normal) main form, and then displays a modal form (e.g. a dialog box, or a TOpenDialog), then the "modality" means that the main form, and the rest of your application, becomes "disabled" until the modal form is closed. (But other applications aren't affected at all by this.) But this doesn't make sense for the main form, because when the main form is shown, there is no "rest" of your application to disable. In fact, a normal main form is in a sense already modal, if you do not open any other forms.

I think that you wish to create a system modal form, that is, a form that disables the rest of the desktop when shown. But this isn't too easy to do, because of the security principles of modern versions of the Microsoft Windows operating system. Indeed, a single application isn't (normally) supposed to take control over the entire OS like this.




回答2:


As other answers mention that you want to do is difficult to comprehend as modal form's purpose is to disable all application forms below so basically application form might be considered a modal form itself.

Although if you wish to make your application the only receiver of focus on current windows desktop (possibly non-administrative user desktop), you need to:

  1. Hide the taskbar by making your form fullscreen
  2. Lock as many windows keys as you can afford considering accessibility of your application (Ctrl, Alt, F1-F12, Windows, Menu)

With new versions of windows you can do all of that as non-priviledged user, except Ctrl+Alt+Del combination using global window hooks.

uses
  Windows;

var
  hKeybaordHook: HHOOK = 0;

function KeyboardHook(nCode: Integer; wParam: WPARAM; lParam: LPARAM): HRESULT; stdcall;
type
  PKBDLLHOOKSTRUCT = ^TKBDLLHOOKSTRUCT;
  TKBDLLHOOKSTRUCT = packed record
    vkCode: DWORD;
    scanCode: DWORD;
    flags: DWORD;
    time: DWORD;
    dwExtraInfo: DWORD;
  end;
const
  LLKHF_ALTDOWN = $20;
var
  pkbhs: PKBDLLHOOKSTRUCT;
begin
  pkbhs := PKBDLLHOOKSTRUCT(lParam);
  if nCode = HC_ACTION then
  begin
    Result := 1;
// CTRL
    if WordBool(GetAsyncKeyState(VK_CONTROL) and $8000) then Exit
// ALT
    else if LongBool(pkbhs^.flags and LLKHF_ALTDOWN) then Exit
// WIN KEYS
    else if (pkbhs^.vkCode = VK_LWIN) or (pkbhs^.vkCode = VK_RWIN) then Exit
// FUNCTION KEYS
    else if bDisableFunctionKeys and (pkbhs^.vkCode >= VK_F1) and (pkbhs^.vkCode <= VK_F24) then Exit;
{
// Disabling specific combinations
// CTRL+ESC
    else if (pkbhs^.vkCode = VK_ESCAPE) and WordBool(GetAsyncKeyState(VK_CONTROL) and $8000) then Exit
// ALT+TAB
    else if (pkbhs^.vkCode = VK_TAB) and LongBool(pkbhs^.flags and LLKHF_ALTDOWN) then Exit
// ALT+ESC
    else if (pkbhs^.vkCode = VK_ESCAPE) and LongBool(pkbhs^.flags and LLKHF_ALTDOWN) then Exit
}
  end;
  Result := CallNextHookEx(hKeybaordHook, nCode, wParam, lParam);
end;

procedure MainForm.FormShow(Sender: TObject);
const
  WH_KEYBOARD_LL = 13;
begin
  SetBounds(0, 0, Screen.Width, Screen.Height);

  if hKeybaordHook = 0 then
    hKeybaordHook := SetWindowsHookEx(WH_KEYBOARD_LL, @KeyboardHook, HInstance, 0);
end;

procedure MainForm.FormHide(Sender: TObject);
begin
  if (hKeybaordHook <> 0) and UnhookWindowsHookEx(hKeybaordHook) then
    hKeybaordHook := 0;
end;

You can also set "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\taskmgr.exe" registry key value to some dummy text, to disable task manager (including Ctrl+Shift+Esc combination).




回答3:


Create your own desktop using CreateDesktop() (and create a status window to display on it), then use OpenDesktop() to retreive the user's desktop, then switch between them using SwitchDesktop() when the file transfer begins and ends. While your custom desktop is active, the user cannot access his/her desktop (the screensaver does exactly this, for instance).




回答4:


If you want to take over the user's desktop and prevent them from using their computer, you could use dWinLock.



来源:https://stackoverflow.com/questions/5028944/how-can-i-make-a-system-modal-window

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!