请问怎么在对话框初试话时就隐藏啊? 试了很多次,发现只能在按下按钮后用showwindow(SW_HIDE)隐藏,我想在初始化时就隐藏,可以吗? 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 直接在函数里生成对话框后就接着用showwindow(SW_HIDE)不行吗? 1.定时器最直观,又是最无奈的一个方法就是使用定时器。既然我们在对话框开始显示之前不能用ShowWindow(SW_HIDE)将其隐藏,那就给一个时间让它显示,完了我们在隐藏它。 方法: 1.在OnInitDialog()函数里设置定时器:(WINDOWS API里面响应消息WM_INITDIALOG) SetTimer(1, 1, NULL); 2.添加处理WM_TIMER的消息处理函数OnTimer,添加代码: if(nIDEvent == 1) { DeleteTimer(1); ShowWindow(SW_HIDE); } 这种方法的缺点是显而易见的,使用定时器,使得程序的稳定性似乎打一个折扣;窗口是要先显示出来的,那么效果就是窗口闪了一下消失。 2.改变对话框显示状况在对话框初始化时改变其显示属性可以让它隐藏起来。方法是调用SetWindowPlacement函数: BOOL CDialogExDlg::OnInitDialog() { CDialog::OnInitDialog(); //DO something WINDOWPLACEMENT wp; wp.length=sizeof(WINDOWPLACEMENT); wp.flags=WPF_RESTORETOMAXIMIZED; wp.showCmd=SW_HIDE; SetWindowPlacement(&wp); return TRUE; } 在需要显示时(通常是响应热键或者托盘图标的鼠标消息): WINDOWPLACEMENT wp; wp.length=sizeof(WINDOWPLACEMENT); wp.flags=WPF_RESTORETOMAXIMIZED; wp.showCmd=SW_SHOW; SetWindowPlacement(&wp); 这样的效果很不理想:窗口显示在屏幕的左上角,并且是只有标题栏,要正常显示,还需加上如下代码: 定义一个成员变量CRect rect; 在OnInitDialog()里面: GetWindowRect(&rect); 在需要显示的地方: SetWindowPos(&wndNoTopMost, wndRc.left, wndRc.top, wndRc.right, wndRc.bottom, SWP_SHOWWINDOW); CenterWindow(); 即使这样,效果还是很差。 这种方法还有一个弊端是当程序开始运行并且隐藏起来后,原来激活的窗口变成了非激活状态了,而当对话框显示出来后,对话框自身也是非激活状态的。 3.不绘制窗口当对话框显示时将要响应消息WM_PAINT绘制客户区,相应消息WM_NCPAINT绘制窗口边框。我们在窗口第一次自绘自身时隐藏窗口,可以收到比较良好的效果。由于窗口是先画窗口边框,所以我们仅需处理WM_NCPAINT即可。代码如下: 添加WM_NCPAINT处理函数。 void CMyDialog::OnNcPaint() { static int i = 2; if(i > 0) { i --; ShowWindow(SW_HIDE); } else CDialog::OnNcPaint(); } 这里有个问题:为什么要定义静态变量i而且设其值为2呢? 我们只要窗口隐藏第一次,所以定义这个变量可以判断是否时首次显示窗口。当程序开始运行时,系统发送(SendMessage)WM_NCPAINT消息,此时程序的窗口边框应该被显示,但是此时我们没有作任何显示的操作,而是将窗口隐藏,ShowWindow(SW_HIDE)将把窗口的WS_VISIBLE属性去掉,继续执行,程序将检查WS_VISIBLE属性,如果没有则显示窗口,所以又发送了一个WM_NCPAINT消息。所以我们要处理两次WM_NCPAINT消息。 在需要窗口显示时,调用ShowWindow(SW_SHOW)即可。 程序执行的结果是,原来处于激活状态的窗口可能会闪动两下,然后仍然处于激活状态。这种处理方式比上面的方式要优越得多。 4.将对话框作为子窗口这种方法是采用SDI框架,主窗口始终隐藏,对话框作为主窗口的成员变量,在CMainFrame::OnCreate()里面加入下代码: if(!dlg.Create(IDD_MYDIALOG, this)) { return –1; } dlg.ShowWindow(SW_HIDE); 在要显示对话框的地方用dlg.ShowWindow(SW_SHOW);即可。注意,主窗口一定要隐藏,否则对话框可能会闪现一下。 隐藏状态栏窗口上面介绍了几种检查对话框的方法,大家如果试过的话可能已经注意到系统状态栏里在程序启动时会有程序的图标闪过,在隐藏对话框的时候这个也是要隐藏的,方法很简单: 在OnInitDialog()函数里面加上ModifyStyleEx(WS_EX_APPWINDOW, WS_EX_TOOLWINDOW);即可。在要显示窗口的地方加上代码ModifyStyleEx(WS_EX_TOOLWINDOW, WS_EX_APPWINDOW);即将窗口的扩展样式改回来。 以上是我的一点经验总结,有错误或不完善的地方还望大家提出指正。欢迎大家与我联系。 基于 CDialog 的应用程序一开始便被隐藏的方法作者: Solomon ([email protected])日期: 2001/12/29相关文章: http://www.csdn.net/develop/article/11/11634.shtm 要使一个基于 CDialog 的应用程序一开始便被隐藏的方法有好多种。大多数方法在相关文章(http://www.csdn.net/develop/article/11/11634.shtm)中已经提及。本人之所以要写这篇文章,主要是通过分析MFC 调用模式对话框的方法向大家展示一种简单,合理,完满的解决方案。 首先,用MFC 生成的一个基于对话框的应用程序框架,然后修改对话框资源的Visible属性使之成为不可见(在属性页的MoreStyle中),接着按下F5 来运行这个程序,我们会发现,它并不象我们期望的那样一开始就被隐藏。而是被显示了出来。那么为什么会这样呢?特别是精通SDK的朋友们,会对此百思不得其解。 其实,MFC框架为了显示对话框很多工作,它并不简简单单地调用 DialogBox 显示对话框,而是使用了相对复杂的方法。现在,我就来引导大家对此探个究竟。 在生成的应用程序框架中(名称为Test),你会看到CTestApp和CTestDlg 两个类,在 CTestApp 的 InitInstance 方法中有如下语句: CTestDlg dlg; m_pMainWnd = &dlg; int nResponse = dlg.DoModal(); // 此处将创建并显示对话框DoModal 是一个虚函数,MFC允许用户编写自己的调用对话框方式来替代原来的方式。但是,MS 实在令人失望。如果,你打开 DlgCore.Cpp (MFC Source 目录下)并复制 DoModal 的代码到你自己的类中,你会发现无法编译成功。原因在于MS在 DoModal 中使用了两个非输出函数 AfxHookWindowCreate 和 AfxUnhookWindowCreate。(这两个函数的作用超出了本文所讨论的范围,因此不作详细论述。)由于无法编译,所以 MS 要求用户的 DoModal 必须调用 CDialog 的 DoModal 来显示对话框。这样,控制隐藏就无法通过重载 DoModal 实现了。那么 MS 在 DoModal 中干了什么呢?下面就是一部分代码。int CDialog::DoModal(){ ...... 读入资源,并作一些设置 if (CreateDlgIndirect(lpDialogTemplate, CWnd::FromHandle(hWndParent), hInst)) //创建无模式对话框 { if (m_nFlags & WF_CONTINUEMODAL) { // enter modal loop DWORD dwFlags = MLF_SHOWONIDLE; //罪魁祸首就是他 if (GetStyle() & DS_NOIDLEMSG) dwFlags |= MLF_NOIDLEMSG; VERIFY(RunModalLoop(dwFlags) == m_nModalResult); //进入消息循环 } ....... } } ...... 释放资源等}原来,DoModal 并不使用 DialogBox 直接调出对话框,而是通过创建无模式对话框并维护消息循环的方式(RunModalLoop)来模拟模式对话框的效果。(看起来好像有点像DialogBox 的内部作业方式)MLF_SHOWONIDLE 是什么?看英文的意思是在Idle 的时候ShowWindow。那么是不是这样呢?好吧,为了探个究竟,让我们进入RunModalLoop。RunModalLoop在WinCore.CPP中定义。打开WinCore.CPP 并找到 RunModalLoop, 会看到以下的语句BOOL bShowIdle = (dwFlags & MLF_SHOWONIDLE) && !(GetStyle() & WS_VISIBLE);条件 dwFlags & MLF_SHOWONIDLE 始终为TRUE。 而 !(GetStyle() & WS_VISIBLE)只有在WS_VISIBLE属性没有设置的时候才会为 TRUE。这样,当我们去掉Visible 属性后 bShowIdle 就为 TRUE 了。再往下,就会看到以下的调用 while (bIdle && !::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE)) { ASSERT(ContinueModal()); // show the dialog when the message queue goes idle if (bShowIdle) // 找到了 { ShowWindow(SW_SHOWNORMAL); UpdateWindow(); bShowIdle = FALSE; // 指示下一次Idle 时不用显示对话框了 }While 里的条件是消息队列里再也没有任何消息了。此时,由于 bShowIdle 为 TRUE ,就会调用 ShowWindow 来显示对话框。由于 ShowWindow 只执行一次,所以如果能截获第一次WM_SHOWWINDOW消息, 就能控制了隐藏了。是的。在 CTestDlg 处理 WM_SHOWWINDOW 并添上以下代码void CTestDlg::OnShowWindow(BOOL bShow, UINT nStatus){ if( GetStyle() & WS_VISIBLE ) { CDialog::OnShowWindow(bShow, nStatus); } else { long Style = ::GetWindowLong(*this, GWL_STYLE); ::SetWindowLong(*this, GWL_STYLE, Style | WS_VISIBLE); CDialog::OnShowWindow(SW_HIDE, nStatus); }}再运行一下,哈哈,对话框不见了,连闪都不闪一下。细心的读者也许会问为什么使用SetWindowLong,而不是 ModifyStyle, 其实是为了加快速度,因为 ModifyStyle 内部还要调用 GetWindowLong 和 SetWindowPos。到此为止,一个简单,完满的解决方法已经展现在大家面前了。其实,本来 MS 可以做的更好,比如把 GetStyle() 声明为虚函数,使得我们能返回WS_VISIBLE 来控制 bShowIdle 成为 FALSE, 或者把 DWORD dwFlags = MLF_SHOWONIDLE;改成 DWORD dwFlags = ShowOnIdle(); // 声明为虚函数希望MS能在以后的版本中考虑这个问题。 做成无模式比较简单:CDrawDlg* dlg=new CDrawDlg;dlg->Create(IDD_DIALOG2);dlg->ShowWindow(SW_HIDE); sencond way:OnInitialDialog(){ WINDOWPLACEMENT wp; wp.length=sizeof(WINDOWPLACEMENT); wp.flags=WPF_RESTORETOMAXIMIZED; wp.showCmd=SW_HIDE; SetWindowPlacement(&wp); //this function...} 设置 SHOWCMD 的值 就好了啊 VC程序数据初始化问题 WIN32 SDK 如何修改按钮的背景图片。 ADO---_ConnectionPtr??? 请教 error C2236: unexpected 'class' 'CCircleTool' 如何解决? 如何在播放器里连续播放几个文件? 如何加宽CMainFrame主框架窗口左右两边的非客户区的宽度? 奇怪的问题?? 请问对话框调整尺寸和显示位置的函数是什么? 初学者关于控件以及如何制作安装程序的问题,请指教 小女子实在没办法, 各位仁兄请帮帮忙! 关于字符串的问题? 如何改变窗体的灰色?OnNcPaint()如何用?
最直观,又是最无奈的一个方法就是使用定时器。既然我们在对话框开始显示之前不能用ShowWindow(SW_HIDE)将其隐藏,那就给一个时间让它显示,完了我们在隐藏它。 方法: 1.在OnInitDialog()函数里设置定时器:(WINDOWS API里面响应消息WM_INITDIALOG) SetTimer(1, 1, NULL); 2.添加处理WM_TIMER的消息处理函数OnTimer,添加代码: if(nIDEvent == 1) { DeleteTimer(1); ShowWindow(SW_HIDE); } 这种方法的缺点是显而易见的,使用定时器,使得程序的稳定性似乎打一个折扣;窗口是要先显示出来的,那么效果就是窗口闪了一下消失。 2.改变对话框显示状况
在对话框初始化时改变其显示属性可以让它隐藏起来。方法是调用SetWindowPlacement函数: BOOL CDialogExDlg::OnInitDialog() { CDialog::OnInitDialog(); //DO something WINDOWPLACEMENT wp; wp.length=sizeof(WINDOWPLACEMENT); wp.flags=WPF_RESTORETOMAXIMIZED; wp.showCmd=SW_HIDE; SetWindowPlacement(&wp); return TRUE; } 在需要显示时(通常是响应热键或者托盘图标的鼠标消息): WINDOWPLACEMENT wp; wp.length=sizeof(WINDOWPLACEMENT); wp.flags=WPF_RESTORETOMAXIMIZED; wp.showCmd=SW_SHOW; SetWindowPlacement(&wp); 这样的效果很不理想:窗口显示在屏幕的左上角,并且是只有标题栏,要正常显示,还需加上如下代码: 定义一个成员变量CRect rect; 在OnInitDialog()里面: GetWindowRect(&rect); 在需要显示的地方: SetWindowPos(&wndNoTopMost, wndRc.left, wndRc.top, wndRc.right, wndRc.bottom, SWP_SHOWWINDOW); CenterWindow(); 即使这样,效果还是很差。 这种方法还有一个弊端是当程序开始运行并且隐藏起来后,原来激活的窗口变成了非激活状态了,而当对话框显示出来后,对话框自身也是非激活状态的。 3.不绘制窗口
当对话框显示时将要响应消息WM_PAINT绘制客户区,相应消息WM_NCPAINT绘制窗口边框。我们在窗口第一次自绘自身时隐藏窗口,可以收到比较良好的效果。由于窗口是先画窗口边框,所以我们仅需处理WM_NCPAINT即可。代码如下: 添加WM_NCPAINT处理函数。 void CMyDialog::OnNcPaint() { static int i = 2; if(i > 0) { i --; ShowWindow(SW_HIDE); } else CDialog::OnNcPaint(); } 这里有个问题:为什么要定义静态变量i而且设其值为2呢? 我们只要窗口隐藏第一次,所以定义这个变量可以判断是否时首次显示窗口。当程序开始运行时,系统发送(SendMessage)WM_NCPAINT消息,此时程序的窗口边框应该被显示,但是此时我们没有作任何显示的操作,而是将窗口隐藏,ShowWindow(SW_HIDE)将把窗口的WS_VISIBLE属性去掉,继续执行,程序将检查WS_VISIBLE属性,如果没有则显示窗口,所以又发送了一个WM_NCPAINT消息。所以我们要处理两次WM_NCPAINT消息。 在需要窗口显示时,调用ShowWindow(SW_SHOW)即可。 程序执行的结果是,原来处于激活状态的窗口可能会闪动两下,然后仍然处于激活状态。这种处理方式比上面的方式要优越得多。 4.将对话框作为子窗口
这种方法是采用SDI框架,主窗口始终隐藏,对话框作为主窗口的成员变量,在CMainFrame::OnCreate()里面加入下代码: if(!dlg.Create(IDD_MYDIALOG, this)) { return –1; } dlg.ShowWindow(SW_HIDE); 在要显示对话框的地方用dlg.ShowWindow(SW_SHOW);即可。注意,主窗口一定要隐藏,否则对话框可能会闪现一下。 隐藏状态栏窗口
上面介绍了几种检查对话框的方法,大家如果试过的话可能已经注意到系统状态栏里在程序启动时会有程序的图标闪过,在隐藏对话框的时候这个也是要隐藏的,方法很简单: 在OnInitDialog()函数里面加上ModifyStyleEx(WS_EX_APPWINDOW, WS_EX_TOOLWINDOW);即可。在要显示窗口的地方加上代码ModifyStyleEx(WS_EX_TOOLWINDOW, WS_EX_APPWINDOW);即将窗口的扩展样式改回来。 以上是我的一点经验总结,有错误或不完善的地方还望大家提出指正。欢迎大家与我联系。
m_pMainWnd = &dlg;
int nResponse = dlg.DoModal(); // 此处将创建并显示对话框DoModal 是一个虚函数,MFC允许用户编写自己的调用对话框方式来替代原来的方式。但是,MS 实在令人失望。如果,你打开 DlgCore.Cpp (MFC Source 目录下)并复制 DoModal 的代码到你自己的类中,你会发现无法编译成功。原因在于MS在 DoModal 中使用了两个非输出函数 AfxHookWindowCreate 和 AfxUnhookWindowCreate。(这两个函数的作用超出了本文所讨论的范围,因此不作详细论述。)由于无法编译,所以 MS 要求用户的 DoModal 必须调用 CDialog 的 DoModal 来显示对话框。这样,控制隐藏就无法通过重载 DoModal 实现了。那么 MS 在 DoModal 中干了什么呢?下面就是一部分代码。int CDialog::DoModal()
{
...... 读入资源,并作一些设置
if (CreateDlgIndirect(lpDialogTemplate,
CWnd::FromHandle(hWndParent), hInst)) //创建无模式对话框
{
if (m_nFlags & WF_CONTINUEMODAL)
{
// enter modal loop
DWORD dwFlags = MLF_SHOWONIDLE; //罪魁祸首就是他
if (GetStyle() & DS_NOIDLEMSG)
dwFlags |= MLF_NOIDLEMSG;
VERIFY(RunModalLoop(dwFlags) == m_nModalResult); //进入消息循环
} .......
}
}
...... 释放资源等
}原来,DoModal 并不使用 DialogBox 直接调出对话框,而是通过创建无模式对话框并维护消息循环的方式(RunModalLoop)来模拟模式对话框的效果。(看起来好像有点像DialogBox 的内部作业方式)MLF_SHOWONIDLE 是什么?看英文的意思是在Idle 的时候ShowWindow。那么是不是这样呢?好吧,为了探个究竟,让我们进入RunModalLoop。RunModalLoop在WinCore.CPP中定义。打开WinCore.CPP 并找到 RunModalLoop, 会看到以下的语句BOOL bShowIdle = (dwFlags & MLF_SHOWONIDLE) && !(GetStyle() & WS_VISIBLE);条件 dwFlags & MLF_SHOWONIDLE 始终为TRUE。 而 !(GetStyle() & WS_VISIBLE)只有在WS_VISIBLE属性没有设置的时候才会为 TRUE。这样,当我们去掉Visible 属性后 bShowIdle 就为 TRUE 了。再往下,就会看到以下的调用 while (bIdle &&
!::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE))
{
ASSERT(ContinueModal()); // show the dialog when the message queue goes idle
if (bShowIdle) // 找到了
{
ShowWindow(SW_SHOWNORMAL);
UpdateWindow();
bShowIdle = FALSE; // 指示下一次Idle 时不用显示对话框了
}
While 里的条件是消息队列里再也没有任何消息了。此时,由于 bShowIdle 为 TRUE ,就会调用 ShowWindow 来显示对话框。由于 ShowWindow 只执行一次,所以如果能截获第一次WM_SHOWWINDOW消息, 就能控制了隐藏了。是的。在 CTestDlg 处理 WM_SHOWWINDOW 并添上以下代码void CTestDlg::OnShowWindow(BOOL bShow, UINT nStatus)
{ if( GetStyle() & WS_VISIBLE ) {
CDialog::OnShowWindow(bShow, nStatus);
} else {
long Style = ::GetWindowLong(*this, GWL_STYLE);
::SetWindowLong(*this, GWL_STYLE, Style | WS_VISIBLE);
CDialog::OnShowWindow(SW_HIDE, nStatus);
}
}
再运行一下,哈哈,对话框不见了,连闪都不闪一下。细心的读者也许会问为什么使用SetWindowLong,而不是 ModifyStyle, 其实是为了加快速度,因为 ModifyStyle 内部还要调用 GetWindowLong 和 SetWindowPos。到此为止,一个简单,完满的解决方法已经展现在大家面前了。其实,本来 MS 可以做的更好,比如把 GetStyle() 声明为虚函数,使得我们能返回WS_VISIBLE 来控制 bShowIdle 成为 FALSE, 或者把 DWORD dwFlags = MLF_SHOWONIDLE;改成 DWORD dwFlags = ShowOnIdle(); // 声明为虚函数
希望MS能在以后的版本中考虑这个问题。
CDrawDlg* dlg=new CDrawDlg;
dlg->Create(IDD_DIALOG2);
dlg->ShowWindow(SW_HIDE);
{
WINDOWPLACEMENT wp;
wp.length=sizeof(WINDOWPLACEMENT);
wp.flags=WPF_RESTORETOMAXIMIZED;
wp.showCmd=SW_HIDE;
SetWindowPlacement(&wp); //this function.
..
}