zoukankan      html  css  js  c++  java
  • MFC Ribbon UI 弹出菜单实现分析

    微软推出的Ribbon UI界面在应用程序开发上完全颠覆了以往的菜单+工具条的应用模式,非常有新颖性。Ribbon UI有一个弹出窗口功能让人感觉很疑惑,窗口截图如下:

    无标题

    通过spy4win工具抓取窗口信息发现这几个窗口都具有WS_POPUP属性,也就是说它是一个弹出窗口。支持鼠标、键盘按键,也有弹出窗口的特性“点窗口里面不会关闭,点外就会关闭”,让人疑惑的是这个弹出窗口还不会抢窗口焦点。理论上一个具有WS_POPUP属性的窗口一定要激活才能支持按键及点窗口外关闭这两个功能的,于是花了点时间研究了一下MFC 自带的Ribbon界面,分析了一下这个弹出窗口的实现原理,疑惑解决了。主要解决方法如下:

    第一步:创建一个具有WS_POPUP属性的窗口并以不激活的方式显示创建的窗口

    BOOL CMFCPopupMenu::Create(CWnd* pWndParent, int x, int y, HMENU hMenu, BOOL bLocked, BOOL bOwnMessage)
    {
    ……
    UINT nClassStyle = CS_SAVEBITS;
    CString strClassName = ::AfxRegisterWndClass(nClassStyle, ::LoadCursor(NULL, IDC_ARROW), (HBRUSH)(COLOR_BTNFACE + 1), NULL);
    ……
    DWORD dwStyle = WS_POPUP;
    if (m_pMenuCustomizationPage != NULL)
    {
    dwStyle |= (WS_CAPTION | WS_SYSMENU);
    }
    ……
    CRect rect(x, y, x, y);
    BOOL bCreated = CMiniFrameWnd::CreateEx(pWndParent->GetExStyle() & WS_EX_LAYOUTRTL, strClassName, m_strCaption,
    dwStyle, rect, pWndParent->GetOwner() == NULL ? pWndParent : pWndParent->GetOwner());
    ……
    SetWindowPos(&wndTop, -1, -1, -1, -1, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
    ……
    return TRUE;
    }

    第二步:设置鼠标点击时不激活窗口,实现了即支持鼠标事件又不强焦点的效果

    int CMFCPopupMenu::OnMouseActivate(CWnd* /*pDesktopWnd*/, UINT /*nHitTest*/, UINT /*message*/)
    {
    return MA_NOACTIVATE;
    }
     

    第三步:通过应用程序激活事件来关闭弹出窗口

    void CMFCPopupMenu::OnActivateApp(BOOL bActive, DWORD /*dwThreadID*/)
    {
    if (!bActive && !CMFCToolBar::IsCustomizeMode() && !InCommand())
    {
    if (m_bTrackMode)
    {
    m_bTobeDstroyed = TRUE;
    }

    PostMessage(WM_CLOSE);
    }
    }

    第四步:通过主窗口向弹出窗口发送键盘事件,实现了弹出窗口在不激活的时候还能处理按钮,在哪之前要确保弹出窗口时它的主窗口是激活的

    BOOL CFrameImpl::ProcessKeyboard(int nKey, BOOL* pbProcessAccel)
    {
    ……
    if (CMFCPopupMenu::m_pActivePopupMenu != NULL && ::IsWindow(CMFCPopupMenu::m_pActivePopupMenu->m_hWnd))
    {
    ……
    CMFCPopupMenu::m_pActivePopupMenu->SendMessage(WM_KEYDOWN, nKey);
    ……
    }
    ……
    }

    通过这四步就实现了可接收鼠标、键盘事件,又不抢焦点的弹出窗口。希望这个对一直被弹出窗口抢焦点这个问题困惑着的朋友有用。

  • 相关阅读:
    [BZOJ 2821] 作诗
    [P1084] 疫情控制
    [BZOJ 2243] 染色
    Session
    Jinja2 及 render_template 的深度用法
    request机制
    三件套
    初识flask
    mysql大法
    liunx命令大全
  • 原文地址:https://www.cnblogs.com/ihaoqi/p/3137811.html
Copyright © 2011-2022 走看看