如何隐藏随windows启动而启动的程序,我在程序中的
application.initialize;之前已经加上了下列语句:systemparametersinfo(spi_screensaverrunning,1,0,0);//屏蔽ctrl+alt+del
registerserviceprocess(getcurrentprocessid,1);//使程序名不出现在任务列表中但windows启动时按ctrl+alt+del键后程序名还是会出现在任务列表中,过二秒左右后才消失,怎么样才能不出现在列表中?
application.initialize;之前已经加上了下列语句:systemparametersinfo(spi_screensaverrunning,1,0,0);//屏蔽ctrl+alt+del
registerserviceprocess(getcurrentprocessid,1);//使程序名不出现在任务列表中但windows启动时按ctrl+alt+del键后程序名还是会出现在任务列表中,过二秒左右后才消失,怎么样才能不出现在列表中?
用HOOK API函数来实现,HOOK那个枚举函数。
. 将程序的启动信息放到注册表中。
. 将运行程序的快捷方式添加到Wi n d o w s的开始菜单中。
使用第一种方法运行的程序将早于使用第二种方法运行的程序。本小节和下一小节将分别
对两种方法进行介绍。
例程S16_29 该例程(运行界面如图1 6 - 4 7所示)实现了第一种方法。
参照图1 6 - 4 7定制窗体,其中有一个不可视组件
O p e n D i a l o g。
添加B u t t o n组件的O n C l i c k事件的处理过程如下:
procedure TForm1.Button1Click(Sender: TO b j e c t ) ;
v a r
Reg: TRegistry;
AppFileName: PChar;
b e g i n
if Edit1.Text='' then // 判断文件名是否为空
b e g i n
M e s s a g e B o x ( H a n d l e , '应用程序名称不可以为空。' , '错误' , M B _ O K + M B _ I C O N E R R O R ) ;
E x i t ;
e n d ;
// 初始化A p p F i l e N a m e
G e t M e m ( A p p F i l e N a m e , 2 5 6 ) ;
E d i t 1 . G e t Te x t B u f ( A p p F i l e N a m e , 2 5 6 ) ;
R e g : = T R e g i s t r y. C r e a t e ;
t r y
R e g . R o o t K e y : = H K E Y _ L O C A L _ M A C H I N E ;
if (Reg.OpenKey('Software\Microsoft\Wi n d o w s \ C u r r e n t Ve r s i o n \ R u n ' , F a l s e ) ) = True then
b e g i n
// 在注册表中添加数值
R e g . Wr i t e S t r i n g ( ' S t a r t U p 1 ' , A p p F i l e N a m e ) ;
e n d
e l s e
M e s s a g e B o x ( H a n d l e , '打开注册表失败。' , '错误' , M B _ O K + M B _ I C O N E R R O R ) ;
f i n a l l y
R e g . C l o s e K e y ;
R e g . F r e e ;
F r e e M e m ( A p p F i l e N a m e ) ;
e n d ;
procedure TForm1.Button2Click(Sender: TO b j e c t ) ;
b e g i n
第16章章其他编程技术章名427
图16-47 例程S16_29的运行界面
if OpenDialog1.Execute then
E d i t 1 . Te x t : = O p e n D i a l o g 1 . F i l e N a m e ; // 获取可执行文件的文件名
e n d ;
编译前,在U n i t 1 . p a s文件的u s e s语句中添加r e g i s t r y单元的说明。
执行完毕后,可以使用“注册表编辑器”查看运行结果。然后重新启动计算机,测试效果。
上面在使用过程Wr i t e S t r i n g的时候,将应用程序的说明信息也就是注册表中的数值的名称
设置为S t a r t U p 1,在实际编程的过程中可以取应用程序的可执行文件名或以其他方式设定。
如果计算机在启动Wi n d o w s的时候出现问题,可以查看上例中注册表的启动程序是否存在。
16.6.22 为程序在启动菜单中创建快捷方式
例程S16_30 该例程(运行界面如图1 6 - 4 8所示)将为应用程序在启动菜单中创建一个快
捷方式。
参照图1 6 - 4 8定制窗体,其中有两个不可视组件: D d e C l i e n t C o n v组件和O p e n D i a l o g组件。
将D d e C l i e n t C o n v组件的D d e S e r v i c e属性设置为P r o g M a n。
添加两个B u t t o n组件的O n C l i c k事件的处理过程如下:
procedure TForm1.Button1Click(Sender: TO b j e c t ) ;
v a r
Macro: string;
Cmd: array[0..255] of Char;
b e g i n
if Edit1.Text='' then // 判断文件名是否为空
b e g i n
M e s s a g e B o x ( H a n d l e , '程序名称不可以为空。' , '错误' , M B _ O K + M B _ I C O N E R R O R ) ;
E x i t ;
e n d ;
// 打开"启动"程序项
Macro := Format('[CreateGroup(%s)]', ['启动']) + #13#10;
StrPCopy (Cmd, Macro);
D d e C l i e n t C o n v 1 . O p e n L i n k ;
if DdeClientConv1.ExecuteMacro(Cmd, False)=False then
b e g i n
M e s s a g e B o x ( 0 , '打开启动程序项失败。' , '错误' , M B _ O K + M B _ I C O N E R R O R ) ;
E x i t ;
e n d ;
Macro := Format('[AddItem("%s",%s)]', [Edit1.Te x t , E d i t 2 . Text]) + #13#10;
StrPCopy (Cmd, Macro);
D d e C l i e n t C o n v 1 . O p e n L i n k ;
// 创建应用程序的快捷方式
if DdeClientConv1.ExecuteMacro(Cmd, False)=False then
b e g i n
M e s s a g e B o x ( 0 , '创建程序项失败。' , '错误' , M B _ O K + M B _ I C O N E R R O R ) ;
E x i t ;
e n d ;
e n d ;
procedure TForm1.Button2Click(Sender: TO b j e c t ) ;
428基本第三部分Delphi 高级编程技术
下载
图16-48 例程S16_30的运行界面
b e g i n
if OpenDialog1.Execute then
E d i t 1 . Te x t : = O p e n D i a l o g 1 . F i l e N a m e ; // 获取可
执行文件的文件名
e n d ;
示。其中图标的左下方有一个小箭头,表明是一个快捷
方式。
此外,可以将本例程与例程S 1 6 _ 7结合在一起练习。
注意:在定义宏命令A d d I t e m的时候,本例程中的第一个
字符串两端加了双引号,而例程S 1 6 _ 7中没有。
16.6.23 在程序中运行其他程序
有时在程序中需要启动其他应用程序,可以通过Windows API 函数C r e a t e P r o c e s s或
Wi n E x e c来实现。
例程S16_31 该例程(运行界面如图1 6 - 5 0所示)对在程序中运行其他程序进行了说明。
参照图1 6 - 5 0定制窗体,添加B u t t o n组件的O n C l i c k事件的处理过程如下:
procedure TForm1.Button1Click(Sender: TO b j e c t ) ;
v a r
S t a r t u p I n f o : T S t a r t u p I n f o ;
P r o c e s s I n f o : T P r o c e s s I n f o r m a t i o n ;
b e g i n
// 初始化工作
F i l l C h a r ( S t a r t u p I n f o , S i z e o f ( S t a r t u p I n f o ) , # 0 ) ;
StartupInfo.cb := Sizeof(StartupInfo);
StartupInfo.dwFlags := STA RT F _ U S E S H O W W I N D O W;
C r e a t e P r o c e s s ( n i l ,
'Calc', // 运行计算器
n i l ,
n i l ,
f a l s e ,
C R E ATE_NEW_CONSOLE or
N O R M A L _ P R I O R I T Y _ C L A S S ,
n i l ,
n i l ,
S t a r t u p I n f o ,
P r o c e s s I n f o ) ;
e n d ;
procedure TForm1.Button2Click(Sender: TO b j e c t ) ;
b e g i n
Wi n E x e c ( ' N o t e P a d ' , S W _ R E S TORE); // 运行写字本
e n d ;
16.6.24 同时只运行程序的一个实例
对于有些应用程序,只希望在系统中运行它的一个实例,也就是在程序运行期间,禁止它
第16章章其他编程技术章名429
下载
图16-49 在启动菜单中创建了
一个快捷方式
图16-50 例程S16_31的运行界面
第二次运行。
为了实现上述功能,可以采用下面的方法:在主窗体初始化的时候,设置窗体的类名。应
用程序在运行的最开始,判断当前系统中是否存在该窗体类名。如果存在,则给已经运行的应
用程序发送一个还原或在前台显示的消息,并且退出;如果不存在,则继续执行应用程序。
例程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
430基本第三部分Delphi 高级编程技术
下载
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 ;
下载
有具体代码吗?