MFC中菜单栏的重绘方法

经常在网上闲转,发现很多vc热衷着发贴询问在MFC中菜单栏如何重绘,这几天有点闲工夫,写了一个关于MFC菜单重绘的demo,写的很粗糙,很多小细节的地方都没有去仔细处理,希望能对大家有所帮助吧,呵呵也以此抛砖引玉吧。呵呵废话不说了吧,进入正题。
  对于菜单如何重绘网上到处都是,在这里就不再罗嗦了,呵呵
  对于一个菜单栏如何重绘,我们需要做的第一步工作就是如何不让系统默认的画菜单栏操做去执行。其实解决这个问题很简单,我们只需要处理一下windows的一个消息即可,也就是WM_NCHITTEST消息,WM_NCHITTEST消息返回值(HTMENU)有很多种,其中一个就是告诉系统鼠标是不是在菜单上,我们把这个返回值给屏蔽掉,不让它返回这个值,我拦截这个消息让它返回一个1即可。这样我们就做到了不让系统去做他默认处理菜单的事情了,呵呵。
e.g
if(message == WM_NCHITTEST)
{
     LRESULT lRet = T::WindowProc(message, wParam, lParam);
     if (lRet == HTMENU)
     {
        return 1;
     }
     return lRet;
}
  紧接着下来的工作就是我们自己要绘制我们想要的菜单栏了。在这里一个非常关键Win32 API  GetMenuBarInfo,通过这个函数我们去获取菜单栏响应位置信息
如何使用这个函数,详细使用方法见MSDN,我就不详细介绍了,读者自己去看,通过这个API我们就获取了我们想需要得到的信息了,下来就绘制了。

e.g

MENUBARINFO __getMenuBarInfo(long idItem)
{
  MENUBARINFO _menuBarInfo;
  _menuBarInfo.cbSize = sizeof(MENUBARINFO);
  GetMenuBarInfo(OBJID_MENU, idItem, &_menuBarInfo);
  return _menuBarInfo;
}

如何去绘制我们的菜单栏呢,我们需要处理一下几个消息:
WM_KICKIDLE
WM_MOUSELEAVE
WM_NCHITTEST
WM_GETDLGCODE
WM_ACTIVATE
WM_NOTIFY
WM_NCPAINT
WM_LBUTTONDOWN
WM_ENTERIDLE
详细的处理过成见代码吧,我就不详细介绍了,如果有更好的方法来处理菜单栏重绘的方法希望告诉我一声,呵呵。下面附上完整代码:

e.g
template<class T >
class CODrawMenuBar : public T
{
public:
        CODrawMenuBar(void)
        {
                m_btrackPopupMenu = m_bMouseOver = FALSE;
       
                m_MenuItemPos = -2;
                m_trackPopuMenu = -1;
        };

        CODrawMenuBar(UINT nID, CWnd* pParent) : T(nID, pParent)
        {
                m_btrackPopupMenu = m_bMouseOver = FALSE;
                m_MenuItemPos = -2;
                m_trackPopuMenu = -1;
        }

        CODrawMenuBar(UINT nID) : T(nID)
        {
                m_btrackPopupMenu = m_bMouseOver = FALSE;
                m_MenuItemPos= -2;
                m_trackPopuMenu = -1;
        }
public:
        ~CODrawMenuBar(void){};
private:
        BOOL m_bMouseOver;
        int m_MenuItemPos;
        BOOL m_btrackPopupMenu;
        int m_trackPopuMenu;
protected:
        /*
                对于菜单栏重绘关键在于:第一禁止系统默认的画操作,要控制这个我们必须同伙WM_NCHITTEST消息
                来控制不让系统重绘菜单栏。
                                        第二如何响应原有系统菜单消息。
        */
        virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
        {
   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
MFC,我们可以通过对窗口的WM_NCPAINT、WM_PAINT、WM_ERASEBKGND等消息进行处理来实现重绘标题栏和菜单栏。 首先,我们需要在类的声明添加自定义消息。例如: #define WM_CUSTOM_TITLEBAR_REDRAW WM_USER+1 //自定义消息,重绘标题栏 #define WM_CUSTOM_MENUBAR_REDRAW WM_USER+2 //自定义消息,重绘菜单栏 然后在窗口创建时,通过对NC_PAINT和WM_PAINT消息的处理来实现标题栏和菜单栏重绘。例如: void CMyFrameWnd::OnNcPaint() { //获取窗口的DC CDC* pDC = GetWindowDC(); //重绘标题栏 SendMessage(WM_CUSTOM_TITLEBAR_REDRAW, (WPARAM)pDC->m_hDC); //重绘菜单栏 SendMessage(WM_CUSTOM_MENUBAR_REDRAW, (WPARAM)pDC->m_hDC); //释放DC ReleaseDC(pDC); } void CMyFrameWnd::OnPaint() { CPaintDC dc(this); //绘制标题栏 SendMessage(WM_CUSTOM_TITLEBAR_REDRAW, (WPARAM)dc.m_hDC); //绘制菜单栏 SendMessage(WM_CUSTOM_MENUBAR_REDRAW, (WPARAM)dc.m_hDC); } 接下来,我们需要在窗口的消息映射添加对自定义消息的处理。例如: BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd) ON_MESSAGE(WM_CUSTOM_TITLEBAR_REDRAW, OnCustomTitlebarRedraw) //重绘标题栏 ON_MESSAGE(WM_CUSTOM_MENUBAR_REDRAW, OnCustomMenubarRedraw) //重绘菜单栏 END_MESSAGE_MAP() LRESULT CMyFrameWnd::OnCustomTitlebarRedraw(WPARAM wParam, LPARAM lParam) { HDC hDC = (HDC)wParam; //在hDC上重绘标题栏 ... return 0; } LRESULT CMyFrameWnd::OnCustomMenubarRedraw(WPARAM wParam, LPARAM lParam) { HDC hDC = (HDC)wParam; //在hDC上重绘菜单栏 ... return 0; } 通过以上步骤,我们就可以实现对MFC窗口标题栏和菜单栏重绘。当然,具体的重绘方式和效果可以根据实际需求进行调整和优化。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值