MFC Ribbon UI 弹出菜单实现解析
添加时间:2013-6-16 点击量:
微软推出的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);
……
}
……
}
经由过程这四步就实现了可接管鼠标、键盘事务,又不抢核心的弹出窗口。这个对一向被弹出窗口抢核心这个题目困惑着的伴侣有效。
容易发怒的意思就是: 别人做了蠢事, 然后我们代替他们, 表现出笨蛋的样子。—— 蔡康永
微软推出的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);
……
}
……
}
经由过程这四步就实现了可接管鼠标、键盘事务,又不抢核心的弹出窗口。这个对一向被弹出窗口抢核心这个题目困惑着的伴侣有效。
容易发怒的意思就是: 别人做了蠢事, 然后我们代替他们, 表现出笨蛋的样子。—— 蔡康永