利用C++Builder自定义Windows窗体“系统菜单”
利用C++Builder自定義Windows窗體“系統菜單”
安徽合肥智能機械研究所張建軍
-------------------------------------------------------------------------------
??? 在開發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環境下調試通過,所實現的界面效果如圖1所示。
| |
| |
圖1.本文代碼實現的自定義窗體“系統菜單”
------------------------------------------------------------------------------
總結
以上是生活随笔為你收集整理的利用C++Builder自定义Windows窗体“系统菜单”的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 利用生物视觉机制提高神经网络的对抗鲁棒性
- 下一篇: 我的个人网站更新了!