当前位置: 首页 > news >正文

搭建wordpress/快速刷排名seo软件

搭建wordpress,快速刷排名seo软件,自己网站怎么做外链,餐饮招商加盟网站建设费用一、提出问题 在VCKBASE上读到《 自绘菜单的实现》[作者:querw]。应用的我自己的正在进行的工程后发现效果不错,可是有存在许多问题。整个类的设计方面存在很多缺陷(先天,后天的),存…
一、提出问题

  在VCKBASE上读到《 自绘菜单的实现》[作者:querw]。应用的我自己的正在进行的工程后发现效果不错,可是有存在许多问题。整个类的设计方面存在很多缺陷(先天,后天的),存在的主要问题如下:
  1. 当应用在多文档界面(MDI)中的时候,无法对系统自动添加菜单和文档模板菜单进行自绘(比如无法对文件->最近文件(MRU)菜单项中的文件列表就是系统自动添加)。原因是类内部没有对CMainFrame::OnInitPopupMenu()消息进行处理的函数, 因此不具备修改系统自动添加菜单项的功能。(BCMENU有这功能,而且工作的不错)
  2. 作者提到的 BCMENU 不用映射 WM_DRAWITEM 和 WM_MEASUREITEM 两个消息就能实现自画功能,实际上是错误的。不映射这两个重要的消息,即使能自绘,也是有问题的,不信看图。
    菜单编辑器中的模菜单样

    使用BCMENU并且映射了这两个消息后的执行情况



    使用BCMENU没有映射两个消息的执行情况



      原作者分析的自绘的是因为把主菜单(top-level menu)的子菜单都加载成弹出菜单(popupmenu),是不正确的。真正的原因是因为MFC框架会自动调用CMenu的两个虚拟函数MeasureItem()和OnDrawItem()。 因此,当CMenuEx派生于CMenu,并且重写这两个虚拟函数以后。

    1、MFC框架调用的GetMenu()->MeasureItem()就相当于调用了CMenuEx::MeasureItem(),从而实现自绘菜单控件尺寸的测量。
    2、MFC框架调用GetMenu()->DrawItem()就相当于调用了CMenuEx::DrawItem()来实现自绘菜单控件的自绘操作(不懂??,这正是C++的虚拟的妙用,指向派生类对象的基类指针可以调用派生类的虚拟函数,多么伟大的发明,谁想出来的???)。与子菜单是否为弹出菜单(popupmenu)没有什么关系。以下是摘自WINCORE.CPP的一段程序,也就是WM_MEASUREITEM消息的默认流向的地方,相信大家会从中看出一些端倪。
    void CWnd::OnMeasureItem(int /*nIDCtl*/, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
    {
    if (lpMeasureItemStruct->CtlType == ODT_MENU)
    {
    ......
    // 如果没有主菜单
    if (pThreadState->m_hTrackingWindow == m_hWnd)
    {
    ......
    }
    else
    {
    // 如果有主菜单
    pMenu = GetMenu();  // 找到窗体的主菜单,注意,pMenu的是CMenu* 类型
    }
    // 在当前菜单中寻找ID匹配的菜单项
    pMenu = _AfxFindPopupMenuFromID(pMenu, lpMeasureItemStruct->itemID);
    if (pMenu != NULL)			
    // 如果找到,就调用MeasureItem()
    // 这就是所谓的基类指针指向派生类对象,可以调用派生类虚拟函数的情况了
    pMenu->MeasureItem(lpMeasureItemStruct);  
    else
    TRACE1("Warning: unknown WM_MEASUREITEM for menu item 0x%04X./n",
    lpMeasureItemStruct->itemID);
    }
    else
    {
    ......
    }
    ......
    }        
  3. 当菜单项中含有子菜单(submenu),而不含有分割条的时候,子菜单项的高度不可调。原因为原CMenuEx程序中将分割条的原COMMAND ID(0)改为菜单项的COMMADN ID(-1), 以欺骗MFC框架调用CMenuEx::MeasureItem()来计算子菜单项(submenu)的高度。(很令我失望,这也是促使我自己动手重写该类的原因之一。不信看程序,看图)
    摘录自原CMenuEx.cpp第546-560行
    if(uID == 0) //分隔符
    {
    ::AppendMenu(hNewMenu,MF_SEPARATOR,0,NULL);
    ......
    // 注意,就是下面那个-1,把分割条的ID从0改到-1,
    // 从而是MFC框架误以为找到了ID为-1的菜单项,并且测量了它的尺寸
    // 而实际上ID为-1的菜单项是不可能被void CWnd::OnMeasureItem()找到的
    ::ModifyMenu(hNewMenu,i,MF_BYPOSITION | MF_OWNERDRAW,-1,(LPCTSTR)pMenuItem);
    }        
    菜单编辑器中没有分割条菜单的菜单



    原CMenuEx执行的模样



    菜单编辑器中有分割条菜单的菜单



    原CMenuEx执行的模样



  4. 代码不够简练,程序粒度划分不好,可读性差(不过比BCMENU的代码可读性强多了:))。

