我们很多的项目仅仅需要最简单的MFC对话框程序就可以了,但是最近的一个项目中需要将基于主对话框程序的项目在程序启动的时候最小化,仅仅需要在托盘中操作隐藏和恢复。
功能需求:1. MFC主对话框程序,开机隐藏主窗口2. 不能有闪烁(有的方案在开机有一瞬间闪烁,然后消失)3. 任务栏不能有图标(默认的对话框任务栏里头有图标出现)4. 在托盘中能够完美恢复被隐藏的对话框
常规方法中,主对话框的隐藏仅仅是ShowWindow或者设置属性不可见都是不行的。网络上搜索了一番,也能见到一些解决方案,但是因为本人的项目中用到了其他的UI库,比如有的方法需要响应NCPaint,在画程序边框之前的消息中隐藏主窗口,但是本人的程序中无法接受此消息,有人提出用MoveWindow(0,0,0,0)解决,但本人的程序规定了最小大小;等等原因就不一一列举了,最后还是让我找到了相对完美的解决方案,此方案绿色环保无公害,值得推荐。原理:通过MoveWindow函数,将主对话框引动到TopPoint(0,0)之外,即显示屏幕之外就行了。道理就是这么简单,这样做的唯一麻烦之处就是,因为要频繁的切换主对话框隐藏位置,需要记录上一次的主对话框正确的可视位置。并且随着对话框的大小位置改变都要记录此位置。下面逐步介绍重要的步骤和代码:1. 2个重要的函数void CModeDlgHideDlg::HideMainDlg()
{
GetWindowRect(&_last_dlg_pos);
//移动窗口到屏幕区域之外,达到消失的目的
MoveWindow(-_last_dlg_pos.Width(),
-_last_dlg_pos.Height(),
_last_dlg_pos.Width(),
_last_dlg_pos.Height());
// 修改对话框的风格, 使任务栏上的图标消失
ModifyStyleEx(WS_EX_APPWINDOW, WS_EX_TOOLWINDOW);
}
void CModeDlgHideDlg::RestoreMainDlg()
{
CRect rectNow;
GetWindowRect(&rectNow);
if (rectNow != _last_dlg_pos
|| !IsWindowVisible())
{
MoveWindow(_last_dlg_pos);
ShowWindow(SW_SHOW);
//如果对话框程序有最小化窗口时的特殊处理,否则最小化时不能正确恢复窗口
if (IsIconic())
ShowWindow(SW_RESTORE);
// 修改对话框的风格, 使消失的任务栏图标正常
ModifyStyleEx(WS_EX_TOOLWINDOW, WS_EX_APPWINDOW);
}
SendMessage(WM_SIZE);
SetForegroundWindow();
}
可以在对话框初始化函数中调用HideMainDlg函数,在需要恢复原状的地方调用RestoreMainDlg:TrayMessage(NIM_ADD);
this->CenterWindow();
HideMainDlg();
bool CModeDlgHideDlg::TrayMessage( DWORD dwFlag, UINT uIconId)
{
CString strTips;
strTips = _T("Just a test.");
NOTIFYICONDATA notify;
notify.cbSize=sizeof(NOTIFYICONDATA);
notify.hWnd= m_hWnd;
notify.uFlags=NIF_MESSAGE|NIF_ICON|NIF_TIP;
notify.uCallbackMessage = WM_MY_NOTIFY_MESSAGE; //用户定义的回调消息
wcscpy_s(notify.szTip, 128, strTips);
notify.uID=uIconId;
HICON hIcon= AfxGetApp()->LoadIcon(uIconId);
notify.hIcon=hIcon;
return ::Shell_NotifyIcon(dwFlag, ¬ify)?true:false;
}
LRESULT CModeDlgHideDlg::WindowProc(UINT message, WPARAM wParam,LPARAM lParam)
{
switch(message)
{
case WM_MY_NOTIFY_MESSAGE://如果是用户定义的消息
if(lParam==WM_LBUTTONDBLCLK)
{
this->RestoreMainDlg();
}
else if(lParam==WM_RBUTTONDOWN)
{
}
break;
}
return CDialog::WindowProc(message, wParam, lParam);
}
2. 在OnSize和OnCancel处加上适宜的代码:
void CModeDlgHideDlg::OnSize(UINT nType, int cx, int cy)
{
CDialog::OnSize(nType, cx, cy);
/*!< 为了对话框在调整大小后隐藏主窗口,可以随时恢复调整之后的大小和位置*/
CRect rectNow;
GetWindowRect(&rectNow);
if (rectNow != _last_dlg_pos
&& rectNow.left >= 0)
{
_last_dlg_pos = rectNow;
}
}
void CModeDlgHideDlg::OnCancel()
{
/*!< 点关闭按钮时,不真正的退出对话框,而是记住位置再隐藏 */
GetWindowRect(&_last_dlg_pos);
ShowWindow(SW_HIDE);
}
功能需求:1. MFC主对话框程序,开机隐藏主窗口2. 不能有闪烁(有的方案在开机有一瞬间闪烁,然后消失)3. 任务栏不能有图标(默认的对话框任务栏里头有图标出现)4. 在托盘中能够完美恢复被隐藏的对话框
常规方法中,主对话框的隐藏仅仅是ShowWindow或者设置属性不可见都是不行的。网络上搜索了一番,也能见到一些解决方案,但是因为本人的项目中用到了其他的UI库,比如有的方法需要响应NCPaint,在画程序边框之前的消息中隐藏主窗口,但是本人的程序中无法接受此消息,有人提出用MoveWindow(0,0,0,0)解决,但本人的程序规定了最小大小;等等原因就不一一列举了,最后还是让我找到了相对完美的解决方案,此方案绿色环保无公害,值得推荐。原理:通过MoveWindow函数,将主对话框引动到TopPoint(0,0)之外,即显示屏幕之外就行了。道理就是这么简单,这样做的唯一麻烦之处就是,因为要频繁的切换主对话框隐藏位置,需要记录上一次的主对话框正确的可视位置。并且随着对话框的大小位置改变都要记录此位置。下面逐步介绍重要的步骤和代码:1. 2个重要的函数void CModeDlgHideDlg::HideMainDlg()
{
GetWindowRect(&_last_dlg_pos);
//移动窗口到屏幕区域之外,达到消失的目的
MoveWindow(-_last_dlg_pos.Width(),
-_last_dlg_pos.Height(),
_last_dlg_pos.Width(),
_last_dlg_pos.Height());
// 修改对话框的风格, 使任务栏上的图标消失
ModifyStyleEx(WS_EX_APPWINDOW, WS_EX_TOOLWINDOW);
}
void CModeDlgHideDlg::RestoreMainDlg()
{
CRect rectNow;
GetWindowRect(&rectNow);
if (rectNow != _last_dlg_pos
|| !IsWindowVisible())
{
MoveWindow(_last_dlg_pos);
ShowWindow(SW_SHOW);
//如果对话框程序有最小化窗口时的特殊处理,否则最小化时不能正确恢复窗口
if (IsIconic())
ShowWindow(SW_RESTORE);
// 修改对话框的风格, 使消失的任务栏图标正常
ModifyStyleEx(WS_EX_TOOLWINDOW, WS_EX_APPWINDOW);
}
SendMessage(WM_SIZE);
SetForegroundWindow();
}
可以在对话框初始化函数中调用HideMainDlg函数,在需要恢复原状的地方调用RestoreMainDlg:TrayMessage(NIM_ADD);
this->CenterWindow();
HideMainDlg();
bool CModeDlgHideDlg::TrayMessage( DWORD dwFlag, UINT uIconId)
{
CString strTips;
strTips = _T("Just a test.");
NOTIFYICONDATA notify;
notify.cbSize=sizeof(NOTIFYICONDATA);
notify.hWnd= m_hWnd;
notify.uFlags=NIF_MESSAGE|NIF_ICON|NIF_TIP;
notify.uCallbackMessage = WM_MY_NOTIFY_MESSAGE; //用户定义的回调消息
wcscpy_s(notify.szTip, 128, strTips);
notify.uID=uIconId;
HICON hIcon= AfxGetApp()->LoadIcon(uIconId);
notify.hIcon=hIcon;
return ::Shell_NotifyIcon(dwFlag, ¬ify)?true:false;
}
LRESULT CModeDlgHideDlg::WindowProc(UINT message, WPARAM wParam,LPARAM lParam)
{
switch(message)
{
case WM_MY_NOTIFY_MESSAGE://如果是用户定义的消息
if(lParam==WM_LBUTTONDBLCLK)
{
this->RestoreMainDlg();
}
else if(lParam==WM_RBUTTONDOWN)
{
}
break;
}
return CDialog::WindowProc(message, wParam, lParam);
}
2. 在OnSize和OnCancel处加上适宜的代码:
void CModeDlgHideDlg::OnSize(UINT nType, int cx, int cy)
{
CDialog::OnSize(nType, cx, cy);
/*!< 为了对话框在调整大小后隐藏主窗口,可以随时恢复调整之后的大小和位置*/
CRect rectNow;
GetWindowRect(&rectNow);
if (rectNow != _last_dlg_pos
&& rectNow.left >= 0)
{
_last_dlg_pos = rectNow;
}
}
void CModeDlgHideDlg::OnCancel()
{
/*!< 点关闭按钮时,不真正的退出对话框,而是记住位置再隐藏 */
GetWindowRect(&_last_dlg_pos);
ShowWindow(SW_HIDE);
}