龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > 软件开发 > VC开发 >

Visual C++中自绘菜单的实现(2)

时间:2009-12-30 15:42来源:未知 作者:admin 点击:
分享到:
ODS_SELECTED表示选中控件;hwndItem 指定了组合框、列表框和按钮等自绘控件的窗口句柄;如果自绘的对象时菜单项,则表示包含该菜单项的菜单句柄。hDC指定

  ODS_SELECTED表示选中控件;hwndItem 指定了组合框、列表框和按钮等自绘控件的窗口句柄;如果自绘的对象时菜单项,则表示包含该菜单项的菜单句柄。hDC指定了绘制操作所使用的设备环境。 rcItem指定了将被绘制的矩形区域。这个矩形区域就是上面hDC的作用范围。系统会自动裁剪组合框、列表框或按钮等控件的自绘制区域以外的部分。也就是说rcItem中的坐标点(0,0)指的就是控件的左上角。但是系统不裁剪菜单项,所以在绘制菜单项的时候,必须先通过一定的换算得到该菜单项的位置,以保证绘制操作在我们希望的区域中进行。

  itemData这个成员变量最为关键,菜单自绘时所需要的图标、文本等信息都是通过它获取的,至于它的具体值,是通过CMenu类的CMenu::AppendMenu()、CMenu::InSertMenu()、CMenu::ModifMenu()等函数的调用来传递的。

  菜单自绘仅仅重载CMenu::DrawItem()函数是不够的,还需要重载CMenu:: MeasureItem()函数,在这个函数里面填充MEASUREITEMSTRUCT结构,通知Windows自绘控件的尺寸。该函数的原形为:

virtual void MeasureItem( LPMEASUREITEMSTRUCT lpMeasureItemStruct );

  该函数的参数为一个指向MEASUREITEMSTRUCT结构的指针对象,该对象结构为:

typedef struct tagMEASUREITEMSTRUCT {
 UINT CtlType; //控件类型;
 UINT CtlID; //控件的ID识别号,它不包括菜单控件;
 UINT itemID; //菜单项的ID识别号;
 UINT itemWidth; //菜单项的宽度;
 UINT itemHeight; //菜单项的高度;
 DWORD itemData //自绘控件所需要的数据,
} MEASUREITEMSTRUCT;

  上面这个结构中,成员变量CtlType等于ODT_COMBOBOX 时,表示当前控件为自绘型的组合框,等于ODT_LISTBOX 时表示当前控件为自绘列表控制件,等于ODT_MENU 时表示当前控件为自绘菜单。对于组合框和列表框控件,成员变量itemData是通过相应的AddString()、InsertString()获取的, 对于菜单控件,成员变量itemData与DRAWITEMSTRUCT结构中的itemData是一致的。

  菜单自绘时所需要的图标资源,可以预先定义,使用时直接装载,但是这种方法比较呆板,另外一种方法是通过搜索状态条上的按钮信息,如果当前按钮的ID识别号与某一菜单项的ID识别号一致,那末通过就将该按钮上的图标提取出来,作为菜单图标,如果菜单项与工具条上的所有按钮的ID都不相同,那么对该菜单项不画图标。至于菜单的文本信息,直接采用用户自定义菜单的文本就可以了。

  根据上面介绍的知识,本例定义一个CMemu类的子类CMemuEx类来实现菜单的自绘功能,该类不仅支持在菜单中显示图标、即时反映当前菜单项状态的功能,还支持在菜单中添加纵向位图。在具体实现过程中,CMemuEx类除了上述介绍的需要重载的DrawItem()、MeasureItem()等函数外,另外的一些主要成员函数如下:

  1、void InitMenu(CMenu *pMenu,UINT uToolBar,CToolBar *pToolBar);

  说明:这是CMenuEx类最主要的一个接口。该函数根据状态栏信息来初始化CMenuEx类;

  2、void SetImageLeft(UINT idBmpLeft);

  说明:这也是CMenuEx类中的一个重要的接口。调用CMenuEx类对象的SetImageLeft()可以实现菜单中的纵向位图(像Windows系统中的"开始"菜单),调用该函数时参数是位图的ID值。需要注意的是,目前CMenuEx类实现的是对主框架菜单设置纵向位图,对上下文菜单不适用,读者朋友可以稍加修改,自由的决定对何种菜单设置纵向位图。

  3、void InitPopupMenu(CMenu *pMenu,UINT uToolBar,CToolBar *pToolBar)

  说明:这个函数是为了处理上下文菜单的自绘而编写的,CMenuEx类的任一实例都只能调用InitMenu()、InitPopupMenu()这两个成员函数中的一个,不能一同使用。

精彩图集

赞助商链接