二、解决问题

  针对以上遇到的问题,我参考BCMENU和原作者的CMenuEx,对CMenuEx类重新进行了组织,类定义如下:

// 声明,因为下面的结构要用到 CMenuEx*,又不支持向后引用,又什么办法啊!
class CMenuEx;
//自绘菜单数据项结构,就是要传给系统的那个牛X的LPCTSTR指针所指向的东东
class CMenuEx : public CMenu
{
DECLARE_DYNAMIC( CMenuEx )
// Constructor
public:	
CMenuEx();	
virtual ~CMenuEx();
virtual BOOL DestroyMenu();
// Operation
public:
// 加载菜单操作
BOOL LoadMenu(UINT nIDResource);
BOOL LoadMenu(LPCTSTR lpszResourceName);
BOOL LoadMenu(HMENU hMenu);
BOOL LoadMenu(CMenu & Menu);
// 菜单项操作,如果当前菜单为主菜单(top-level)就调用相应的CMenu的操作。如果是弹出菜单,
// 就将新加入的菜单项定义为自绘菜单
BOOL AppendMenu(UINT nFlags, UINT nIDNewItem = 0,LPCTSTR lpszNewItem = NULL);
BOOL InsertMenu(UINT nPosition,UINT nFlags,UINT nIDNewItem=0,LPCTSTR lpszNewItem=NULL );
BOOL ModifyMenu(UINT nPosition,UINT nFlags,UINT nIDNewItem=0,LPCTSTR lpszNewItem=NULL );	
BOOL RemoveMenu(UINT nPosition, UINT nFlags);	
// 加载菜单图像操作
//通过菜单索引表加载图像索引,此操作必须在设置过菜单图像后调用
void SetImageIndex(const UINT* nIDResource,UINT nIDCount);
void LoadToolBar(const CToolBar* pToolBar);// 通过工具栏加载图像,和图像索引
// 取自绘菜单项的数据项
UINT  GetMenuItemSize() const;
LPMENUITEM GetMenuItem(UINT nPosition);	
// 取子菜单操作,如果位置nPosition存在子菜单,返回该子菜单指针
// 如果不存在子菜单,返回NULL
CMenuEx* GetSubMenu(int nPosition);
// 在当前菜单和所以子菜单中中寻找相应ID
// 如果找到,返回ID所在菜单的指针,没找到返回NULL
CMenuEx* FindPopupMenuFromID(UINT nID);
// Attributes
protected:
// 指示为主菜单(top-level menu or menubar)还是弹出菜单(popupmenu)
BOOL m_bPopupMenu;
// 分割条的默认高度
int m_nSeparator;
// 绘制菜单需要的颜色
COLORREF m_crBackground;		// 菜单背景色	
COLORREF m_crTextSelected;		// 菜单项被选中时的文字颜色
COLORREF m_crText;			// 菜单项文字颜色
COLORREF m_crLeft;			// 菜单左侧的背景颜色
COLORREF m_crSelectedBroder;		// 菜单选中框的线条颜色
COLORREF m_crSelectedFill;		// 菜单选中框的填充颜色
// 菜单项图像的尺寸	
CSize m_szImage;
CImageList* m_pImageList;		// 菜单项正常的图像列表 
CImageList* m_pDisabledImageList;	// 菜单项禁用时的图像列表
CImageList* m_pHotImageList;		// 菜单项被选中时的图像列表
protected:
// 包含所有菜单项的数组
CArray m_MenuItemArr;
public:
// 设置颜色操作
void SetTextSelectedColor(COLORREF color);
void SetBackgroundColor(COLORREF color);
void SetTextColor(COLORREF color);
void SetLeftColor(COLORREF color);
void SetSelectedBroderColor(COLORREF color);
void SetSelectedFillColor(COLORREF color);
// 设置图像列表操作
void SetImageList(CImageList* pImageList);
void SetDisabledImageList(CImageList* pImageList);
void SetHotImageList(CImageList* pImageList);
// 设置当前菜单为主菜单还是弹出菜单
void SetPopupMenu(BOOL bPopupMenu);
// Implementation
public:
// 绘制菜单项的虚拟函数,由MFC框架自动调用
virtual void DrawItem(LPDRAWITEMSTRUCT lpDIS);
// 更新弹出菜单菜单项操作
// 因为有时候系统会通过菜单句柄插入一些非自绘菜单
// 该函数就是更新这些非自绘菜单为自绘菜单
void UpdatePopupMenu();
protected:
// 绘制菜单项的辅助函数,想自己的菜单看上去更COOL,就拿他们开刀
void DrawBackground(CDC* pDC,CRect rect);
void DrawMenuImage(CDC* pDC,CRect rect,LPDRAWITEMSTRUCT lpDIS);
void DrawMenuText(CDC*  pDC,CRect rect,LPDRAWITEMSTRUCT lpDIS);
void DrawSelected(CDC*  pDC,CRect rect,LPDRAWITEMSTRUCT lpDIS);
// Static Member
public:
// 在CMainFrame的OnMeasureItem()消息映射函数中调用它,用来测量所有菜单项尺寸
static void MeasureItem(LPMEASUREITEMSTRUCT lpMIS);
// 在CMainFrame的OnInitPopupMenu()消息映射函数中调用它,
// 用来更新系统自动添加的菜单项为自绘菜单
static void InitPopupMenu(CMenu* pPopupMenu,UINT nIndex,BOOL bSystem);
};
#endif // !defined(MENUEX_H)      
三、实现方法

  有了以上的强有力的武器,就可以对我们的程序下手了:)在MDI或SDI中使用CMenuEx的时候需要修改以下地方。
  1. 先将MenuEx.h和MenuEx.cpp添加到工程中,在CMainFrame中添加头文件,CMenuEx对象,用于存储菜单图像的CImageList对象和初始化菜单程序。
    #include "MenuEx.h" // 添加头文件
    class CMainFrame : public CMDIFrameWnd
    {
    ...
    public:
    HMENU InitMainFrameMenu();		// 初始化主菜单
    HMENU InitImageTypeMenu();		// 初始化文档模板菜单
    protected:  // CMenuEx members
    CMenuEx  m_menuMainFrame;		// 主窗体没有打开任何文档时菜单
    CMenuEx  m_menuImageType;		// 主窗体打开文档时菜单(文档模板菜单)
    protected:  // CMenuEx''s image list members	
    CImageList	m_imageMenu;		// 菜单项正常的图像列表 
    CImageList	m_imageMenuDisable;	// 菜单项禁用时的图像列表
    CImageList	m_imageMenuHot;		// 菜单项被选中时的图像列表
    ...
    }        
  2. 撰写菜单图像索引表,初始化菜单程序,初始化菜单图像列表程序, 和两个重要的消息映射函数CMainFrame::OnMeasureItem()和CMainFrame::OnInitPopupMenu()。 (什么?不会添加!,找ClassWizard帮忙或许有点帮助了:))
    // 声明,因为下面的结构要用到 CMenuEx*,又不支持向后引用,又什么办法啊!
    class CMenuEx;
    //自绘菜单数据项结构,就是要传给系统的那个牛X的LPCTSTR指针所指向的东东
    typedef struct tagMENUITEM
    {
    CString		strText;		// 菜单名称
    UINT		nID;		// 菜单ID号
    // 分割条的ID是 0
    // 子菜单的ID是 -1
    CSize		itemSize;		// 菜单项的尺寸,不包括菜单图像的尺寸
    CImageList*     pImageList;		// 菜单项的正常图像列表
    CImageList*     pDisabledImageList;	// 菜单项的禁用图像列表
    CImageList*     pHotImageList;	// 菜单项的选中图像列表
    UINT		nImageIndex;	// 菜单项的图像列表索引,-1表示没有图像
    BOOL		bIsSubMenu;		// 表示当前菜单项是否为子菜单项
    CMenuEx*	pSubMenu;		// 如果是一般菜单,该值为NULL
    // 如果bIsSubMenu为TRUE,该值为指向子菜单项的CMenuEx*指针
    } MENUITEM,*LPMENUITEM;
    ///
    // 在ManiFram.cpp 中添加菜单图像索引表
    static UINT nMenuImageIndex[] =
    {
    ID_FILE_OPEN,
    ID_FILE_SAVE,
    ID_FILE_PRINT,		
    ID_EDIT_COPY,
    ID_EDIT_PASTE,	
    ID_EDIT_UNDO,
    ID_EDIT_REDO,		
    ID_APP_ABOUT,
    ID_IMAGE_LEVEL,
    ID_IMAGE_EQUALIZE,		
    ID_IMAGE_SMOOTH,
    ID_IMAGE_SHARP,		
    ID_IMAGE_SIZE,
    ID_IMAGE_RA,		
    ID_IMAGE_HISTOGRAM,		
    ID_ZOOMOUT,
    ID_ZOOMIN,
    };
    /
    // 在ManiFram.cpp 中添加初始化菜单程序
    void CMainFrame::InitMenuImage()
    {
    // 初始化菜单图像列表
    CBitmap bm;	
    m_imageMenu.Create(20, 20, TRUE | ILC_COLOR24, 9, 0);
    // 要问我IDB_SMALLMENUCOLOR是什么,当然是是真彩位图了,看图说话了
    bm.LoadBitmap(IDB_SMALLMENUCOLOR);    
    m_imageMenu.Add(&bm,(CBitmap*)NULL);
    bm.Detach();
    // 还有IDB_SMALLMENUDISABLE
    m_imageMenuDisable.Create(20, 20, TRUE | ILC_COLOR24, 9, 0);
    bm.LoadBitmap(IDB_SMALLMENUDISABLE);    
    m_imageMenuDisable.Add(&bm,(CBitmap*)NULL);
    bm.Detach();
    // 还有IDB_SMALLMENUHOT
    m_imageMenuHot.Create(20, 20, TRUE | ILC_COLOR24, 9, 0);
    bm.LoadBitmap(IDB_SMALLMENUHOT);    
    m_imageMenuHot.Add(&bm,(CBitmap*)NULL);
    bm.Detach();	
    }
    /*
    IDB_SMALLMENUCOLOR
      	
    IDB_SMALLMENUHOT
    		  			
    IDB_SMALLMENUDISABLE
    					        
    当然,要通过资源编辑器的Import功能将他们导入到资源文件中,不过因为是真彩,所以不能用VC的图片编辑器编辑了。 告诉大家个敲门,我是用windows自带的画笔画的:)
    */
    /
    // 在ManiFram.cpp 中添加初始化菜单图像列表程序
    int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
    // 在CMainFrame::OnCreate中调用菜单图标初始化程序
    。。。。。。
    InitMenuImage();
    。。。。。。
    }
    /
    HMENU CMainFrame::InitMainFrameMenu()
    {	
    //初始化主菜单	
    m_menuMainFrame.LoadMenu(IDR_MAINFRAME);
    {
    // 这只加载图像的一种方法,是一种两步方法,先加载图像列表
    m_menuMainFrame.SetImageList(&m_imageMenu);
    m_menuMainFrame.SetDisabledImageList(&m_imageMenuDisable);
    m_menuMainFrame.SetHotImageList(&m_imageMenuHot);
    // 再通过菜单图像索引表为菜单加载图像索引,
    m_menuMainFrame.SetImageIndex(nMenuImageIndex,
    sizeof(nMenuImageIndex)/sizeof(UINT));	
    }
    // 也可以使用另外一种一步方法加载图像
    /*
    // 假设MAINFRAM具有m_wndToolBar成员,并且已经设置了真彩位图
    // 关于设置工具栏的真彩位图,请参考 http://www.vckbase.com/document/viewdoc/?id=576
    // 或者看我的另外一篇文章 《完美实现真彩工具栏》(还没写出来那:))
    // 不过源程序里面已经有实现方法了
    // 自己看也可以明白的
    m_menuMainFrame.LoadToolBar(&m_wndToolBar);	
    */
    return m_menuMainFrame.Detach();
    }
    /
    HMENU CMainFrame::InitImageTypeMenu()
    {		
    // 初始化文档模板菜单
    m_menuImageType.LoadMenu(IDR_IMAGETYPE);
    m_menuImageType.SetImageList(&m_imageMenu);
    m_menuImageType.SetDisabledImageList(&m_imageMenuDisable);
    m_menuImageType.SetHotImageList(&m_imageMenuHot);
    //通过菜单图像索引表为菜单加载图像索引
    m_menuImageType.SetImageIndex(nMenuImageIndex,sizeof(nMenuImageIndex)/sizeof(UINT));
    return m_menuImageType.Detach();
    }
    /
    void CMainFrame::OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu) 
    {	
    // 记住,顺序一定不能反,因为有些MFC自动添加的菜单是在CMDIFrameWnd::OnInitMenuPopup()
    // 中添加的.
    // 如果反了,当然就找不到新加入的菜单了
    CMDIFrameWnd::OnInitMenuPopup(pPopupMenu, nIndex, bSysMenu);
    // 静态函数,看好了,别忘了写CMenuEx啊	
    CMenuEx::InitPopupMenu(pPopupMenu, nIndex, bSysMenu);	
    }
    /
    void CMainFrame::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct) 
    {
    // 都是她惹的祸"CMDIFrameWnd::OnMeasureItem()",不对子菜单项的尺寸进行测量
    // 害的我们只好映射这个函数了		
    CMDIFrameWnd::OnMeasureItem(nIDCtl, lpMeasureItemStruct);
    // 静态函数,看好了,别忘了写CMenuEx啊
    CMenuEx::MeasureItem(lpMeasureItemStruct);
    }       
  3. 在CXXXApp::InitInstance()中添加代码,XXX代表你自己的程序了
    BOOL CXXXApp::InitInstance()
    {
    ......
    CMultiDocTemplate* pDocTemplate;
    pDocTemplate = new CMultiDocTemplate(
    IDR_IMAGETYPE,
    RUNTIME_CLASS(CImageDoc),
    RUNTIME_CLASS(CChildFrame), // custom MDI child frame
    RUNTIME_CLASS(CImageView));
    AddDocTemplate(pDocTemplate);
    // create main MDI Frame window
    CMainFrame* pMainFrame = new CMainFrame;
    if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
    return FALSE;
    m_pMainWnd = pMainFrame;
    // 这些才是要添加的代码,别弄错了
    // 初始化文档模板菜单
    pDocTemplate->m_hMenuShared=pMainFrame->InitImageTypeMenu();	
    // 初始化主窗体菜单
    pMainFrame->m_hMenuDefault=pMainFrame->InitMainFrameMenu();	
    // 更新,具体干什么没研究,反正不调用就出错了:)
    pMainFrame->OnUpdateFrameMenu(pMainFrame->m_hMenuDefault);	
    // 要添加的代码到这结束	
    ......
    }        

