|          
安徽合肥智能机械研究所 张建军
 在开发Windows应用程序时,软件人员希望所编制的程序具有风格独特的用户界面,为此不惜采用一些占用系统内存资源颇多的第三方OCX控件,结果导致程序运行速度变慢或者打包后的安装程序体积太大的缺点。其实,如果我们仔细研究一下Windows提供的几百个WinAPI,就不难发现,通过直接调用API函数,发送、接收或者拦截系统消息等方法,同样可以实现在某些情况下只能依靠调用OCX才能达到的界面效果。
 
 例如:为我们所熟知的屏幕抓图软件HyperSnap,在其强大的屏幕抓图功能背后,还具有一项比较特殊的界面效果。
 
 通常情况下,当用鼠标点击一个Windows窗体左上角的Icon时,所看到的系统菜单一般都是固定不变的。
 
 HyperSnap的窗体改变了标准“系统菜单”,增加了多个新菜单项,并分别赋予它们不同的功能。其实这种效果的实现并不复杂,主要通过调用GetSystemMenu、AppendMenu等API函数完成。下面,我们就以C++Builder为例,讨论一下如何在自己的应用程序中实现类似HyperSnap的界面效果,并给出完整代码实例。
 
 1.API函数介绍
 
 ⑴ GetSystemMenu
 
 ① 功能:
 
 允许访问(拷贝或修改)系统菜单,普通Windows窗体如果未改变其菜单项状态,自动采用标准Windows菜单,即“恢复”、“移动”、“最大化”、“最小化”、“关闭”等。
 
 ②     原形:
 
 HMENU GetSystemMenu(
 
 HWND hWnd,
 
 BOOL bRevert
 
 );
 
 ③     入口参数:
 
 HWND为预改变系统菜单的窗体句柄。
 
 bRevert为标志。
 
 当bRevert为假,GetSystemMenu返回HWND代表窗体的拷贝,初始状态下,拷贝与原窗体一致,但允许修改。
 
 当bRevert为真,GetSystemMenu将HWND代表的窗体菜单恢复默认状态,之前对菜单的修改被取消。
 
 ④     返回值:
 
 当bRevert为假,返回HWND代表的窗体拷贝的句柄,当bRevert为真,返
 
 回值为Null。
 
 ⑵ AppendMenu
 
 ①功能:
 
 在指定菜单的最后插入一个菜单项,并可规定该菜单项的文字内容、外观和触发事件。
 
 ②     原形:
 
 BOOL AppendMenu(
 
 HMENU hMenu
 
 UINT uFlags
 
 UINT uIDNewItem
 
 LPCTSTR lpNewItem
 
 );
 
 ③     入口参数:
 
 hMenu为欲增加菜单项的菜单句柄。
 
 uFlags为新增菜单项的标志,可以是几种系统常量的组合。
 
 UIDNewItem为新增菜单项的标识。
 
 lpNewItem为新增菜单项的文字内容,可取MF_STRING、MF_SEPARATOR等值。
 
 ④     返回值:
 
 成功返回0,失败返回非0。
 
 ⑶ WM_SYSCOMMAND
 
 当点击菜单项时触发的系统消息。
 
 ⒉ 编程实例
 
 ⑴ 新建工程
 
 在C++ Builder 5.0 IDE 中新建工程Project1,Project1中包含Form1。
 
 ⑵ Form_Click事件
 
 void __fastcall TForm1::FormClick(TObject *Sender)
 
 {
 
 ChangeSystemMenu(Form1, "-", 0);
 
 ChangeSystemMenu(Form1, "自定义项目...", 99);
 
 Application->OnMessage = Form1->RegisterMsg;//指定窗体消息处理函数
 
 }
 
 ⑶ 自定义消息处理过程
 
 void __fastcall TForm1::RegisterMsg(tagMSG &Msg, bool &Handled)
 
 {
 
 if (Msg.message == WM_SYSCOMMAND)
 
 if (Msg.wParam == 99)
 
 ShowMessage("你点击了自定义菜单");//自定义菜单响应代码
 
 }
 
 ⑷ 改变系统菜单过程
 
 void __fastcall ChangeSystemMenu(TForm *Form, AnsiString Item, Word ItemID)
 
 {
 
 void* NormalSystemMenu;
 
 void* MinSystemMenu;
 
 char* AItem = new char[255];
 
 PChar PItem;
 
 NormalSystemMenu = GetSystemMenu(Form->Handle, false);
 
 MinSystemMenu = GetSystemMenu(Application->Handle, false);
 
 if (Item == "-")
 
 {
 
 AppendMenu(NormalSystemMenu, MF_SEPARATOR, 0, 0);//增加菜单分隔线
 
 AppendMenu(MinSystemMenu, MF_SEPARATOR, 0, 0);//增加菜单分隔线
 
 }
 
 else
 
 {
 
 PItem = StrPCopy(AItem, Item);
 
 AppendMenu(NormalSystemMenu, MF_STRING, ItemID, PItem);//增加菜单项文字
 
 AppendMenu(MinSystemMenu, MF_STRING, ItemID, PItem);//增加菜单项文字
 
 }
 
 }
 
 ⒊ 实例代码
 
 ⑴ Unit1.h文件
 
 //---------------------------------------------------------------------------
 
 #ifndef unitAppendMenuH
 
 #define unitAppendMenuH
 
 //---------------------------------------------------------------------------
 
 #include <Classes.hpp>
 
 #include <Controls.hpp>
 
 #include <StdCtrls.hpp>
 
 #include <Forms.hpp>
 
 //---------------------------------------------------------------------------
 
 class TForm1 : public TForm
 
 {
 
 __published:    // IDE-managed Components
 
 void __fastcall RegisterMsg(tagMSG &Msg, bool &Handled);//自定义菜单响应事件
 
 void __fastcall FormClick(TObject *Sender);
 
 private:    // User declarations
 
 public:     // User declarations
 
 __fastcall TForm1(TComponent* Owner);
 
 };
 
 //---------------------------------------------------------------------------
 
 extern PACKAGE TForm1 *Form1;
 
 //---------------------------------------------------------------------------
 
 #endif
 
 ⑵ Unit1.cpp文件
 
 //---------------------------------------------------------------------------
 
 #include <vcl.h>
 
 #pragma hdrstop
 
 #include "unitAppendMenu.h"
 
 //---------------------------------------------------------------------------
 
 #pragma package(smart_init)
 
 #pragma resource "*.dfm"
 
 TForm1 *Form1;
 
 //---------------------------------------------------------------------------
 
 __fastcall TForm1::TForm1(TComponent* Owner)
 
 : TForm(Owner)
 
 {
 
 }
 
 //---------------------------------------------------------------------------
 
 void __fastcall ChangeSystemMenu(TForm *Form, AnsiString Item, Word ItemID)
 
 {
 
 void* NormalSystemMenu;
 
 void* MinSystemMenu;
 
 char* AItem = new char[255];
 
 PChar PItem;
 
 NormalSystemMenu = GetSystemMenu(Form->Handle, false);
 
 MinSystemMenu = GetSystemMenu(Application->Handle, false);
 
 if (Item == "-")
 
 {
 
 AppendMenu(NormalSystemMenu, MF_SEPARATOR, 0, 0);//增加菜单分隔线
 
 AppendMenu(MinSystemMenu, MF_SEPARATOR, 0, 0);//增加菜单分隔线
 
 }
 
 else
 
 {
 
 PItem = StrPCopy(AItem, Item);
 
 AppendMenu(NormalSystemMenu, MF_STRING, ItemID, PItem);//增加菜单项文字
 
 AppendMenu(MinSystemMenu, MF_STRING, ItemID, PItem);//增加菜单项文字
 
 }
 
 }
 
 //---------------------------------------------------------------------------
 
 void __fastcall TForm1::RegisterMsg(tagMSG &Msg, bool &Handled)
 
 {
 
 if (Msg.message == WM_SYSCOMMAND)
 
 if (Msg.wParam == 99)
 
 ShowMessage("你点击了自定义菜单");//自定义菜单响应代码
 
 }
 
 //---------------------------------------------------------------------------
 
 void __fastcall TForm1::FormClick(TObject *Sender)
 
 {
 
 ChangeSystemMenu(Form1, "-", 0);
 
 ChangeSystemMenu(Form1, "自定义项目...", 99);
 
 Application->OnMessage = Form1->RegisterMsg;//指定窗体消息处理函数
 
 }
 
 //---------------------------------------------------------------------------
 
 4.实例效果
 
 以上代码在Win98、C++Builder 5.0环境下调试通过
 |