自 画 菜 单

我们知道,C++Builder没有自画菜单，但可以调用API函数::SetMenuItemInfo（）来改变菜单类型，达到自画菜单的目的。下面的例子演示了如何使用自画菜单。当鼠标位于菜单上拾，菜单项将凸出来。(黑体字为添加的代码)

//头文件
//---------------------------------------------------------------------------
#ifndef TestMenuH
#define TestMenuH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <Menus.hpp>//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TMainMenu *MainMenu1;
TMenuItem *aaa1;
TMenuItem *aaaaaaaaa1;
TMenuItem *ccc1;
TMenuItem *ddd1;
TMenuItem *eee1;
TMenuItem *ddsds1;
TMenuItem *fcdfsss1;
TMenuItem *dddddddd1;
void __fastcall FormCreate(TObject *Sender);
private: // User declarations
void __fastcall Modify(TMenuItem *pMenuItem);
protected :
MESSAGE void __fastcall CNMeasureItem(TWMMeasureItem &Msg);//增加响应消息
MESSAGE void __fastcall CNDrawItem(TWMDrawItem &Msg);
public: // User declarations
__fastcall TForm1(TComponent* Owner);
BEGIN_MESSAGE_MAP//添加消息映射
VCL_MESSAGE_HANDLER(WM_MEASUREITEM, TWMMeasureItem, CNMeasureItem);
VCL_MESSAGE_HANDLER( WM_DRAWITEM, TWMDrawItem, CNDrawItem);
END_MESSAGE_MAP(TForm);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

//实现文件
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "TestMenu.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Modify(TMenuItem *pMenuItem)
{//修改缺省属性
for(int i=0;i<pMenuItem->Count;i++)
{
MENUITEMINFO mii=
{
sizeof(MENUITEMINFO),
MIIM_TYPE|MIIM_DATA ,//改变类型和数据
MF_OWNERDRAW,0,0,0,0,0,DWORD(pMenuItem->Items[i]->Handle),
//把菜单项的句柄赋给32位数据
0,
0,
};
if(pMenuItem->Items[i]->Caption!="-")//如果不是间隔线
::SetMenuItemInfo(pMenuItem->Handle,i,TRUE,&mii);
if(pMenuItem->Items[i]->Count)//如果含有子菜单
Modify(pMenuItem->Items[i]);
}

}
void __fastcall TForm1::FormCreate(TObject *Sender)
{
for(int i=0;i<MainMenu1->Items->Count;i++)
{
Modify(MainMenu1->Items->Items[i]);
}
DrawMenuBar(Handle);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::CNMeasureItem(TWMMeasureItem &Msg)
{//设置菜单大小
TMenuItem *pItem=MainMenu1->FindItem(Msg.MeasureItemStruct->itemData,fkHandle);
Msg.MeasureItemStruct->itemWidth =pItem->Caption.Length()*8+40;
Msg.MeasureItemStruct->itemHeight = 20;
}
void __fastcall TForm1::CNDrawItem(TWMDrawItem &Msg)
{//画出菜单
TMenuItem *pItem=MainMenu1->FindItem(Msg.DrawItemStruct->itemData,fkHandle);
TCanvas *pCanvas=new TCanvas;
pCanvas->Handle=Msg.DrawItemStruct->hDC;
RECT r=Msg.DrawItemStruct->rcItem;
pCanvas->Brush->Color=clBtnFace;
RECT r1=r;
r1.right+=1;
r1.bottom+=1;
r1.top-=1;
r1.left-=1;
pCanvas->FillRect(r);
::SetBkMode(pCanvas->Handle,TRANSPARENT);
pCanvas->TextOut(r.left+10,r.top+2,pItem->Caption);
r.right-=1;
r.bottom-=1;
if(Msg.DrawItemStruct->itemAction == ODA_SELECT&&
Msg.DrawItemStruct->itemState&ODS_SELECTED )
{
pCanvas->Pen->Color=(TColor)(RGB(255,255,255));
pCanvas->MoveTo(r.right,r.top);
pCanvas->LineTo(r.left,r.top);
pCanvas->LineTo(r.left,r.bottom);
pCanvas->Pen->Color=(TColor)(RGB(128,128,128));
pCanvas->LineTo(r.right,r.bottom);
pCanvas->LineTo(r.right,r.top);
}
}