此功能是记住用户的操作,在用户点击关闭时是真退出程序还是最小化到托盘,我们常见的PC客户端都有此功能,例如:IMO客户端、网易云音乐
我自己的项目中也要实现此功能,在此总结一下,最终效果:
.h文件
1 #ifndef _CLOSEHINTDIALOG_H_ 2 #define _CLOSEHINTDIALOG_H_ 3 4 class CCloseHintDialog :public WindowImplBase 5 { 6 public: 7 CCloseHintDialog(); 8 9 ~CCloseHintDialog(); 10 11 public: 12 virtual LPCTSTR GetWindowClassName() const; 13 14 virtual void OnFinalMessage(HWND hWnd); 15 16 virtual CDuiString GetSkinFile(); 17 18 virtual CDuiString GetSkinFolder(); 19 20 virtual UILIB_RESOURCETYPE GetResourceType() const; 21 22 virtual CControlUI* CreateControl(LPCTSTR pstrClassName); 23 24 virtual LRESULT ResponseDefaultKeyEvent(WPARAM wParam); 25 26 virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); 27 28 virtual void Notify(TNotifyUI& msg); 29 30 virtual void OnClick(TNotifyUI& msg); 31 32 virtual void InitWindow(); 33 34 void OnPrepare(); 35 36 public: 37 38 COptionUI * m_pBtnYES; 39 40 COptionUI * m_pBtnNO; 41 42 COptionUI * m_pExitbtn; 43 44 COptionUI * m_pMoveToTraybtn; 45 46 CCheckBoxUI* m_pchkOption; 47 }; 48 #endif//_CLOSEHINTDIALOG_H_
.cpp文件
1 #include "....stdafx.h" 2 #include "CloseHintDialog.h" 3 4 CCloseHintDialog::CCloseHintDialog() 5 :m_pBtnYES(NULL) 6 ,m_pBtnNO(NULL) 7 ,m_pExitbtn(NULL) 8 ,m_pchkOption(NULL) 9 ,m_pMoveToTraybtn(NULL) 10 { 11 12 } 13 14 CCloseHintDialog::~CCloseHintDialog() 15 { 16 17 } 18 19 LPCTSTR CCloseHintDialog::GetWindowClassName() const 20 { 21 return TEXT("CloseHintDialog"); 22 } 23 24 void CCloseHintDialog::OnFinalMessage(HWND hWnd) 25 { 26 CWindowWnd::OnFinalMessage(hWnd); 27 } 28 29 CDuiString CCloseHintDialog::GetSkinFile() 30 { 31 return TEXT("xml//CloseHintDlg.xml"); 32 } 33 34 CDuiString CCloseHintDialog::GetSkinFolder() 35 { 36 return TEXT(""); 37 } 38 39 LRESULT CCloseHintDialog::ResponseDefaultKeyEvent(WPARAM wParam) 40 { 41 if (wParam == VK_RETURN) 42 { 43 return FALSE; 44 } 45 else if (wParam == VK_ESCAPE) 46 { 47 //Close(); 48 return TRUE; 49 } 50 return FALSE; 51 } 52 53 UILIB_RESOURCETYPE CCloseHintDialog::GetResourceType() const 54 { 55 return UILIB_FILE; 56 } 57 58 CControlUI* CCloseHintDialog::CreateControl(LPCTSTR pstrClassName) 59 { 60 return NULL; 61 } 62 63 void CCloseHintDialog::InitWindow() 64 { 65 m_pBtnYES = static_cast<COptionUI *>(m_PaintManager.FindControl(TEXT("yesbtn"))); 66 67 m_pBtnNO = static_cast<COptionUI *>(m_PaintManager.FindControl(TEXT("nobtn"))); 68 69 m_pExitbtn = static_cast<COptionUI *>(m_PaintManager.FindControl(TEXT("ExitDirectbtn"))); 70 71 m_pMoveToTraybtn = static_cast<COptionUI *>(m_PaintManager.FindControl(TEXT("MoveInTraybtn"))); 72 73 m_pchkOption = static_cast<CCheckBoxUI*>(m_PaintManager.FindControl(TEXT("chkOption"))); 74 75 } 76 77 void CCloseHintDialog::OnPrepare() 78 { 79 80 } 81 82 void CCloseHintDialog::Notify(TNotifyUI& msg) 83 { 84 if( msg.sType == TEXT("windowinit") ) OnPrepare(); 85 86 if(msg.sType == TEXT("click")) 87 { 88 if(msg.pSender->GetName()==TEXT("closebtn")) 89 { 90 Close(IDCLOSE); 91 } 92 else if(msg.pSender->GetName() == TEXT("yesbtn")) 93 { 94 Close(IDOK); 95 } 96 else if (msg.pSender->GetName() == _T("nobtn")) 97 { 98 Close(IDCANCEL); 99 } 100 } 101 WindowImplBase::Notify(msg); 102 } 103 104 void CCloseHintDialog::OnClick(TNotifyUI& msg) 105 { 106 __super::OnClick(msg); 107 } 108 109 //禁用双击标题栏窗口最大化 110 LRESULT CCloseHintDialog::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) 111 { 112 LRESULT lRes = 0; 113 BOOL bHandled = TRUE; 114 115 switch( uMsg ) 116 { 117 case WM_NCLBUTTONDBLCLK: 118 //不做处理 119 { 120 return 0; 121 } 122 break; 123 default: 124 bHandled = FALSE; 125 } 126 return WindowImplBase::HandleMessage(uMsg,wParam,lParam); 127 }
xml文件
<?xml version="1.0" encoding="utf-8" standalone="yes" ?> <Window size="370,170" caption="0,0,0,30" sizebox="0,0,0,0" roundcorner="1,1"> <Font name="微软雅黑" size="12" bold="false" italic="false" underline="false" /> <Font name="微软雅黑" size="14" bold="false" italic="false" underline="false" /> <VerticalLayout bkcolor="#FFFFFFFF" bkimage="file='imageclosetitle.png'" > <HorizontalLayout height="30" > <Control width="10"/> <Label textcolor="#FFFFFFFF" width="52" height="14" padding="0,5,0,0" /> <Control /> <Button name="closebtn" height="22" width="27" normalimage=" file='imagesysButtonclose.png'" hotimage=" file='imagesysButtonclose_hover.png'" pushedimage=" file='imagesysButtonclose_pressed.png'"/> </HorizontalLayout> <VerticalLayout inset="54,8,0,0" bkcolor="#FFFFFFFF"> <Label name="msg_text" text="关闭主面板时:" height="22" align="left" textcolor="#FF333333" font="0"/> <Option name="ExitDirectbtn" text="退出程序" height="22" width="180" padding="24,-5,0,0" textpadding="18,5,0,0" textcolor="#FF333333" align="left" selectedimage="file='imageButtonRadioBtnSel.png' source='0,0,12,12' dest='0,7,12,20'" normalimage="file='imageButtonRadioBtnNon.png' source='0,0,12,12' dest='0,7,12,20'" group="RadioBoxTest" selected="true" font="0"/> <Option name="MoveInTraybtn" text="隐藏到任务通知栏,不退出程序" height="22" width="230" padding="24,0,0,0" textpadding="18,5,0,0" textcolor="#FF333333" align="left" selectedimage="file='imageButtonRadioBtnSel.png' source='0,0,12,12' dest='0,7,12,20'" normalimage="file='imageButtonRadioBtnNon.png' source='0,0,12,12' dest='0,7,12,20'" group="RadioBoxTest" font="0"/> </VerticalLayout> <HorizontalLayout height="49" bkcolor="#FFFFFFFF"> <Control width="10"/> <CheckBox name="chkOption" width="14" height="32" padding="0,9,0,0" normalimage="file='imageCheckBoxungouxuan.png' source='0,0,14,14' dest='0,7,14,21'" selectedimage="file='imageCheckBoxgouxuan.png' source='0,0,14,14' dest='0,7,14,21'"/> <Label text="下次不再提示(A)" width="90" height="32" padding="5,7,0,0" textcolor="#FF333333" font="0"/> <Control /> <Button name="yesbtn" text="是(Y)" height="22" width="74" padding="0,13,0,0" textcolor="#FF333333" align="center" normalimage="file='imageButtonyes_or_no.jpg'" hotimage=" file='imageButtonyes_or_no-green.png'" pushedimage="file='imageButtonyes_or_no.jpg'" font="0"/> <Button name="nobtn" text="否(N)" height="22" width="74" padding="5,13,0,0" textcolor="#FF333333" align="center" normalimage="file='imageButtonyes_or_no.jpg'" hotimage=" file='imageButtonyes_or_no-green.png'" pushedimage="file='imageButtonyes_or_no.jpg'" font="0"/> <Control width="10"/> </HorizontalLayout> <HorizontalLayout height="5" bkcolor="#FFEDF3FC"/> </VerticalLayout> </Window>
1.最小化托盘原理: 首先要将窗口隐藏,然后在右下角绘制托盘图标
2.恢复的原理:将窗口显示
在点击关闭按钮响应函数里面处理:
1 bool OnExitConfirm() 2 { 3 bool bResult = false; 4 //从配置文件中读取用户设置 5 TCHAR cofigValue[MAX_PATH]; 6 CString tszModule = CommonUtils::GetModuleDirectory(); 7 tszModule+="\config.ini"; 8 ::GetPrivateProfileString(L"Setting",L"ExitDirect",L"Error",cofigValue,MAX_PATH,tszModule); 9 10 if (_tcsicmp(cofigValue,_T("Error")) == 0)//配置文件里面没有 11 { 12 CCloseHintDialog closeHintBox; 13 closeHintBox.Create(this->GetHWND(), _T("CloseHintDialog"), UI_WNDSTYLE_EX_FRAME, WS_EX_WINDOWEDGE); 14 closeHintBox.CenterWindow(); 15 16 if(closeHintBox.ShowModal()== IDOK) 17 { 18 if (closeHintBox.m_pchkOption->GetCheck())//勾选 19 { 20 if(closeHintBox.m_pExitbtn->IsSelected()) 21 { 22 CString strExit; 23 strExit.Format(L"%d",1); 24 ::WritePrivateProfileString(L"Setting",L"ExitDirect",strExit,tszModule); 25 26 Close(IDCLOSE); 27 28 bResult = true; 29 30 return bResult; 31 32 } 33 else if (closeHintBox.m_pMoveToTraybtn->IsSelected()) 34 { 35 CString strExit; 36 strExit.Format(L"%d",0); 37 ::WritePrivateProfileString(L"Setting",L"ExitDirect",strExit,tszModule); 38 39 ::ShowWindow(this->GetHWND(),SW_HIDE); 40 41 return bResult; 42 } 43 } 44 else//不勾选 45 { 46 if(closeHintBox.m_pExitbtn->IsSelected()) 47 { 48 Close(IDCLOSE); 49 50 bResult = true; 51 52 return bResult; 53 } 54 else if (closeHintBox.m_pMoveToTraybtn->IsSelected()) 55 { 56 ::ShowWindow(this->GetHWND(),SW_HIDE); 57 return bResult; 58 } 59 } 60 } 61 else 62 { 63 return bResult; 64 } 65 } 66 else 67 { 68 if (_tcsicmp(cofigValue,_T("1")) == 0) 69 { 70 Close(IDCLOSE); 71 72 bResult = true; 73 74 return bResult; 75 } 76 else if (_tcsicmp(cofigValue,_T("0")) == 0) 77 { 78 ::ShowWindow(this->GetHWND(),SW_HIDE); 79 return bResult; 80 } 81 } 82 83 return bResult; 84 }
恢复界面函数
1 LRESULT CMainFrameWnd::OnTrayNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) 2 { 3 if(wParam == 1000) 4 { 5 switch(lParam) 6 { 7 ... 8 9 case WM_LBUTTONDBLCLK: 10 { 11 ::ShowWindow(this->GetHWND(),SW_SHOW);//显示窗口 12 } 13 break; 14 } 15 } 16 return 0; 17 }