To zhengxq 大虾:
辛勤的劳动终于得到了回报,呵呵!
我原来就记得哪本书上说过,Delphi 的 TApplication 对象中其实隐含了一个窗口,只是没有
让用户看见,这个窗口的句柄就是 TApplication.Handle 。
为了证实这一点,我跟踪了 TApplication 对象的源码,发现了如下的代码:
procedure TApplication.CreateHandle;
begin
if not FHandleCreated and not IsConsole then
begin
FObjectInstance := MakeObjectInstance(WndProc);
if not GetClassInfo(HInstance, WindowClass.lpszClassName, TempClass) then
begin
WindowClass.hInstance := HInstance;
if Windows.RegisterClass(WindowClass) = 0 then
raise EOutOfResources.Create(SWindowClass);
end;
<Font color = #ff0000>FHandle := CreateWindow(WindowClass.lpszClassName, PChar(FTitle),
WS_POPUP or WS_CAPTION or WS_CLIPSIBLINGS or WS_SYSMENU
or WS_MINIMIZEBOX,
GetSystemMetrics(SM_CXSCREEN) div 2,
GetSystemMetrics(SM_CYSCREEN) div 2,
0, 0, 0, 0, HInstance, nil);</font> // Application Window 的宽高均为 0
FTitle := '';
FHandleCreated := True;
SetWindowLong(FHandle, GWL_WNDPROC, Longint(FObjectInstance));
...
end;
end;
上面的代码证实了这一说法,于是我察看了 TApplication.Restore 方法的源代码,找到了
这个问题的答案:
procedure TApplication.Restore;
begin
if IsIconic(FHandle) then
begin
SetActiveWindow(FHandle);
if (MainForm <> nil) and (ShowMainForm or MainForm.Visible) then
DefWindowProc(FHandle, WM_SYSCOMMAND, SC_RESTORE, 0)
else ShowWinNoAnimate(FHandle, SW_RESTORE);
SetWindowPos(FHandle, 0, GetSystemMetrics(SM_CXSCREEN) div 2,
GetSystemMetrics(SM_CYSCREEN) div 2, 0, 0, SWP_SHOWWINDOW);
// 其实所有的消息都应该发往 Application 对象窗口的句柄:TApplication.Handle
// 而不是主窗口的句柄
// 只有下面一句话才是操作 Application 的主窗口的,把主窗口显示出来
if (FMainForm <> nil) and (FMainForm.FWindowState = wsMinimized) and
not FMainForm.Visible then
begin
FMainForm.WindowState := wsNormal;
FMainForm.Show;
end;
...
end;
end;
我把上面的操作简化了一下,用标准的方法实现了 zhenxq 大虾的要求:
需要注意的是,本程序要把 Application.Title 设置为 '2ndRunning'
program Project1;
uses
Forms,Windows,Messages,
Unit1 in 'Unit1.pas' {Form1};
{$R *.RES}
var
HWindow: THandle;
begin
Application.Initialize;
begin
HWindow := FindWindow(nil, '2ndRunning')
// 查找 Application 的 Title ,而不是主窗口的 'Form1'
if HWindow <> 0 then
begin
if IsIconic(HWindow) then
SendMessage(HWindow,WM_SYSCOMMAND,SC_RESTORE,0);
SetForeGroundWindow(HWindow);
Application.Terminate;
Exit;
end;
end;
Application.Title := '2ndRunning';
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
这样做了以后,即使是最小化,也能正确地切换回来。
有兴趣的朋友可以用 SetWindowLong(Applicatin.Handle, ...) 和 SetWindowPos(Applicatin.Handle, ...)
函数把这个 Application 窗口显示出来看一看它的尊容。
From: BaKuBaKu