Delphi7 程序任务栏菜单标准化

方法一、delphi7 程序任务栏菜单的改进(转)

首先作一下定义:当启动一个应用程序时,在任务栏上会出现一个程序切换按钮,右击时会出现一个菜单(实际是系统菜单,这个菜单也出现在应用程序窗口的标题条上),在本文中称之为任务栏菜单。 对于用delphi编写的程序来说,明眼人从任务栏的菜单上一眼就能看出,区别在哪里?就是的任务栏菜单只有三项 ——还原、最小化、关闭。如何改进?为什么?
记得以前在阿甘的家看到用Delphi比用VC或VB编写的程序多了 TApplication对象(我没有用过VC或VB),TApplication对象在create时利用IsLibrary的值来区分你建立的工程是应用程序还是动态链接库。如果是应用程序就出现任务栏菜单,否则不出现。可以利用增加一个RunFirst.pas单元来改变IsLibrary的值,使 IsLibrary := True,在Application.Initialize后再使IsLibrary:=False,再增加一个Form2作为主窗口,把Form1隐藏起来,这样出现的任务栏菜单就不只会有三项了,与用VC或VB编写出的程序外观上几乎没有了差别。按照他的方法照做,却出现了新的问题,在建立多文档界面或使用ActiveX对象时总出现错误,如何改进,接着往下看…  如何改进?

受到上面内容的启发,经过三天三夜反反复复、复复反反终于功成德满。跟我一起作:

1.既然使 IsLibrary := True 可以出现真正的系统菜单,那么我们就找一找何处出现 IsLibrary 为真值,经过多次实践可以找到在 Form.pas 单元中有 Application.create 的过程中有 if not IsLibrary then CreateHandle ,那么看看CreateHandle都干了些什么?

procedure TApplication.CreateHandle;
var TempClass: TWndClass; SysMenu: HMenu;
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;
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); FTitle := ‘‘; //最重要的,产生一个窗口句柄,这个窗口是宽、高都为零的窗口。当你在任务栏上按“显示桌面”后,再点击DELPHI生成的程序就会发现。
FHandleCreated := True; //表明程序句柄已经创建
SetWindowLong(FHandle, GWL_WNDPROC, Longint(FObjectInstance)); //显示这个窗口。为什么看不到?此窗口的Width:=0和Height:=0
if NewStyleControls then
begin
SendMessage(FHandle, WM_SETICON, 1, GetIconHandle);//设置图标
SetClassLong(FHandle, GCL_HICON, GetIconHandle);
end;
SysMenu := GetSystemMenu(FHandle, False); //以下是删除几项菜单项,在任务栏上就不出现了
DeleteMenu(SysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
DeleteMenu(SysMenu, SC_SIZE, MF_BYCOMMAND);
if NewStyleControls then
DeleteMenu(SysMenu, SC_MOVE, MF_BYCOMMAND);
end;
end;
我们完全可以在 if not IsLibrary then CreateHandle 行首加上“//”不去执行它。

2. 编译程序。.怎么样,任务栏的程序标题也变成了Form1。(高兴…) 别忙,点任务栏菜单的最小化命令,怎么没反应?接下来…

3.新建 unit2 和在 Form11 上建立 Button1 , 在 Button1 的 OnClick 事件中加入 Form2.Show;

4.编译运行,单击Button1,!!!注意任务栏!!!看见了什么?这是因为Form2在建立时是以 TApplication.Handle 为父的,因为我们没有建立 TApplication.Handle,那怎么办?

5.找到 procedure TApplication.CreateForm(InstanceClass: TComponentClass; var Reference);过程,在 FMainForm := TForm(Instance); 语句下面加入

if not IsLibrary then//我们把在 create 中不执行的判断语句再加上,如不是动态链接库就赋值
begin
FHandle := FMainForm.Handle;//把主窗口的句柄赋值给程序(能行吗?我也不知道^_^)
SetActiveWindow( FMainForm.Handle);//激活主窗口,没有此句,程序运行后得不到输入焦点。
end;  
至此,改进完成。

方法二、实用而简单的方法就可以实现:

procedure TForm1.FormCreate(Sender: TObject);
begin
GetSystemMenu(Application.Handle, True);
end;

留下评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注

76 − = 66