自 画 菜 单

 
     我们知道,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);
                       }
                   }
 

返回