// 重载窗口去激活时候的关闭窗口操作 BOOL CDuiMenu::OnNcCloseWindow() { // 如果有父菜单,将父菜单窗口关闭 CDuiMenu* pParentMenu = GetParentMenu(); if(pParentMenu && !pParentMenu->IsAutoClose()) { // 如果鼠标在父菜单窗口中,则不关闭父窗口 CMenuItem* pHoverItem = pParentMenu->GetHoverMenuItem(); if(pHoverItem == NULL) { pParentMenu->SetAutoClose(TRUE); pParentMenu->SetForegroundWindow(); pParentMenu->PostMessage(WM_LBUTTONDOWN, 0, 0); } } // 如果父对象是菜单项,则将菜单项中的弹出菜单指针设置为空 CDuiObject* pParent = GetParent(); if((pParent != NULL) && (pParent->IsClass(CMenuItem::GetClassName()))) { ((CMenuItem*)pParent)->SetPopupMenu(NULL); } // 关闭自身 m_pParentDuiObject = NULL; CloseWindow(); return TRUE; }
// 消息响应 LRESULT CDuiMenu::OnMessage(UINT uID, UINT Msg, WPARAM wParam, LPARAM lParam) { if((Msg != MSG_BUTTON_UP) && (Msg != MSG_BUTTON_CHECK)) { return 0; } CControlBase* pControl = GetControl(uID); if(pControl && !pControl->GetAction().IsEmpty()) { // 如果菜单项设置了action,则添加到动作任务队列中,通过任务来执行 CString strControlName = pControl->GetName(); CString strAction = pControl->GetAction(); //CDuiObject* pParent = pControl->GetParent(); CDlgBase* pParentDlg = pControl->GetParentDialog(); DuiSystem::Instance()->AddDuiActionTask(uID, Msg, wParam, lParam, strControlName, strAction, pParentDlg); }else { // 否则就调用Popup的函数 __super::OnMessage(uID, Msg, wParam, lParam); /*tagMenuInfo* pMenuInfo = new tagMenuInfo; pMenuInfo->uMenuID = uID; pMenuInfo->bSelect = (bool)lParam; pMenuInfo->bDown = (bool)wParam; PostMessage(m_uMessageID, Msg, (LPARAM)pMenuInfo);*/ } if(Msg == MSG_BUTTON_UP) { // 如果点击的是弹出菜单,则不用关闭 if(pControl && pControl->IsClass(CMenuItem::GetClassName()) && ((CMenuItem*)pControl)->IsPopup()) { return 0; } // 如果有父菜单,将父菜单关闭,不采用直接关闭的方法,而是设置自动关闭标识,并通过鼠标事件触发自动关闭 CDuiMenu* pParentMenu = GetParentMenu(); if(pParentMenu && !pParentMenu->IsAutoClose()) { pParentMenu->SetAutoClose(TRUE); pParentMenu->SetForegroundWindow(); pParentMenu->PostMessage(WM_LBUTTONDOWN, 0, 0); } // 关闭自身 CloseWindow(); } return 0; }
BOOL CMenuItem::OnControlMouseMove(UINT nFlags, CPoint point) { enumButtonState buttonState = m_enButtonState; if (!m_bIsDisable && !m_bMouseDown) { if(m_rc.PtInRect(point)) { if(m_bSelect) { if(m_bDown) { m_enButtonState = enBSHoverDown; } else { m_enButtonState = enBSHover; } } else { m_enButtonState = enBSHover; // 如果有子菜单,则加载弹出菜单 if(m_bIsPopup) { ShowPopupMenu(); } } } else { // 如果存在弹出菜单,并且鼠标不在弹出菜单范围内,则关闭弹出菜单 if(m_bIsPopup && (m_pPopupMenu != NULL)) { // 检查父菜单的各个子菜单,看鼠标当前是否在其他菜单项上面 CDuiMenu* pParentMenu = GetParentMenu(); //CMenuItem* pHoverItem = pParentMenu->GetHoverMenuItem(); CMenuItem* pHoverItem = pParentMenu->GetMenuItemWithPoint(point); if((pHoverItem != NULL) && (pHoverItem != this)) { // 如果鼠标在其他平级的菜单上,则关闭子菜单 if(IsWindow(m_pPopupMenu->GetSafeHwnd())) { m_pPopupMenu->CloseWindow(); } m_pPopupMenu = NULL; // 父菜单对象设置回自动关闭 CDuiMenu* pParentMenu = GetParentMenu(); if(pParentMenu) { pParentMenu->SetAutoClose(TRUE); pParentMenu->SetForegroundWindow(); } } } if(m_bSelect) { if(m_bDown) { m_enButtonState = enBSDown; } else { m_enButtonState = enBSNormal; } } else { m_enButtonState = enBSNormal; } } } if(buttonState != m_enButtonState) { UpdateControl(); return true; } return false; }
// 显示弹出菜单 void CMenuItem::ShowPopupMenu() { // 如果已经显示了子菜单,则直接退出 if(m_pPopupMenu) { return; } if(m_bIsPopup) { m_pPopupMenu = new CDuiMenu(DuiSystem::GetDefaultFont(), 12); m_pPopupMenu->SetAutoClose(FALSE); m_pPopupMenu->SetParent(this); m_pPopupMenu->m_clrRowHover = m_clrHover; // 设置菜单菜单的背景色 CPoint point; CRect rc = GetRect(); point.SetPoint(rc.left + rc.Width(), rc.top); int nMenuWidth = rc.Width(); CDlgBase* pParentDlg = GetParentDialog(); // 如果菜单项定义了XML文件,则使用此菜单项定义的XML文件加载子菜单 // 否则查找父菜单对象,找到对应的XML文件名,使用此XML文件名加载子菜单 CString strXmlFile = _T(""); CDuiMenu* pParentMenu = GetParentMenu(); if(pParentMenu) { if(!m_strMenuXml.IsEmpty()) { // 使用菜单项定义的XML文件 strXmlFile = m_strMenuXml; }else { // XML文件设置为父菜单对象的XML文件 strXmlFile = pParentMenu->GetXmlFile(); } // 必须将父菜单对象的自动关闭关掉,否则子菜单显示时候,父菜单失去焦点,会自动销毁 pParentMenu->SetAutoClose(FALSE); // 转换子菜单的坐标 ::ClientToScreen(pParentMenu->GetSafeHwnd(), &point); // 将父菜单的预设值菜单项列表添加到子菜单中 for (size_t i = 0; i < pParentMenu->m_vecMenuItemValue.size(); i++) { MenuItemValue& itemValue = pParentMenu->m_vecMenuItemValue.at(i); m_pPopupMenu->m_vecMenuItemValue.push_back(itemValue); } } if(!strXmlFile.IsEmpty()) { BOOL bSucc = m_pPopupMenu->LoadXmlFile(strXmlFile, pParentDlg, point, WM_DUI_MENU, GetName()); if(bSucc) // 加载弹出菜单成功才显示弹出菜单 { // 计算菜单的位置并显示 CRect rc; m_pPopupMenu->GetWindowRect(&rc); // 如果超出屏幕右侧范围,则菜单窗口往左移动一些,移动到当前菜单的左侧 int nScreenWidth= GetSystemMetrics(SM_CXFULLSCREEN); if(rc.right > nScreenWidth) { //rc.OffsetRect(nScreenWidth - rc.right -10, 0); // 移动到屏幕最右侧 rc.OffsetRect(-(nMenuWidth + rc.Width()), 0); // 移动到当前菜单左侧 } int nScreenHeight= GetSystemMetrics(SM_CYFULLSCREEN); if(rc.bottom > nScreenHeight) { rc.OffsetRect(0, -(rc.Height() - m_rc.Height())); // 高度超出屏幕则改为下对齐方式 } m_pPopupMenu->MoveWindow(rc); m_pPopupMenu->ShowWindow(SW_SHOW); m_pPopupMenu->SetAutoClose(TRUE); }else { // 弹出菜单加载失败,删除菜单对象 delete m_pPopupMenu; m_pPopupMenu = NULL; } } } }
// 鼠标左键放开事件处理 BOOL CMenuItem::OnControlLButtonUp(UINT nFlags, CPoint point) { bool bSend = false; BOOL bbDown = FALSE; bool bSelect = false; enumButtonState buttonState = m_enButtonState; if (!m_bIsDisable) { if(m_rc.PtInRect(point)) { if(m_bSelect) { if(m_bDown) { m_enButtonState = enBSHoverDown; } else { m_enButtonState = enBSHover; } if(m_bMouseDown) { // 如果组名非空,说明是radiobutton组,则刷新同一个组下面其他radiobtn if(!m_strGroupName.IsEmpty()) { m_bDown = true; ResetGroupCheck(); }else { m_bDown = !m_bDown; } bSend = false; bbDown = m_bDown; bSelect = true; } } else { m_enButtonState = enBSHover; bSend = true; } } else { // 如果存在弹出菜单,并且鼠标不在弹出菜单范围内,则关闭父菜单 if(m_bIsPopup) { // 父菜单对象设置回自动关闭 CDuiMenu* pParentMenu = GetParentMenu(); if(pParentMenu) { pParentMenu->SetAutoClose(TRUE); pParentMenu->SetForegroundWindow(); } } if(m_bDown) { m_enButtonState = enBSDown; } else { m_enButtonState = enBSNormal; } } } m_bMouseDown = false; if(buttonState != m_enButtonState) { UpdateControl(); if(bSend) { SendMessage(MSG_BUTTON_UP, bbDown, bSelect); } return true; } return false; }
// 消息处理 LRESULT CControlBase::OnMessage(UINT uID, UINT uMsg, WPARAM wParam, LPARAM lParam) { if(m_bTaskMsg) { // 如果设置了任务方式发消息的属性,则添加一个任务消息 CString strControlName = GetName(); CString strAction = GetAction(); CDlgBase* pParentDlg = GetParentDialog(); DuiSystem::Instance()->AddDuiActionTask(uID, uMsg, wParam, lParam, strControlName, strAction, pParentDlg); return 0; } if(m_strAction.Find(_T("dlg:")) == 0) // 动作:打开一个对话框,有内存泄漏,改为通过DuiSystem创建和管理 { if(uMsg == MSG_BUTTON_UP) // 鼠标放开事件才处理 { CString strXmlFile = m_strAction; strXmlFile.Delete(0, 4); DuiSystem::ShowDuiDialog(strXmlFile, GetParentDialog()); } }else if(m_strAction.Find(_T("popup:")) == 0) // 动作:打开一个Popup对话框 { if(uMsg == MSG_BUTTON_UP) // 鼠标放开事件才处理 { /*UINT nIDTemplate = 0; CDlgBase* pParentDlg = GetParentDialog(); if(pParentDlg != NULL) { nIDTemplate = pParentDlg->GetIDTemplate(); } CDlgPopup* pPopup = new CDlgPopup; pPopup->SetParent(this); CString strXmlFile = m_strAction; strXmlFile.Delete(0, 6); pPopup->SetXmlFile(_T("xml:") +strXmlFile ); CRect rc = pControlBase->GetRect(); rc.OffsetRect(-95, rc.Height()); ClientToScreen(&rc); pPopup->Create(this, rc, WM_SKIN); pPopup->ShowWindow(SW_SHOW);*/ } }else if(m_strAction.Find(_T("menu:")) == 0) // 动作:打开一个菜单 { CDuiMenu *pDuiMenu = new CDuiMenu(DuiSystem::GetDefaultFont(), 12); // 可以考虑改为通过DuiSystem创建和管理 pDuiMenu->SetAutoClose(FALSE); pDuiMenu->SetParent(this); CPoint point; CRect rc = GetRect(); // 计算菜单的显示位置 if(m_posMenu.nCount >= 2) { // 使用设置的菜单位置 int nMenuX = PositionItem2Value(m_posMenu.Left, rc.left, rc.right); int nMenuY = PositionItem2Value(m_posMenu.Top, rc.top, rc.bottom); point.SetPoint(nMenuX, nMenuY); }else { // 如果没有设置位置信息,则默认按照控件底部开始显示,水平方向中间对齐 point.SetPoint(rc.left + rc.Width() / 2, rc.bottom); } CDlgBase* pParentDlg = GetParentDialog(); if(pParentDlg != NULL) { pParentDlg->ClientToScreen(&point); } CString strXmlFile = m_strAction; strXmlFile.Delete(0, 5); if(pDuiMenu->LoadXmlFile(strXmlFile, pParentDlg, point, WM_DUI_MENU)) { if(m_posMenu.nCount >= 4) { // 如果菜单pos有4个值,第三个值为负数表示菜单向左侧显示,第四个值为负数表示菜单向上显示 CRect rcMenu; pDuiMenu->GetWindowRect(&rcMenu); int nOffsetX = 0; int nOffsetY = 0; if(m_posMenu.Right.bMinus) { nOffsetX = -rcMenu.Width(); } if(m_posMenu.Bottom.bMinus) { nOffsetY = -rcMenu.Height(); } rcMenu.OffsetRect(nOffsetX, nOffsetY); pDuiMenu->MoveWindow(rcMenu); } pDuiMenu->ShowWindow(SW_SHOW); pDuiMenu->SetAutoClose(TRUE); } }else if(m_strAction.Find(_T("link:")) == 0) // 动作:打开一个页面链接 { if(uMsg == MSG_BUTTON_UP) // 鼠标放开事件才处理 { CString strLink = m_strAction; strLink.Delete(0, 5); if(!strLink.IsEmpty()) { ShellExecute(NULL, TEXT("open"), strLink, NULL,NULL,SW_NORMAL); } } }else if(m_strAction.Find(_T("run:")) == 0) // 动作:执行一个进程 { if(uMsg == MSG_BUTTON_UP) // 鼠标放开事件才处理 { CString strProcess = m_strAction; strProcess.Delete(0, 4); strProcess.MakeLower(); if(!strProcess.IsEmpty()) { strProcess.MakeLower(); BOOL bForceAdmin = FALSE; if(strProcess.Find(_T("admin@")) == 0) { bForceAdmin = TRUE; strProcess.Delete(0, 6); } BOOL bWaitProcess = FALSE; if(strProcess.Find(_T("&")) == (strProcess.GetLength()-1)) { bWaitProcess = TRUE; strProcess.Delete(strProcess.GetLength()-1, 1); } if(strProcess.Find(_T(".exe")) == -1) { strProcess = DuiSystem::Instance()->GetString(strProcess); } if(strProcess.Find(_T("{platpath}")) == 0) { strProcess.Delete(0, 10); strProcess = DuiSystem::GetExePath() + strProcess; } CString strCmdLine = _T(""); int nPos = strProcess.Find(_T("|")); if(nPos != -1) { strCmdLine = strProcess; strCmdLine.Delete(0, nPos+1); strProcess = strProcess.Left(nPos); } DuiSystem::PathCanonicalize(strProcess); // 路径标准化 DuiSystem::ExecuteProcess(strProcess, strCmdLine, bForceAdmin, bWaitProcess); } } }else if(m_strAction.Find(ACTION_CLOSE_WINDOW) == 0) // 动作:关闭指定的窗口 { if(uMsg == MSG_BUTTON_UP) // 鼠标放开事件才处理 { CString strWndName = m_strAction; strWndName.Delete(0, 13); if(!strWndName.IsEmpty()) { CDlgBase* pDlg = DuiSystem::Instance()->GetDuiDialog(strWndName); if(pDlg != NULL) { //pDlg->DoClose(); pDlg->PostMessage(WM_QUIT, 0, 0); } } } }else { // 首先判断如果是几个默认按钮,则直接做相应的处理 CDlgBase* pParentDlg = GetParentDialog(); if(IsThisObject(BT_OK, NAME_BT_OK)) { if((MSG_BUTTON_UP == uMsg) && (pParentDlg != NULL)) { pParentDlg->DoOK(); } }else if(IsThisObject(BT_CANCEL, NAME_BT_CANCEL)) { if((MSG_BUTTON_UP == uMsg) && (pParentDlg != NULL)) { pParentDlg->DoCancel(); } }else if(IsThisObject(BT_YES, NAME_BT_YES)) { if((MSG_BUTTON_UP == uMsg) && (pParentDlg != NULL)) { pParentDlg->DoYes(); } }else if(IsThisObject(BT_NO, NAME_BT_NO)) { if((MSG_BUTTON_UP == uMsg) && (pParentDlg != NULL)) { pParentDlg->DoNo(); } }else { // 调用控件的DUI事件处理对象 return CallDuiHandler(uMsg, wParam, lParam); } } return 0; }