zoukankan      html  css  js  c++  java
  • 实现自绘菜单

    为了实现菜单的自绘,花了我几个小时,其实真正解决后又发现很简单。实现菜单的自绘只需要三个步骤:

    第一步:将所有菜单项设置为MF_OWNERDRAW,即自绘模式

    第二步:在WM_MEASUREITEM消息中设置菜单项的大小

    第三步:在WM_DRAWITEM消息中进行菜单项的绘制

    问题首先出现在了第一步,我要绘制的是一个上下文菜单,即右键菜单,要将菜单项设置为MF_OWNERDRAW,需要用到ModifyMenu函数,起始由于ModifyMenu函数的参数设置错误,导致程序怎么也响应不了WM_MEASUREITEM和WM_DRAWITEM消息,所以建议在使用ModifyMenu时对返回值进行检查。

    void CMainWindow::OnRButtonDown(UINT nFlags, CPoint point) {     ClientToScreen(&point);     CMenu Menu;     Menu.LoadMenuW(IDR_MENU2);     CMenu *pMenu = Menu.GetSubMenu(0);     CString strText;     for (int i = 0; i < pMenu->GetMenuItemCount(); i++)     {         BOOL bModi = pMenu->ModifyMenuW(ID_123_456 + i, MF_BYCOMMAND|MF_OWNERDRAW, ID_123_456 + i);         if (!bModi)        {               TRACK("ModifyMenu fail!");        }         pMenu->GetMenuStringW(i, strText, MF_BYPOSITION);     }     pMenu->TrackPopupMenu(TPM_LEFTBUTTON|TPM_LEFTALIGN,         point.x,         point.y,         this); }

    第一步的问题解决后,接在在第二步的WM_MEASUREITEM消息中设置菜单项的大小:

    void CMainWindow::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpmis) {     //lpmis->itemWidth = ::GetSystemMetrics(SM_CYMENU) * 4;     lpmis->itemWidth = 150;     lpmis->itemHeight = ::GetSystemMetrics(SM_CYMENU); }  在WM_MEASUREITEM消息中设置的菜单项大小会传入WM_DRAWITEM消息中,然后再在WM_DRAWITEM消息中根据菜单项的大小来进行重绘。

    到第三步也遇到了几个问题,由于最初对WM_DRAWITEM消息中的LPDRAWITEMSTRUCT结构体不了解,以致写出的程序不管在什么时候都会作同一个绘制操作,先来看看WM_DRAWITEM消息的声明:

    afx_msg void CMainWindow::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpdis);

    在这个消息中有两个参数,在自绘菜单时,两个参数都要用到。其中nIDCtl,书上说是所属控件的ID,不太明白是什么意思,在MSDN看到,对于菜单发出的WM_DRAWITEM消息,nIDCtl为0。再说LPDRAWITEMSTRUCT结构体,该结构体中包含了菜单复选状态、选中状态以及菜单项的大小等信息。

    下面是OnDrawItem消息的实现代码:

    void CMainWindow::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpdis) {     CBrush *brush = new CBrush;     CPen *pen = new CPen;     CString strText;     CDC *pDC = CDC::FromHandle(lpdis->hDC); //获取菜单项的设备句柄     //菜单项是否为选中状态     if ((lpdis->itemState & ODS_SELECTED))     {         //在菜单项上自绘矩形框的背景颜色         brush->CreateSolidBrush(RGB(182, 189,210));         //在菜单项自绘矩形的边框颜色         pen->CreatePen(PS_SOLID, 1, RGB(10,36,106));         //设置菜单项的文字背景颜色         pDC->SetBkColor(RGB(182,189,210));     }     else     {         brush->CreateSolidBrush(GetSysColor(COLOR_MENU));         pen->CreatePen(PS_SOLID, 0, GetSysColor(COLOR_MENU));         pDC->SetBkColor(GetSysColor(COLOR_MENU));     }     pDC->SelectObject(pen);     pDC->SelectObject(brush);     //在当前菜单项上画一个矩形框     pDC->Rectangle(lpdis->rcItem.left,         lpdis->rcItem.top,         lpdis->rcItem.right,         lpdis->rcItem.bottom);     /*--------------------------------------*/     //获取当前消息所在菜单项的文本     CMenu menu;     menu.Attach((HMENU)lpdis->hwndItem);     menu.GetMenuStringW(lpdis->itemID, strText,MF_BYCOMMAND);     /*--------------------------------------*/     //如果为菜单发出的DrawItem消息     if (nIDCtl == 0)     {         //在菜单项上输出菜单文本         pDC->TextOutW(lpdis->rcItem.left + 20, lpdis->rcItem.top + 4, strText.GetBuffer(0), strText.GetLength());     }     menu.Detach();     delete brush;     delete pen; }

    效果图:

     

    参考资料:http://www.vckbase.com/document/viewdoc/?id=1583

  • 相关阅读:
    windows中echo的用法
    通过phpMyAdmin写入MySQL,获取webshell
    底部小鱼特效
    kali Linux的简单介绍
    Kali安装gmpy2
    利用kali生成字典的三种方式
    利用kali嗅探HTTP网页用户账户密码
    永恒之蓝(ms017-010)漏洞利用
    如何使用最新Microsoft Edge打开Flash页面
    结对第二次作业
  • 原文地址:https://www.cnblogs.com/lidabo/p/3060499.html
Copyright © 2011-2022 走看看