二次运行的问题?(50分)

  • 主题发起人 主题发起人 zhengxq
  • 开始时间 开始时间
Z

zhengxq

Unregistered / Unconfirmed
GUEST, unregistred user!
Application.Initialize;
begin
HWindow := FindWindow(nil, 'DAO 注册器')

if HWindow <> 0 then begin
SetForeGroundWindow(HWindow);
end
end;
.........
上面的代码在程序不是最小化时没错,最小化时,没效,如加上
ShowWindow(HWindow, sw_show);,可以但当单击最小化按钮时,
他不是最小化到任务栏,而时变成一个只有标题栏的小东西,
停在屏幕上,***,这就是Delphi与众不同的地方,窗口最小化
时的动作也更其他开发的程序不同,随能解决?

出错
 
改成如下试试如何。
Application.Initialize;
begin
HWindow := FindWindow(nil, 'DAO 注册器')

if HWindow <> 0 then begin
Application.CreateForm(TForm1, Form1);
Application.Run;
end
end;
 
如下:
Application.Initialize;
HWindow := FindWindow(nil, 'DAO 注册器')

if HWindow <> 0 then begin
begin
SetForeGroundWindow(HWindow);
application.terminate;
end;
application.create(……);
……
end;
.........
 
上面两位有没有测试过啊。
To zhengxq: 看看下面吧,一个类似的问题:
<a href="DispQ.asp?LID=385232">用showwindow函数显示窗体,不能显示按钮,且无法关闭,为什么???</a>
 
不好意思,有点失误!
如下:
Application.Initialize;
HWindow := FindWindow(nil, 'DAO 注册器')

if HWindow <> 0 then
begin
SetForeGroundWindow(HWindow);
ShowWindow(HWindow, sw_show);
application.terminate;
end;
application.create(……);
……
.........
 
我有个方法,已经试验成功,其指导思想是处理二次运行问题
不要使用ShowWindow这个函数。
而是使用Application.Restore();
只有一次执行的程序自己把自己Restore才能使那些按钮有效。
知道这些就简单多了,

。。。。
HWindow := FindWindow(nil, 'DAO 注册器')

if HWindow <> 0 then begin
SendMessage(一个自定义消息);
而一次执行的程序在接收到这个消息之后执行Application.Restore();就可以了。
 
lml:
用什么代码使:
一次执行的程序在接收到这个消息之后执行Application.Restore();
 
lml:
你说“我有个方法,已经试验成功”,
那麻烦把你的代码给我!

 
我手边只有一个C++ builder 实现的例子,发给你看看吧
 
我的处理思想和lml的思想一样,当检测到时向程序发送一个自定义消息;下面的我的代码:
//unit1为主窗体的代码
unit Unit1;

interface

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

const
cm_restore=WM_USER+$1000;//自定义消息随便你叫什么。
type
TForm1 = class(TForm)
private
{ Private declarations }
public
Procedure RestoreRequest(var message: TMessage)
message CM_RESTORE;
end;
var
Form1: TForm1;

implementation

{$R *.DFM}

{ TForm1 }
procedure TForm1.RestoreRequest(var message: TMessage);
begin
if IsIconic(Application.Handle) = TRUE then
Application.Restore
else
Application.BringToFront;
end;

end.

//这是Project的代码
program Project1;

uses
Forms,
messages,
windows,
Unit1 in 'Unit1.pas' {Form1},

{$R *.RES}
const
cm_restor=WM_User+$1000;//注意,这里的名称要和主Form里定义的一样!
var
RvHandle:hWnd;
begin
RvHandle:= FindWindow(nil, 'DAO 注册器')

if RvHandle>0 then
begin
PostMessage(RvHandle,CM_RESTORE,0,0);
Exit;
end;
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
 
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
 
呵呵,这才是真正的办法,佩服佩服。
 
BaKuBaKu的方法是至今我说看到的最好的!
 
后退
顶部