我找到了一個解決方案,併發布演示代碼(XE2)作爲這個問題的Delphi解決方案。
它是來自delphiDabbler的answer here和解決方案1的組合。
基本上我正在註冊Windows會話狀態更改事件(WM_WTSSESSION_CHANGE
)。在提供的示例中(基於裸VCL表單應用程序),我使用WM_EXITSIZEPOS
消息來保存當前表單的sizepos。
Windows在位置更改消息被觸發的時刻顯示出不同的行爲。這就是爲什麼我必須修改我的初稿,現在使用兩個變量。我在會議鎖定時阻止位置變化,並在會議解鎖後阻止第一次位置變更。位置更改通過使用WM_WINDOWPOSCHANGING
消息截獲。
但是爲了不恢復正常位置,如果窗體是最大化我正在使用FRestoreNormalRect字段。
unit Unit1;
interface
uses
Winapi.Windows,
Winapi.Messages,
Vcl.Forms;
type
TForm1 = class(TForm)
private
FSessionIsLocked: Boolean;
FSessionWasUnlocked: Boolean;
FRestoreNormalRect: Boolean;
FLeft: Integer;
FTop: Integer;
FWidth: Integer;
FHeight: Integer;
procedure WMWTSSessionChange(var Msg: TMessage); message WM_WTSSESSION_CHANGE;
protected
procedure CreateWnd; override;
procedure DestroyWnd; override;
procedure WMExitSizeMove(var Msg: TMessage); message WM_EXITSIZEMOVE;
procedure WMPosChanging(var Msg: TWmWindowPosChanging); message WM_WINDOWPOSCHANGING;
procedure WMSize(var Msg: TWMSize); message WM_SIZE;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
//--------------------------------------------------------------------------------------------------
procedure TForm1.CreateWnd;
begin
inherited;
WTSRegisterSessionNotification(WindowHandle, NOTIFY_FOR_THIS_SESSION);
end;
//--------------------------------------------------------------------------------------------------
procedure TForm1.DestroyWnd;
begin
WTSUnRegisterSessionNotification(WindowHandle);
inherited;
end;
//--------------------------------------------------------------------------------------------------
procedure TForm1.WMExitSizeMove(var Msg: TMessage);
var
WP: TWindowPlacement;
NormalRect: TRect;
begin
WP.Length := SizeOf(TWindowPlacement);
GetWindowPlacement(Self.Handle, @WP);
NormalRect := WP.rcNormalPosition;
FLeft := NormalRect.Left;
FTop := NormalRect.Top;
FWidth := NormalRect.Right - NormalRect.Left;
FHeight := NormalRect.Bottom - NormalRect.Top;
end;
//--------------------------------------------------------------------------------------------------
procedure TForm1.WMPosChanging(var Msg: TWmWindowPosChanging);
begin
{ Sizepos changes might occur due to locks or unlocks. We need do prohibit both.
While the session is locked we ignore all position changes.
When the session has been unlocked we will ignore the next PosChanging message. }
if FSessionIsLocked or FSessionWasUnlocked then
begin
{ overwrite with the old settings }
if FRestoreNormalRect then
begin
Msg.WindowPos.x := FLeft;
Msg.WindowPos.y := FTop;
Msg.WindowPos.cx := FWidth;
Msg.WindowPos.cy := FHeight;
Msg.Result := 0;
end;
{ reset the variable, otherwise a manual resize would not be possible }
if FSessionWasUnlocked then
FSessionWasUnlocked := False;
end;
end;
//--------------------------------------------------------------------------------------------------
procedure TiQForm.WMSize(var Msg: TWMSize);
begin
inherited;
{ We need to restore our normal rect only if the form is not maximized. Because
if it is maximized it only positioned on one monitor and will not be moved
by windows. If we do not repsect this case we would be restoring the normal
rect unintentionally in WMPosChanging for every maximized form. }
FRestoreNormalRect := not (Msg.SizeType = SIZE_MAXIMIZED);
end;
//--------------------------------------------------------------------------------------------------
procedure TForm1.WMWTSSessionChange(var Msg: TMessage);
begin
case Message.WParam of
WTS_CONSOLE_DISCONNECT, WTS_REMOTE_DISCONNECT, WTS_SESSION_LOCK, WTS_SESSION_LOGOFF:
begin
FSessionIsLocked := True;
end;
WTS_CONSOLE_CONNECT, WTS_REMOTE_CONNECT, WTS_SESSION_UNLOCK, WTS_SESSION_LOGON:
begin
FSessionIsLocked := False;
FSessionWasUnlocked := True;
end;
end;
inherited;
end;
//--------------------------------------------------------------------------------------------------
end.
您可以顯示嘗試還原的代碼。你能告訴我們什麼時候窗口狀態是什麼時候存儲,什麼時候恢復。它最大化了嗎? –
我添加了信息。那裏沒什麼特別的。我試圖找出正確的事件作出響應或適當的時間重置位置,如果這是可能的。最好的辦法是攔截適當的信息,並防止我的表格被重新調整大小。 –
也許這可以幫助http://bobobobo.wordpress.com/2008/02/10/intercepting-the-screensaver/ – Graymatter