You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求Delphi实现Windows锁屏拦截提醒:检测锁屏并提供取消锁定选项

解决方案

实现思路

要实现拦截Windows锁屏操作并弹出自定义选择对话框,核心需要三步:

  1. 全局拦截锁屏命令:通过Windows全局钩子拦截SC_LOCKWORKSTATION系统命令,阻止默认锁屏行为;
  2. 自定义交互对话框:弹出带自定义按钮的对话框,根据用户选择执行「直接锁屏」或「先在线注销再锁屏」操作;
  3. 后台开机启动:通过注册表配置程序开机自动运行,并隐藏主窗口。

代码实现

1. 全局钩子DLL(LockHook.dll)

创建一个Delphi DLL工程,用于全局拦截锁屏命令:

library LockHook;

uses
  Windows, Messages, SysUtils;

var
  HookHandle: HHOOK;
  MainWnd: HWND;

function HookProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
var
  pMsg: PMSG;
begin
  Result := CallNextHookEx(HookHandle, nCode, wParam, lParam);
  if (nCode >= 0) then
  begin
    pMsg := PMSG(lParam);
    if (pMsg^.message = WM_SYSCOMMAND) and (pMsg^.wParam = SC_LOCKWORKSTATION) then
    begin
      // 阻止系统默认锁屏行为
      pMsg^.message := 0;
      // 通知主程序处理
      if MainWnd <> 0 then
        PostMessage(MainWnd, WM_USER + 1, 0, 0);
    end;
  end;
end;

procedure SetHook(hWnd: HWND); stdcall;
begin
  MainWnd := hWnd;
  HookHandle := SetWindowsHookEx(WH_GETMESSAGE, @HookProc, HInstance, 0);
end;

procedure UnsetHook; stdcall;
begin
  if HookHandle <> 0 then
  begin
    UnhookWindowsHookEx(HookHandle);
    HookHandle := 0;
  end;
end;

exports
  SetHook, UnsetHook;

begin
end.

2. 主程序(后台运行程序)

创建一个Delphi VCL工程,主窗口设置为隐藏,处理钩子通知并弹出对话框:

unit Main;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TMainForm = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    procedure SetStartup;
    procedure ShowLockDialog;
    procedure WMUser(var Msg: TMessage); message WM_USER + 1;
  public
  end;

var
  MainForm: TMainForm;

implementation

{$R *.dfm}

type
  TSetHook = procedure(hWnd: HWND); stdcall;
  TUnsetHook = procedure; stdcall;

var
  HookDLL: HMODULE;
  SetHook: TSetHook;
  UnsetHook: TUnsetHook;

procedure TMainForm.FormCreate(Sender: TObject);
begin
  // 隐藏主窗口,实现后台运行
  Visible := False;
  // 配置开机自动启动
  SetStartup;
  // 加载钩子DLL并初始化全局钩子
  HookDLL := LoadLibrary('LockHook.dll');
  if HookDLL <> 0 then
  begin
    @SetHook := GetProcAddress(HookDLL, 'SetHook');
    @UnsetHook := GetProcAddress(HookDLL, 'UnsetHook');
    if Assigned(SetHook) then
      SetHook(Handle);
  end;
end;

procedure TMainForm.FormDestroy(Sender: TObject);
begin
  // 卸载钩子并释放DLL
  if Assigned(UnsetHook) then
    UnsetHook;
  if HookDLL <> 0 then
    FreeLibrary(HookDLL);
end;

procedure TMainForm.SetStartup;
var
  Reg: TRegistry;
begin
  Reg := TRegistry.Create;
  try
    // 写入当前用户的开机启动项(无需管理员权限)
    Reg.RootKey := HKEY_CURRENT_USER;
    if Reg.OpenKey('Software\Microsoft\Windows\CurrentVersion\Run', True) then
    begin
      Reg.WriteString('LockInterceptor', Application.ExeName);
      Reg.CloseKey;
    end;
  finally
    Reg.Free;
  end;
end;

procedure TMainForm.ShowLockDialog;
var
  Dlg: TForm;
  btnLock, btnLogoffLock: TButton;
  lblMsg: TLabel;
begin
  // 创建自定义对话框
  Dlg := TForm.Create(nil);
  try
    Dlg.Caption := '锁屏确认';
    Dlg.Width := 320;
    Dlg.Height := 160;
    Dlg.Position := poScreenCenter;
    Dlg.FormStyle := fsStayOnTop;
    Dlg.BorderStyle := bsDialog;

    // 提示文本
    lblMsg := TLabel.Create(Dlg);
    lblMsg.Parent := Dlg;
    lblMsg.Caption := '检测到锁屏操作,请选择后续操作:';
    lblMsg.SetBounds(20, 20, 280, 30);
    lblMsg.Alignment := taCenter;
    lblMsg.WordWrap := True;

    // 「锁定」按钮
    btnLock := TButton.Create(Dlg);
    btnLock.Parent := Dlg;
    btnLock.Caption := '锁定(继续锁屏)';
    btnLock.SetBounds(30, 70, 120, 30);
    btnLock.ModalResult := mrYes;

    // 「先注销再锁屏」按钮
    btnLogoffLock := TButton.Create(Dlg);
    btnLogoffLock.Parent := Dlg;
    btnLogoffLock.Caption := '取消锁定(先在线注销再锁屏)';
    btnLogoffLock.SetBounds(170, 70, 120, 30);
    btnLogoffLock.ModalResult := mrNo;

    // 根据用户选择执行操作
    case Dlg.ShowModal of
      mrYes: LockWorkStation; // 直接执行锁屏
      mrNo:
        begin
          // ===== 替换为你的在线注销逻辑 =====
          // MyAppOnlineLogoff(); // 示例:调用自定义注销函数
          ShowMessage('已完成在线注销,即将锁屏'); // 测试用,实际删除
          // ================================
          LockWorkStation; // 注销后执行锁屏
        end;
    end;
  finally
    Dlg.Free;
  end;
end;

// 处理钩子发来的通知消息
procedure TMainForm.WMUser(var Msg: TMessage);
begin
  ShowLockDialog;
end;

end.

关键说明

  1. 全局钩子:通过WH_GETMESSAGE全局钩子拦截所有进程的WM_SYSCOMMAND消息,阻止默认锁屏行为;
  2. 自定义对话框:使用TForm创建自定义对话框,避免MessageDlg的按钮文本限制;
  3. 开机启动:写入HKEY_CURRENT_USER下的Run项,无需管理员权限,仅对当前用户生效;若需全局生效,可改为写入HKEY_LOCAL_MACHINE下的Run项,但程序需以管理员权限运行;
  4. 在线注销逻辑:在mrNo分支中替换为你的实际在线注销代码,比如调用应用的注销API。

内容的提问来源于stack exchange,提问作者ScottMan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 09:55:19