CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
IBM Rational 系统开发最佳实践工具包 WebSphere MQ 最佳实践 TOP 15
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  VC/MFC >  界面

自绘菜单的问题,怎么WM_MEASUREITEM中设置的菜单大小不起作用???

楼主hawkxjy(developer)2006-03-15 13:25:30 在 VC/MFC / 界面 提问

想把菜单的背景色和字体颜色做个修改,要设置MF_OWNERDRAW属性,并响应WM_MEASUREITEM消息来设置各个item的大小,同时还有WM_DRAWITEM来画。  
  可奇怪的是我在WM_MEASUREITEM中设置的大小根本不起作用!!!另外弹出的菜单总是边框的一小部分无法刷上我所设置的颜色?  
   
  部分代码:  
  switch(cwps.message)  
  {  
  case   WM_INITMENUPOPUP:  
  {  
  HMENU hMenu   =   (HMENU)cwps.wParam;  
  int   nCount   =   GetMenuItemCount(hMenu);  
  for(   int   i   =   0;   i   <   nCount;   ++i   )  
  {  
  UINT   nId   =   GetMenuItemID(hMenu,   i);  
  ModifyMenu(hMenu,   i,   MF_BYPOSITION|MF_OWNERDRAW,   nId,   (LPCSTR)cwps.lParam);       //   改变菜单的自绘属性  
  }  
  }  
  break;  
  case   WM_MEASUREITEM:  
  {  
  LPMEASUREITEMSTRUCT lpmis   =   (LPMEASUREITEMSTRUCT)cwps.lParam;  
  if(   lpmis->CtlType   ==   ODT_MENU   )  
  {  
  lpmis->itemHeight   =   30;     //   设置大小,却不起作用???!!!  
  lpmis->itemWidth   =   150;  
   
  return   0;  
  }  
  }  
  break;  
  case   WM_DRAWITEM:  
  {  
  COLORREF   clrSel,   clrUnSel;  
  COLORREF   clrBkSel,   clrBkUnSel;  
  LPDRAWITEMSTRUCT lpdis   =   (LPDRAWITEMSTRUCT)cwps.lParam;  
  if(   lpdis->itemState   &   ODS_SELECTED   )  
  {  
  clrSel   =   SetTextColor(lpdis->hDC,   RGB(255,   0,   0));  
  FillRect(lpdis->hDC,   &lpdis->rcItem,   (HBRUSH)GetStockObject(WHITE_BRUSH));  
  }  
  else  
  {  
  clrUnSel   =   SetTextColor(lpdis->hDC,   RGB(0,   255,   0));  
  FillRect(lpdis->hDC,   &lpdis->rcItem,   (HBRUSH)GetStockObject(BLACK_BRUSH));  
  }  
  TextOut(lpdis->hDC,   lpdis->rcItem.left+13,   lpdis->rcItem.top,   "Good",   4);  
  }         //   得到的UI显示有些异常,菜单项的边框部分总是有一点点灰色,不是自定义的颜色!!??  
  return   0;  
   
   
  求高手指点~~~~ 问题点数:100、回复次数:9Top

1 楼ringphone(临风)回复于 2006-03-15 14:01:28 得分 50

WM_MEASUREITEM里面设置了大小需要返回TRUE而不是0。  
  菜单项的边框部分总是有一点点灰色,不是自定义的颜色,这是正常的,因为菜单也是一个窗口,是有边框的,不得到其窗口句柄,你没办法为窗口边框上色。  
  菜单的窗口比较特殊,没办法用FindWindow等函数得到其窗口句柄,因此要想得到窗口句柄给其边框上色,必须用HOOK勾WH_CALLWNDPROC,替换其窗口过程才行。Top

2 楼hawkxjy(developer)回复于 2006-03-15 17:28:41 得分 0

ringphone(临风)老兄,谢谢你的提示。不过当我把返回值改为TRUE后(包括   WM_DRAWITEM的返回值),结果还是一样啊!大小仍然不起作用!!!?  
  另外,和老兄想的一样,俺晓得需要HOOK一下才能改变菜单边框的颜色,我可以通过HOOK拿到菜单的HWND,可这咋去改窗口边框呢?  
   
   
  能不能给个例子啊??Top

3 楼ringphone(临风)回复于 2006-03-16 09:09:19 得分 0

The   WM_INITMENUPOPUP   message   is   sent   when   a   drop-down   menu   or   submenu   is   about   to   become   active.   This   allows   an   application   to   modify   the   menu   before   it   is   displayed,   without   changing   the   entire   menu  
   
  估计不能在WM_INITMENUPOPUP消息里面设置自绘,你改在WM_CREATE里面试试。  
   
  HOOK是要替换菜单的窗口过程,在其WM_NCPAINT里面给边框上色。具体例子可以找一下XP样式菜单,网上有很多这样的代码。Top

4 楼laiyiling(陌生人[MVP])回复于 2006-03-16 09:34:45 得分 20

自画菜单的WM_MEASUREITEM只会发送一次Top

5 楼hawkxjy(developer)回复于 2006-03-16 11:25:41 得分 0

楼上两为说的都对,不过在WM_INITMENUPOPUP消息里面是可以设置自绘属性的,并且可以截获WM_MEASUREITEM消息,只是设置的大小在WM_DRAWITEM里就是看不到啊!  
   
  我试着在WM_CREATE里做了属性的设置,其结果还是一样~~~~郁闷啊---------  
  Top

6 楼LongLongAgoImBoy(ThereIsAMe)回复于 2006-03-16 11:45:10 得分 30

自绘菜单      
  闻怡洋译      
  --------------------------------------------------------------------------------  
  在这里提供一个C++类(CCustomMenu),该类是CMenu的子类,并且拥有自绘能力。它可以向你提供以下的功能:    
  设置字体颜色。    
  设置高亮度颜色。    
  设置高亮度时的风格。    
  设置选中时和在普通状态下的菜单显示的图标。    
  设置显示图标大小。    
  在CCustomMenu中定义了结构MENUDATA,你必须根据你的需要填充该结构,并且在增加菜单时提供该结构的指针(调用AppendMenu,InsertMenu)。下面是一个例子:  
  1、定义CCustomMenu的实例,和MENUDATA结构变量。  
  CCustomMenu   m_cCustomMenu;  
  MENUDATA   menuData   [8]; //   as   many   menu   items   are   present   ,   You   should   be   able   to   use    
  //new   and   do   the   same  
  2、调用CreateMenu()设置有关参数。  
  m_customMenu.CreateMenu   ();  
  m_customMenu.SetIconSize   (25,25); //This   is   to   set   the   size   of   the   Icon.    
  //   This   should   be   used   only   once   for   any   menu  
  //   in   order   to   resize   it,   destroy   and   create   the   menu   again   with     different   size.  
  m_customMenu.SetHighlightStyle   (Normal);   //Or   TextOnly,   if   you   want   the  
  //   background   color   to   remain   the   same  
  //   and   the   Text   color   to   change   to   the   Highlight   color.  
                  //   The   following   setXXXColor   sets   the   menu   colors.   If   you   dont   want   to   change   any,   Dont   call   these   member   functions.    
                m_customMenu.SetTextColor   (RGB   (255,0,0));  
                m_customMenu.SetBackColor   (RGB   (255,255,255));  
                m_customMenu.SetHighlightColor   (RGB   (0,0,255));  
  3、设置MENUDATA变量,并增加菜单项。    
          lstrcpy   (menuData[0].menuText   ,   "text1");  
          menuData[0].menuIconNormal=   IDI_ICON1;  
          m_customMenu.AppendMenu   (MF_OWNERDRAW,3,(LPCTSTR)menuData);  
  3、在你的窗口中重载OnMeasureItem(...)函数。  
  void   CMyView::OnMeasureItem(int   nIDCtl,   LPMEASUREITEMSTRUCT   lpMeasureItemStruct)  
  {  
  if   (   lpMeasureItemStruct->CtlType   ==   ODT_MENU   &&  
  IsMenu((HMENU)lpMeasureItemStruct->itemID)   &&  
  (lpMeasureItemStruct->itemID   ==   (UINT)m_hMenuSub)   )  
  {  
  m_customMenu.MeasureItem   (lpMeasureItemStruct);  
  }  
  else  
  //   let   MFC's   self-drawing   handle   it  
  CView::OnMeasureItem(nIDCtl,   lpMeasureItemStruct);  
  }  
   
  下面的函数将帮助你设置菜单属性。  
  void   SetTextColor   (COLORREF   );  
  void   SetBackColor   (COLORREF);  
  void   SetHighlightColor   (COLORREF);  
  void   SetIconSize   (int,   int);  
  void   SetHighlightStyle   (HIGHLIGHTSTYLE   );   //   HIGHLIGHTSTYLE   :   enum   {Normal,   TextOnly}  
  void   SetHighlightTextColor   (COLORREF);  
   
  下面是文件代码:  
  //*************************************************************************  
  //   CustomMenu.h   :   header   file  
  //  
  #if  
  !defined(AFX_CUSTOMMENU_H__FE5B01C3_1E02_11D1_B87A_0060979CDF6D__INCLUDED_)  
  #define   AFX_CUSTOMMENU_H__FE5B01C3_1E02_11D1_B87A_0060979CDF6D__INCLUDED_  
   
  #if   _MSC_VER   >=   1000  
  #pragma   once  
  #endif   //   _MSC_VER   >=   1000  
  class   MENUDATA  
  {  
  public:  
  MENUDATA   ()   {   menuIconNormal   =   -1;   menuIconSelected   =   -1;};  
  char     menuText[32];  
  UINT   menuIconNormal;  
  UINT   menuIconSelected;  
  };  
   
  typedef   enum   {Normal,TextOnly}   HIGHLIGHTSTYLE;  
  ///////////////////////////////////////////////////////////////////////////  
  //  
  //   CCustomMenu   window  
  class   CCustomMenu   :   public   CMenu  
  {  
  //   Construction  
  public:  
  CCustomMenu();  
  //   Attributes  
  public:  
  //   Operations  
  public:  
  //   Overrides  
  //   ClassWizard   generated   virtual   function   overrides  
  //{{AFX_VIRTUAL(CCustomMenu)  
  //}}AFX_VIRTUAL  
  //   Implementation  
  public:  
  virtual   ~CCustomMenu();  
  virtual   void   DrawItem(   LPDRAWITEMSTRUCT);  
  virtual   void   MeasureItem(   LPMEASUREITEMSTRUCT   );  
  void   SetTextColor   (COLORREF   );  
  void   SetBackColor   (COLORREF);  
  void   SetHighlightColor   (COLORREF);  
  void   SetIconSize   (int,   int);  
  void   SetHighlightStyle   (HIGHLIGHTSTYLE   );  
  void   SetHighlightTextColor   (COLORREF);  
  //   Generated   message   map   functions  
  protected:  
  COLORREF   m_crText;  
  COLORREF   m_clrBack;  
  COLORREF   m_clrText;  
  COLORREF   m_clrHilight;  
  COLORREF   m_clrHilightText;  
  LOGFONT   m_lf;  
  CFont   m_fontMenu;  
  UINT   m_iMenuHeight;  
  BOOL   m_bLBtnDown;  
  CBrush   m_brBackground,m_brSelect;  
  CPen   m_penBack;  
  int   m_iconX,m_iconY;  
  HIGHLIGHTSTYLE   m_hilightStyle;  
  //{{AFX_MSG(CCustomMenu)  
  //   NOTE   -   the   ClassWizard   will   add   and   remove   member   functions   here.  
  //}}AFX_MSG  
  };  
  ///////////////////////////////////////////////////////////////////////////  
  //  
  //{{AFX_INSERT_LOCATION}}  
  //   Microsoft   Developer   Studio   will   insert   additional   declarations   immediately   before   the   previous   line.  
  #endif   //!defined(AFX_CUSTOMMENU_H__FE5B01C3_1E02_11D1_B87A_0060979CDF6D__INCLUDED_)  
  Top

7 楼LongLongAgoImBoy(ThereIsAMe)回复于 2006-03-16 11:45:22 得分 0

 
  //*************************************************************************  
  //   CustomMenu.cpp   :   implementation   file  
  //  
  #include   "stdafx.h"  
  #include   "CustomMenu.h"  
  #ifdef   _DEBUG  
  #define   new   DEBUG_NEW  
  #undef   THIS_FILE  
  static   char   THIS_FILE[]   =   __FILE__;  
  #endif  
   
  ///////////////////////////////////////////////////////////////////////////  
  //  
  //   CCustomMenu  
  CCustomMenu::CCustomMenu()  
  {  
  m_clrText   =     GetSysColor   (COLOR_MENUTEXT);  
  m_clrBack   =   GetSysColor   (COLOR_MENU);  
  m_brBackground.CreateSolidBrush   (m_clrBack);  
  m_penBack.CreatePen   (PS_SOLID,0,m_clrBack);  
  m_crText   =   m_clrText;  
  m_bLBtnDown   =   FALSE;  
  m_iconX   = GetSystemMetrics   (   SM_CXMENUCHECK);  
  m_iconY   = GetSystemMetrics   (SM_CYMENUCHECK   );  
  m_clrHilight   =   GetSysColor   (COLOR_HIGHLIGHT);  
  m_brSelect.CreateSolidBrush   (m_clrHilight);  
  m_clrHilightText   =   GetSysColor   (COLOR_HIGHLIGHTTEXT);  
  ZeroMemory   ((PVOID)   &m_lf,sizeof   (LOGFONT));  
  NONCLIENTMETRICS   nm;  
  nm.cbSize   =   sizeof   (NONCLIENTMETRICS);  
  //Get   the   system   metrics   for   the   Captionfromhere  
  VERIFY   (SystemParametersInfo   (SPI_GETNONCLIENTMETRICS,0,&nm,0));    
  m_lf   =     nm.lfMenuFont;  
  m_iMenuHeight   =   nm.iMenuHeight;  
  m_fontMenu.CreateFontIndirect   (&m_lf);  
  }  
   
  CCustomMenu::~CCustomMenu()  
  {  
  if   ((HBRUSH)   m_brBackground   !=   NULL)  
  m_brBackground.DeleteObject   ();  
  if   ((HFONT)m_fontMenu   !=NULL)  
  m_fontMenu.DeleteObject   ();  
  if   ((HBRUSH)m_brSelect   !=   NULL)  
    m_brSelect.DeleteObject   ();  
  }  
  ///////////////////////////////////////////////////////////////////////////  
  //  
  //   CCustomMenu   message   handlers  
  void   CCustomMenu::DrawItem   (LPDRAWITEMSTRUCT   lpDIS)  
  {  
  ASSERT(lpDIS   !=   NULL);  
  CDC*   pDC   =   CDC::FromHandle(lpDIS->hDC);  
  CRect   rect;  
  HICON   hIcon;  
  COLORREF   crText   =   m_crText;  
  //   draw   the   colored   rectangle   portion  
  rect.CopyRect(&lpDIS->rcItem);  
  //   draw   the   up/down/focused/disabled   state  
  UINT   action   =   lpDIS->itemAction;  
  UINT   state   =   lpDIS->itemState;  
  CString   strText;  
  LOGFONT   lf;  
  lf   =   m_lf;  
  CFont   dispFont;  
  CFont   *pFont;  
  //GetWindowText(strText);  
  if   (lpDIS->itemData   !=   NULL)  
  {  
  strText   =   (((MENUDATA*)   (lpDIS->itemData))->menuText);  
  if   ((((MENUDATA   *)(lpDIS->itemData))->menuIconNormal)   ==   -1)  
  hIcon   =   NULL;  
  else   if   (state   &   ODS_SELECTED)  
  {  
  if   ((((MENUDATA   *)(lpDIS->itemData))->menuIconSelected)   !=   -1)  
  hIcon   =   AfxGetApp   ()->LoadIcon   (((MENUDATA   *)(lpDIS->itemData))->menuIconSelected);  
  else  
  hIcon   =   AfxGetApp()->LoadIcon   (((MENUDATA*)(lpDIS->itemData))->menuIconNormal);  
  }  
  else  
  hIcon   =   AfxGetApp()->LoadIcon   (((MENUDATA*)(lpDIS->itemData))->menuIconNormal);  
  TRACE1   ("Draw   for   %s\n",   strText);  
  }  
  else  
  {  
  strText.Empty();  
  hIcon   =   NULL;  
  }  
  if   (   (state   &   ODS_SELECTED)   )  
  {  
  //   draw   the   down   edges  
  CPen   *pOldPen   =   pDC->SelectObject   (&m_penBack);  
  //You   need   only   Text   highlight   and   thats   what   you   get  
  if   (m_hilightStyle   !=   Normal)  
  {  
  pDC->FillRect   (rect,&m_brBackground);  
  }  
  else  
  {  
  pDC->FillRect   (rect,&m_brSelect);  
  }  
  pDC->SelectObject   (pOldPen);  
  pDC->Draw3dRect   (rect,GetSysColor   (COLOR_3DHILIGHT),GetSysColor(COLOR_3DSHADOW));  
  lf.lfWeight   =   FW_BOLD;  
  if   ((HFONT)dispFont   !=   NULL)  
  dispFont.DeleteObject   ();  
  dispFont.CreateFontIndirect   (&lf);  
  crText   =   m_clrHilightText;  
  //While   selected   move   the   text   a   bit  
  TRACE0   ("SELECT,SELECTED\n");  
  }  
  else  
  {  
  CPen   *pOldPen   =   pDC->SelectObject   (&m_penBack);  
  pDC->FillRect   (rect,&m_brBackground);  
  pDC->SelectObject   (pOldPen);  
  //   draw   the   up   edges  
  pDC->Draw3dRect   (rect,m_clrBack,m_clrBack);  
  if   ((HFONT)dispFont   !=   NULL)  
  dispFont.DeleteObject   ();  
  dispFont.CreateFontIndirect   (&lf);   //Normal  
  TRACE0   ("SELECT,   NORMAL\n");  
  }  
  //   draw   the   text   if   there   is   any  
  //We   have   to   paint   the   text   only   if   the   image   is   nonexistant  
  if   (hIcon   !=   NULL)  
  {  
  if(DrawIconEx   (pDC->GetSafeHdc(),rect.left,rect.top,hIcon,  
  (m_iconX)?m_iconX:32,(m_iconY)?m_iconY:32,0,NULL,DI_NORMAL))  
  TRACE0("Wrote   the   icon   successfully\n");  
  else  
  TRACE0   ("SORRY.NOGO\n");  
  }  
  //This   is   needed   always   so   that   we   can   have   the   space   for   check   marks  
  rect.left   =   rect.left   +((m_iconX)?m_iconX:32);    
  if   (   !strText.IsEmpty())  
  {  
  // pFont->GetLogFont   (&lf);  
  int     iOldMode   =   pDC->GetBkMode();  
  pDC->SetBkMode(   TRANSPARENT);  
  pDC->SetTextColor(   crText);  
  pFont   =   pDC->SelectObject   (&dispFont);  
  TRACE1(   "About   To   DrawText   %s\n",strText);  
  pDC->DrawText   (strText,rect,DT_LEFT|DT_SINGLELINE|DT_VCENTER);  
  TRACE0("Done\n");  
  pDC->SetBkMode(   iOldMode   );  
  pDC->SelectObject   (pFont);   //set   it   to   the   old   font  
  }  
  dispFont.DeleteObject   ();  
  }  
  void   CCustomMenu::MeasureItem(   LPMEASUREITEMSTRUCT   lpMIS   )  
  {  
  CDC   *pDC   =   AfxGetApp()->m_pMainWnd->GetDC();  
  CFont*   pFont   =   pDC->SelectObject   (&m_fontMenu);  
  int   iconX   =   0,iconY=   0;  
  TEXTMETRIC   tm;  
  pDC->GetTextMetrics   (&tm);  
  pDC->SelectObject   (pFont);  
  AfxGetApp()->m_pMainWnd->ReleaseDC   (pDC);  
  if   (m_iconX)  
  iconX   =   m_iconX;  
  if   (m_iconY)  
  iconY   =   m_iconY;  
  lpMIS->itemWidth   =   iconX   +   tm.tmAveCharWidth   *     lstrlen(((MENUDATA*)(lpMIS->itemData))->menuText)   +10;  
  lpMIS->itemHeight   =   (iconY   >   (m_iMenuHeight+1))?iconY:m_iMenuHeight   +   1;  
  }  
  void   CCustomMenu::SetIconSize   (int   width,   int   height)  
  {  
  m_iconX   =   width;  
  m_iconY   =   height;  
  }  
  void   CCustomMenu::SetTextColor   (COLORREF   clrText)  
  {  
  m_crText   =   clrText;  
  }  
  void   CCustomMenu::SetBackColor   (COLORREF   clrBack)  
  {  
  m_clrBack   =   clrBack;  
  if   ((HBRUSH)m_brBackground   !=   NULL)  
  m_brBackground.DeleteObject   ();  
  m_brBackground.CreateSolidBrush   (clrBack);  
  }  
  void   CCustomMenu::SetHighlightColor   (COLORREF   clrHilight)  
  {  
  m_clrHilight   =   clrHilight;  
  if   ((HBRUSH)m_brSelect   !=   NULL)  
  m_brSelect.DeleteObject   ();  
  m_brSelect.CreateSolidBrush   (clrHilight);  
  }  
  void   CCustomMenu::SetHighlightTextColor   (COLORREF   clrHilightText)  
  {  
  m_clrHilightText   =   clrHilightText;  
  }  
  void   CCustomMenu::SetHighlightStyle   (HIGHLIGHTSTYLE   hilightStyle)  
  {  
  m_hilightStyle   =   hilightStyle;  
  }  
  //*************************************************************************  
     
  Top

8 楼hawkxjy(developer)回复于 2006-03-17 14:02:20 得分 0

好长的代码,现在菜单项大小的问题解决了;剩下的问题就是如何把菜单边上的那么一小部分刷上自定义的颜色。我用了WM_NCPAINT试过,不能够即刻刷新,效果不理想啊~~~  
   
  烦劳哪个大哥费神给点代码或意见,咋来把颜色刷上去呢??Top

9 楼hawkxjy(developer)回复于 2006-03-19 17:32:59 得分 0

还是没搞定边框绘制的问题Top

相关问题

  • 为什么“Edit1.Perform(WM_KEYDOWN,VK_BACK,1);”这句不起作用?
  • 如何关闭一个IE窗口?sendmessage(hwd,wm_close,0,0);不起作用
  • 菜单放入 Coolbar 后,菜单项的快捷键不起作用,如何解决?
  • sendmessage不起作用
  • onDraw不起作用?
  • include不起作用
  • SetWindowPos不起作用
  • JSTL不起作用
  • 界面难题:为什么属性页中弹出式菜单不起作用?(有内容)
  • 为什么我在基于对话框程序中的菜单更新函数不起作用?

关键词

  • 函数
  • 属性
  • 代码
  • ccustommenu
  • custommenu
  • 菜单
  • 边框
  • lpdis
  • measureitem
  • 设置

得分解答快速导航

  • 帖主:hawkxjy
  • ringphone
  • laiyiling
  • LongLongAgoImBoy

相关链接

  • Visual C++类图书
  • Visual C++类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo