如何检测用户何时在 Windows 7 中锁定/解锁屏幕?
我找到了 this question它有 C# 的答案,但我想在 Delphi 2009 中使用它。我猜有一些 Windows 消息(如 these )可以完成这项工作。这是我试过的代码,但没有用:
const
NOTIFY_FOR_ALL_SESSIONS = 1;
{$EXTERNALSYM NOTIFY_FOR_ALL_SESSIONS}
NOTIFY_FOR_THIS_SESSION = 0;
{$EXTERNALSYM NOTIFY_FOR_THIS_SESSION}
type
TfrmAlisson = class(TForm)
lbl2: TLabel;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
public
FLockedCount: Integer;
procedure WndProc(var Message: TMessage); override;
function WTSRegisterSessionNotification(hWnd: HWND; dwFlags: DWORD): bool; stdcall;
function WTSUnRegisterSessionNotification(hWND: HWND): bool; stdcall;
end;
implementation
uses
// my impl uses here
procedure TfrmAlisson.FormCreate(Sender: TObject);
begin
if (WTSRegisterSessionNotification(Handle, NOTIFY_FOR_THIS_SESSION)) then
ShowMessage('Nice')
else
begin
lastError := GetLastError;
ShowMessage(SysErrorMessage(lastError));
end;
end;
procedure TfrmAlisson.FormDestroy(Sender: TObject);
begin
WTSUnRegisterSessionNotification(Handle);
end;
procedure TfrmAlisson.WndProc(var Message: TMessage);
begin
case Message.Msg of
WM_WTSSESSION_CHANGE:
begin
if Message.wParam = WTS_SESSION_LOCK then
begin
Inc(FLockedCount);
end;
if Message.wParam = WTS_SESSION_UNLOCK then
begin
lbl2.Caption := 'Session was locked ' +
IntToStr(FLockedCount) + ' times.';
end;
end;
end;
inherited;
end;
function TfrmAlisson.WTSRegisterSessionNotification(hWnd: HWND; dwFlags: DWORD): bool;
external 'wtsapi32.dll' Name 'WTSRegisterSessionNotification';
function TfrmAlisson.WTSUnRegisterSessionNotification(hWND: HWND): bool;
external 'wtsapi32.dll' Name 'WTSUnRegisterSessionNotification';
当 FormCreate
执行时,WTSRegisterSessionNotification
返回 false
并且最后一个操作系统错误返回 Invalid Parameter。
最佳答案
您的代码无法正常工作,因为您没有正确实现它。
您没有正确声明 WTSRegisterSessionNotification()
和 WTSUnRegisterSessionNotification()
。
此外,您没有考虑 VCL 在 Form 对象的生命周期内动态重新创建 Form 窗口的可能性。因此,即使 WTSRegisterSessionNotification()
成功,您也可能会丢失您的注册而没有意识到。
试试这个:
interface
uses
...;
type
TfrmAlisson = class(TForm)
lbl2: TLabel;
protected
procedure CreateWnd; override;
procedure DestroyWindowHandle; override;
procedure WndProc(var Message: TMessage); override;
public
LockedCount: Integer;
end;
implementation
const
NOTIFY_FOR_THIS_SESSION = $0;
NOTIFY_FOR_ALL_SESSIONS = $1;
function WTSRegisterSessionNotification(hWnd: HWND; dwFlags: DWORD): Boolean; stdcall; external 'wtsapi32.dll' name 'WTSRegisterSessionNotification';
function WTSUnRegisterSessionNotification(hWnd: HWND): Boolean; stdcall; external 'wtsapi32.dll' name 'WTSUnRegisterSessionNotification';
procedure TfrmAlisson.CreateWnd;
begin
inherited;
if not WTSRegisterSessionNotification(Handle, NOTIFY_FOR_THIS_SESSION) then
RaiseLastOSError;
end;
procedure TfrmAlisson.DestroyWindowHandle;
begin
WTSUnRegisterSessionNotification(Handle);
inherited;
end;
procedure TfrmAlisson.WndProc(var Message: TMessage);
begin
if Message.Msg = WM_WTSSESSION_CHANGE then
begin
case Message.wParam of
WTS_SESSION_LOCK: begin
Inc(LockedCount);
end;
WTS_SESSION_UNLOCK: begin
lbl2.Caption := Format('Session was locked %d times.', [LockedCount]);
end;
end;
end;
inherited;
end;
end.
也就是说,考虑编写不依赖于 VCL 的窗口重新创建行为的代码。您可以分配一个专用窗口来监视 session 更改:
interface
uses
...;
type
TfrmAlisson = class(TForm)
lbl2: TLabel;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
SessionWnd: HWND;
procedure SessionWndProc(var Message: TMessage);
public
LockedCount: Integer;
end;
implementation
const
NOTIFY_FOR_THIS_SESSION = $0;
NOTIFY_FOR_ALL_SESSIONS = $1;
function WTSRegisterSessionNotification(hWnd: HWND; dwFlags: DWORD): Boolean; stdcall; external 'wtsapi32.dll' name 'WTSRegisterSessionNotification';
function WTSUnRegisterSessionNotification(hWnd: HWND): Boolean; stdcall; external 'wtsapi32.dll' name 'WTSUnRegisterSessionNotification';
procedure TfrmAlisson.FormCreate(Sender: TObject);
begin
SessionWnd := AllocateHWnd(SessionWndProc);
if not WTSRegisterSessionNotification(SessionWnd, NOTIFY_FOR_THIS_SESSION) then
RaiseLastOSError;
end;
procedure TfrmAlisson.FormDestroy(Sender: TObject);
begin
if SessionWnd <> 0 then
begin
WTSUnRegisterSessionNotification(SessionWnd);
DeallocateHWnd(SessionWnd);
end;
end;
procedure TfrmAlisson.SessionWndProc(var Message: TMessage);
begin
if Message.Msg = WM_WTSSESSION_CHANGE then
begin
case Message.wParam of
WTS_SESSION_LOCK: begin
Inc(LockedCount);
end;
WTS_SESSION_UNLOCK: begin
lbl2.Caption := Format('Session was locked %d times.', [LockedCount]);
end;
end;
end;
Message.Result := DefWindowProc(SessionWnd, Message.Msg, Message.WParam, Message.LParam);
end;
end.
关于windows - 使用 Delphi 在 Windows 7 中检测用户何时锁定/解锁屏幕,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45988192/