(转载)
对于有些应用程序,只希望在系统中运行它的一个实例,也就是在程序运行期间,禁止它
第二次运行。
为了实现上述功能,可以采用下面的方法:在主窗体初始化的时候,设置窗体的类名。应
用程序在运行的最开始,判断当前系统中是否存在该窗体类名。如果存在,则给已经运行的应
用程序发送一个还原或在前台显示的消息,并且退出;如果不存在,则继续执行应用程序。
例程S16_32 该例程对上述功能进行了说明。
首先在主窗体中自定义一个消息,并为主窗体的类名定义一个字符串常量。为了设置窗体
的类名,需要重载T C u s t o m F o r m 类的方法C r e a t e P a r a m s 。在U n i t 1 . p a s 中添加代码如下:
i n t e r f a c e
u s e s
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
c o n s t
C M _ R E S TORE = WM_USER + $1000; // 自定义一个消息,用来恢复窗口
APPNAME = 'S16_33'; // 窗体类名字符串常量
t y p e
TForm1 = class(TForm)
. . .
p u b l i c
procedure CreateParams(var Params: TCreateParams); override;
Procedure RestoreRequest(var message: TMessage); message CM_RESTO R E ;
e n d ;
. . .
i m p l e m e n t a t i o n
{$R *. D F M }
{ TForm1 }
procedure TForm1.CreateParams(var Params: TCreateParams);
b e g i n
// 设置窗体的类名
inherited CreateParams(Params);
P a r a m s . WinClassName := APPNAME;
e n d ;
下面添加测试窗体类名的代码。
为了在程序运行的一开始就测试当前系统中是否存在主窗体中要定义的类名,可以在工程
文件中添加代码进行测试。测试前需要定义与主窗体中一致的自定义消息和窗体类名字符串常
量。工程文件中的有关代码如下:
program Project1;
u s e s
F o r m s , M e s s a g e s , Wi n d o w s ,
Unit1 in 'Unit1.pas' {Form1};
c o n s t
// 自定义一个消息,用来恢复窗口
C M _ R E S TORE = WM_USER + $1000;
APPNAME = 'S16_33'; // 窗体类名字符串常量
v a r
下载
RvHandle : hWnd; // 窗口句柄
{$R *. R E S }
b e g i n
RvHandle := FindWindow(APPNAME, NIL); // 根据窗体类名查找窗口句柄
if RvHandle > 0 then // 如果找到则发送自定义的消息并退出
b e g i n
PostMessage(RvHandle, CM_RESTORE, 0, 0);
E x i t ;
e n d ;
A p p l i c a t i o n . I n i t i a l i z e ;
Application.CreateForm(TForm1, Form1);
A p p l i c a t i o n . R u n ;
e n d .
最后将在主窗体中添加接收自定义消息的代码。
在U n i t 1 . p a s 文件中T F o r m 1 的定义中添加接收自定义消息的过程R e s t o r e R e q u e s t ,并在类的
定义体中按下C t r l + S h i f t + C ,完善过程的定义体。具体代码如下:
t y p e
TForm1 = class(TForm)
. . .
p u b l i c
procedure CreateParams(var Params: TCreateParams); override;
Procedure RestoreRequest(var message: TMessage); message CM_RESTO R E ;
e n d ;
. . .
procedure TForm1.RestoreRequest(var message: TMessage);
b e g i n
// 接到自定义的消息后,如果处于最小化状态则恢复,否则放置到桌面的最前面
M e s s a g e B o x ( H a n d l e , '程序" ' + A P P N A M E + ' "已经运行了。' ,
'信息' , M B _ O K + M B _ I C O N I N F O R M AT I O N + M B _ S Y S T E M M O D A L ) ;
if IsIconic(Application.Handle) = TRUE then
A p p l i c a t i o n . R e s t o r e
e l s e
A p p l i c a t i o n . B r i n g To F r o n t ;
e n d ;
程序编译、链接通过后,可以在Wi n d o w s 的资源管理器中运行测试。
对于有些应用程序,只希望在系统中运行它的一个实例,也就是在程序运行期间,禁止它
第二次运行。
为了实现上述功能,可以采用下面的方法:在主窗体初始化的时候,设置窗体的类名。应
用程序在运行的最开始,判断当前系统中是否存在该窗体类名。如果存在,则给已经运行的应
用程序发送一个还原或在前台显示的消息,并且退出;如果不存在,则继续执行应用程序。
例程S16_32 该例程对上述功能进行了说明。
首先在主窗体中自定义一个消息,并为主窗体的类名定义一个字符串常量。为了设置窗体
的类名,需要重载T C u s t o m F o r m 类的方法C r e a t e P a r a m s 。在U n i t 1 . p a s 中添加代码如下:
i n t e r f a c e
u s e s
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
c o n s t
C M _ R E S TORE = WM_USER + $1000; // 自定义一个消息,用来恢复窗口
APPNAME = 'S16_33'; // 窗体类名字符串常量
t y p e
TForm1 = class(TForm)
. . .
p u b l i c
procedure CreateParams(var Params: TCreateParams); override;
Procedure RestoreRequest(var message: TMessage); message CM_RESTO R E ;
e n d ;
. . .
i m p l e m e n t a t i o n
{$R *. D F M }
{ TForm1 }
procedure TForm1.CreateParams(var Params: TCreateParams);
b e g i n
// 设置窗体的类名
inherited CreateParams(Params);
P a r a m s . WinClassName := APPNAME;
e n d ;
下面添加测试窗体类名的代码。
为了在程序运行的一开始就测试当前系统中是否存在主窗体中要定义的类名,可以在工程
文件中添加代码进行测试。测试前需要定义与主窗体中一致的自定义消息和窗体类名字符串常
量。工程文件中的有关代码如下:
program Project1;
u s e s
F o r m s , M e s s a g e s , Wi n d o w s ,
Unit1 in 'Unit1.pas' {Form1};
c o n s t
// 自定义一个消息,用来恢复窗口
C M _ R E S TORE = WM_USER + $1000;
APPNAME = 'S16_33'; // 窗体类名字符串常量
v a r
下载
RvHandle : hWnd; // 窗口句柄
{$R *. R E S }
b e g i n
RvHandle := FindWindow(APPNAME, NIL); // 根据窗体类名查找窗口句柄
if RvHandle > 0 then // 如果找到则发送自定义的消息并退出
b e g i n
PostMessage(RvHandle, CM_RESTORE, 0, 0);
E x i t ;
e n d ;
A p p l i c a t i o n . I n i t i a l i z e ;
Application.CreateForm(TForm1, Form1);
A p p l i c a t i o n . R u n ;
e n d .
最后将在主窗体中添加接收自定义消息的代码。
在U n i t 1 . p a s 文件中T F o r m 1 的定义中添加接收自定义消息的过程R e s t o r e R e q u e s t ,并在类的
定义体中按下C t r l + S h i f t + C ,完善过程的定义体。具体代码如下:
t y p e
TForm1 = class(TForm)
. . .
p u b l i c
procedure CreateParams(var Params: TCreateParams); override;
Procedure RestoreRequest(var message: TMessage); message CM_RESTO R E ;
e n d ;
. . .
procedure TForm1.RestoreRequest(var message: TMessage);
b e g i n
// 接到自定义的消息后,如果处于最小化状态则恢复,否则放置到桌面的最前面
M e s s a g e B o x ( H a n d l e , '程序" ' + A P P N A M E + ' "已经运行了。' ,
'信息' , M B _ O K + M B _ I C O N I N F O R M AT I O N + M B _ S Y S T E M M O D A L ) ;
if IsIconic(Application.Handle) = TRUE then
A p p l i c a t i o n . R e s t o r e
e l s e
A p p l i c a t i o n . B r i n g To F r o n t ;
e n d ;
程序编译、链接通过后,可以在Wi n d o w s 的资源管理器中运行测试。
解决方案 »
- 200分 求Skin Builder 4.42
- 关于MDI创口的关闭问题。
- 有没有直接输出Excel的DBGrid控件,要源码
- 遇到奇怪问题 请大家赐教
- 用rave做报表,如何自定义报表的大小?
- 怎样在子线程中实现Socket的数据接收
- 这样的开发我不感恭维,大家说说看
- ?报表里QRDBText面的Mask属性能否把时间(2002-2-3 8:03)格式化为8:03!!!
- Delphi调用Oracle存储过程插入图片
- 如何发布一个基于ActiveForm的ActiveX控件?
- 哪里有Delphi控件的详细说明啊!就是Delhpi的一般控件比如TButton
- single类型如何转换成string型?该用哪个函数?
使用当前窗口Handle,来寻找同层级最顶上的窗口
h:=FindWindow(Form1.Handle,HWND_FIRST)
然后一个个用HWND_NEXT找下来,用GetWindowText读出标题,比较和您的程序
标题吻合的个数,超过一个,就将Handle不等于自己的窗口设为Focus,中止当前程序。
注意:用GetWindowText必须先验证其Parent是NULL,即此窗体是主窗体。这样好些,免得你的程序如果有同名窗口的话
原理同上,代码如下:
加到工程文件中.
const classname='你的主窗口类名';//尽量不要是容易重复的名字.
var
handle:integer;
begin
handle:=findwindow(classname,nil);
if handle<>0 then
begin
halt;
end;
Application.Initialize;
Application.CreateForm(....);
Application.Run;
end;
const
CM_RESTORE = WM_USER + $1000; {自定义的“恢复”消息}
MYAPPNAME = "My Delphi Program";
并在Form的定义的public节中加入
procedure CreateParams(var Params: TCreateParams); override;
Procedure RestoreRequest(var message: TMessage); message CM_RESTORE;
在implementation节中加入
{指定窗口名称}
procedure TForm1.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
Params.WinClassName := MYAPPNAME;
end;{处理“恢复”消息}
procedure TForm1.RestoreRequest(var message: TMessage);
begin
if IsIconic(Application.Handle) = TRUE then
Application.Restore
else
Application.BringToFront;
end;经过以上修改,程序的主窗口的类名已经被指定了,这是进行判断的基础。一般在程序刚开始运行的时候进行判断,所以还要对DPR文件进行修改。2、对DPR文件的改动在 uses 节中添加 windows、messages这两个单元加入下列语句,注意两个文件中常量CM_RESTORE和MYAPPNAME的定义必须一致
const
CM_RESTORE = WM_USER + $1000; {自定义的“恢复”消息}
MYAPPNAME = "My Delphi Program";
var
RvHandle : hWnd;将下列语句插到程序最前部(在Application.Initialize之前)RvHandle := FindWindow(MYAPPNAME, NIL);
if RvHandle > 0 then
begin
PostMessage(RvHandle, CM_RESTORE, 0, 0);
Exit;
end;
这段程序的意思是如果找到一个类名相同的窗口,则向该窗口发送一个消息,并退出,而本例中原窗口收到该消息后会自动激活或从图标还原,从而达到了避免二次运行且能自动调出前一例程的目的。