三、总结

说了这么多,也不知道大家看明白没有,没关系,先贴个图,大家看看效果再说了。

效果图一,使用图像索引表加载的小图标菜单



效果图一,工具条加载的大图标菜单



四、结束语

  感谢querw和BCMenu的作者,没有他们的辛勤劳动,后人是没办法站在他们肩膀上的!由于程序写的匆忙,难免有不尽人意和错误的地方,欢迎大家任意修改源程序:) 要说这个菜单做的完美,那是吹牛,世界上哪有完美的东西啊 :) 只要自己觉得完美,就够了。 希望大家能从文章中学到点东西,就好。
 

http://www.jmfq.cn/news/5052115.html

相关文章:

  • 手机链接ppt在哪个网站做/网站外链的优化方法
  • 石家庄网站建设/seo培训优化课程
  • 商城购物网站有哪些模块/东莞整站优化
  • 厦门企业官方网站建设/竞价推广遇到恶意点击怎么办
  • 精灵网站建设/免费的推广网站
  • 网站建设龙岗/seo在线短视频发布页
  • 网站建设歺金手指排名15/厦门seo网站排名优化
  • 营销型网站有什么特点/网络营销与网站推广的
  • 张掖做网站公司/做seo如何赚钱
  • 网站还没上线 可以对网站备案吗/国内营销推广渠道
  • 做阿胶上什么网站比较好/宁波网站优化公司推荐
  • 澳大利亚网站设计/百度seo关键词排名s
  • 投资20万做网站好吗/中国培训网
  • dede网站301怎么做/2022年五月份热点事件
  • 学校营销型网站/网络营销竞价推广
  • ps怎么做网站首页界面/大数据营销名词解释
  • 做网站如何处理并发问题/qq群引流推广平台免费
  • 装饰公司看的设计网站/seo关键词优化举例
  • 临沂企业建站系统模板/seo系统是什么意思
  • 论坛网站制作/手机怎么做网站免费的
  • 江苏seo推广网站建设/怎么做互联网营销推广
  • 电子商务有限公司/360seo优化
  • 做网站怎么跟客户谈话/114啦网址导航官网
  • 门户网站建设 管理 自查报告/市场营销策划方案模板
  • 企业网站信息管理系统/百度seo排名点击软件
  • 做问卷赚钱的网站/百度推广的优势
  • 云匠网接单靠谱么/seo网站快速排名
  • 青岛网站权重提升/搜索引擎营销方案例子
  • 程序员自己做项目的网站/应用市场
  • 基金会网站开发方案/平台推广文案