




已阅读5页,还剩6页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
关于OnOK()、OnCancel()、OnClose()、OnDestroy() 模式对话框非模式对话框总结OnOK()、OnCancel()、OnClose()、OnDestroy()之间的区别(转)2009年09月22日 下午 08:33第一,OnOK()和OnCancel()是CDialog基类的成员函数,而OnClose()和OnDestroy()是CWnd基类的成员函数,即WM消息响应函数。从应用程序结构的角度,拿对话框来说,红色的X对应的是CWnd,而处于对话框中的“确定”、“取消”按钮则对应了CDialog。第二,OnClose()和OnDestroy()在单视图程序中,根据所讲,程序退出时执行的操作顺序为(从点X按钮开始)(1)用户点击X退出按钮,发送了WM_CLOSE消息-响应OnClose()(2)在WM_CLOSE消息的处理函数中,调用DestroyWindow()-销毁与指定CWnd窗口对象关联的窗口,但未销毁CWnd对象(3)在DestroyWindow()中发送了WM_DESTROY消息-窗口销毁后响应OnDestroy()(4)在WM_DESTROY消息中调用PostQuitMessage(),发送WM_QUIT消息,结束消息循环可以看到,程序的退出过程,是先响应OnClose(),然后响应OnDestroy(),在响应OnDestroy()之前,窗口对象已经被销毁。OnDestroy()到底干了什么呢?它就像一个teller,先通知CWnd对象告诉它即将被销毁,尔后OnDestroy的真正运行是在CWnd对象已经从屏幕上清除以后被调用的。第三,OnOK()、OnCancel()()、OnClose()、OnDestroy()CDialog:OnOK首先调用UpdateData(TRUE)将数据传给对话框成员变量,然后调用CDialog:EndDialog关闭对话框;CDialog:OnCancel只调用CDialog:EndDialog关闭对话框;OnClose()是响应 WM_CLOSE 的.一定程度上可以说CDialog:EndDialog()和OnClose()完成类似的工作,但处理的机制不一样,前者是CDialog的对象机制,后者是WM的消息映射机制。CDialog:EndDialog()-OnDestroy()OnClose()-OnDestroy()EndDialog()和OnClose()属于“同级别”的,所以我们在按下OK按钮的时候,程序是不会执行OnClose()的,但两种机制都必须经过OnDestroy()本文来自CSDN博客,转载请标明出处:/wind1987321/archive/2009/09/21/4576585.aspx然后发现下面这两种说法不明晰(1) EndDialog(-1);关闭模态对话框,并且将参数作为父对话框调用的返回值。(2) DestroyWindow(); :PostQuitMessage(0);DestroyWindow 关闭非模态对话框。 退出消息循环,真正结束进程。有不少程序窗口关闭,但是不等于退出运行。cDialog:onok(),enddialog(),destroywindow区别。 收藏模式和无模式对话的中止是不一样的:模式对话通过调用CDialog : : EndDialog 来中止,无模式对话则是调用CWnd: : DestroyWindow来中止的,函数CDialog : : OnOK和CDialog : : OnCancel调用EndDialog ,所以需要调用DestroyWindow并重置无模式对话的函数。最后三个还不错Windows API一日一练(18)EndDialog函数 收藏上一次介绍了怎么样显示对话框的函数,那么怎么样关闭对话框呢?这就需要使用到函数EndDialog。这个函数只能在对话框的消息处理函数里使用,并且这个函数调用之后,没有立即就删除对话框的,而是设置了操作系统里的结束标志。当操作系统查检到有这个标志时,就去删除对话框的消息循环,同时也去释放对话框占用的资源。其实对话框的生命周期是这样的,先由函数DialogBox创建对话框,这样函数DialogBox完成创建对话框但还没有显示前会发出消息WM_INITDIALOG,让对话框有机会初始化上面所有窗口或控件的显示,比如设置文本框的字符串等。最后当用户点出确定或者取消的按钮,就收到两个命令IDOK或IDCANCEL,这时就可以调用函数EndDialog来结束对话框的生命。函数EndDialog声明如下:WINUSERAPIBOOLWINAPIEndDialog(_in HWND hDlg,_in INT_PTR nResult);hDlg是对话框窗口的句柄。nResult是设置给函数DialogBox的返回值。调用这个函数的例子如下:#001 / 显示关于对话框。#002 /#003 / 蔡军生 2007/07/12#004 /#005 INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)#006 #007 UNREFERENCED_PARAMETER(lParam);#008 switch (message)#009 #010 case WM_INITDIALOG:#011 return (INT_PTR)TRUE;#012#013 case WM_COMMAND:#014 if (LOWORD(wParam) = IDOK | LOWORD(wParam) = IDCANCEL)#015 #016 EndDialog(hDlg, LOWORD(wParam);#017 return (INT_PTR)TRUE;#018 #019 break;#020 #021 return (INT_PTR)FALSE;#022 第16行就是调用函数EndDialog来关闭对话框。本文来自CSDN博客,转载请标明出处:/caimouse/archive/2007/07/30/1716140.aspx非模式对话框2009-03-23 17:101、非模式对话框的打开:/ 弹出无模式对话框CDevPproperty *pDlg= new CDevPproperty;pDlg-Create(IDD_DEV_PROPERTY,GetDesktopWindow();/ 填充设备属性,用SetDlgItemInt()时就不用再定义一个CString来将数据转换成字符串了pDlg-SetDlgItemInt(IDC_EDT_DEV_ID,i,TRUE);/ 为了实现向组合框发送选项,而又不想定义变量,所以这里用了消息传递pWnd=pDlg-GetDlgItem(IDC_CMB_DEV_STATUS);pWnd-SetFocus(); / 设置对话框中的焦点pWnd-SendMessage(CB_SETCURSEL,CDeviceInfoi.status,0);/ 显示窗口pDlg-ShowWindow(SW_SHOW);2、关闭非模式对话框:DestroyWindow();delete this;3、在非模式对话框中向主对话框发送消息:/ 获取全局句柄,然后调用Invalidate()来更新窗口AfxGetMainWnd()-Invalidate();4、主窗口中向非模式对话框发送消息/ 填充设备属性,用SetDlgItemInt()时就不用再定义一个CString来将数据转换成字符串了pDlg-SetDlgItemInt(IDC_EDT_DEV_ID,i,TRUE);/ 为了实现向组合框发送选项,而又不想定义变量,所以这里用了消息传递pWnd=pDlg-GetDlgItem(IDC_CMB_DEV_STATUS);pWnd-SetFocus(); / 设置对话框中的焦点pWnd-SendMessage(CB_SETCURSEL,CDeviceInfoi.status,0);5、将非模式对话框显示在父窗口后面,并且可以切换一种解决办法是:建立非模式对话框时Create的第二个参数用GetDesktopWindow(),m_pDlg-Create(IDD_,GetDesktopWindow();如果需要恢复Toolbar的属性:m_pDlg-SetWindowPos(&wndTopMost,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);现在有出现了一个问题:系统的任务栏上出现了非模式对话框的图标,好像该对话框和父窗口是两个应用。解决的办法是:1 定义对象 CWnd *m_pWnd,该对象的父窗口为GetDesktopWindow,设置该对象ShowWindow(SW_HIDE);2 将非模式对话框的父窗口设置为m_pWnd。6、非模式对话框与主对话框是一个消息循环7、如何取得非模式对话框的父窗口指针取父窗口指针用GetParent()或class CWnd* hWnd = FindWindow(NULL,窗口标题);8、基于文档/视图的主窗口均是CMainFrame对象,需要在CView内响应的消息应该这样发送:CMainFrame *pwnd = (CMainFrame *)GetParent();pwnd-GetActiveView()-SendMessage(.)9、怎样才能在线程中实现对话框的顶层显示。不知为什么设置成WS_EX_TOPMOST并不能实现,可能我们还没有真正理解它该怎样使用。但我用另外的方法实现了:SetWindowPos (&wndTopMost, 0, 0, 0, 0,SWP_NOMOVE | SWP_NOSIZE)。10、建立非模态对话框时,它总是在主窗口的最上面,如何才能使它的主窗口显示在上面.答:1)你有没有试过AfxGetMainWnd()-SetForegroundWindow(),在建立你的非模态对话框之后?2)当你建立对话框时,向导建立的构造函数有一个指针指出该对话框的父窗口,如果你输入一个窗口,那么该对话框将总是显示在该窗口的上面,如果你输入一个NULL 那么该对话框就可以在主程序窗口的上面或者下面了.不过这时要仔细考虑用户界面,如果非模态对话框在主窗口消失,会不会让你的用户产生误会?是否将非模态对话框显示在任务条上.11、MSDN中非模式对话框的代码CMyDialog* pDialog;void CMyWnd:OnSomeAction()/pDialog initialized to NULL in the constructor of CMyWnd classpDialog = new CMyDialog();/Check if new succeeded and we got a valid pointer to a dialog objectif(pDialog != NULL)BOOL ret = pDialog-Create(IDD_MYDIALOG,this);if(!ret) /Create failed.AfxMessageBox(Error creating Dialog);pDialog-ShowWindow(SW_SHOW);elseAfxMessageBox(Error Creating Dialog Object);14、由于非模式对话框是在堆中动态分配的,所以每次弹出时,其中的一些变量如果弹出多个的话会有些冲突,比如我在显示每个设备的电量时,由于要用图形显示出来,所以要保存好原来的位置,然后再从第一个位置开始循环画点,这个时候就会发现,弹出的多个对话框中的值是相同的,因此必须要区分开来,我用了两种办法,一是用数组,可以是二维,也可以是一维的,这样呢,用其中的id号作标识。另一个方法是将这些全局变量声明在类内,作为类的变量存在,这样就不会互相干扰了。看代码在非模式对话框头文件中加入变量:其中m_pt是为了保存所有的点的位置,而m_pt_num保存的是点的数目,m_index保存的是一个循环的索引CPoint m_ptX_GRID_NUM;int m_pt_num;int m_index;在非模式对话框程序中加入:CBrush drawBrush;drawBrush.CreateSolidBrush(RGB(255,255,0); / 初始化画刷,为黄色pDC-SelectObject(&drawBrush); / 选择画刷pDC-Ellipse(CRect(-3,-3,3,3); / 画圆,RFD类型为圆圈Sleep(100);len = (rc.right-20)/X_GRID_NUM;m_pt_num = (m_pt_num+1) % X_GRID_NUM;m_ptm_pt_num.x=len*m_pt_num;m_ptm_pt_num.y=-CDeviceInfoid.power/2;for(m_index=1; m_indexEllipse(CRect(m_ptm_index.x-1,m_ptm_index.y-1,m_ptm_index.x+2,m_ptm_index.y+2);pDC-MoveTo(m_ptm_index-1);pDC-LineTo(m_ptm_index);这个很棒/question/62651044.html对话框默认用的两个按钮的ID分别是IDOK和IDCANCEL,这两个都是在winuser.h 中预定义的系统标准控件ID。 对于标准ID,你不重载时MFC会自动调用父类的相应处理函数。 比如IDOK映射到CDialog:OnOK()函数,IDCANCEL映射到CDialog:OnCancel()。 在这两个函数的源码如下: void CDialog:OnOK() if (!UpdateData(TRUE) TRACE(traceAppMsg, 0, UpdateData failed during dialog termination.n); / the UpdateData routine will set focus to correct item return; EndDialog(IDOK); void CDialog:OnCancel() EndDialog(IDCANCEL); 可以看出点击这两个按钮,都会调用EndDialog()来关闭对话框,只是返回值不同。 EndDialog()函数调用了DestroyWindow()函数,DestroyWindow()函数又发送了WM_DESTROY消息,该消息的处理函数是OnDestroy(),对话框的生存期最后一个函数是PostNcDestroy()函数。 点那个叉叉呢,首先向对话框发送WM_CLOSE消息,由OnClose()函数处理,它调用DestroyWindow(),其后是和上面一样的路由。 可以看出点叉叉的时候绕过了OnOK()和OnCancel()。 小结一下: 1. 点“确定”、“取消”时的关闭路由为 OnOK()或OnCancel() - EndDialog() - DestroyWindow() - OnDestroy() - PostNcDestroy() 2. 点“关闭”标题栏按钮的关闭路由为 OnClose()- DestroyWindow() - OnDestroy() - PostNcDestroy() 回答楼主的问题: 请注意,上面提到的这些函数统统都是可以重载的,在重载时加入了你自己的代码后,应该调用父类CDialog同名的函数才能正确路由下去,否则就关不了对话框了。 举个例子,重载了关闭的小叉叉 void CAboutDlg:OnClose() / TODO: 在此添加消息处理程序代码和/或调用默认值 DoSomthing(0; / 执行自己的判断等等 / CDialog:OnClose(); / 把向导生成的父类调用给注释了,这时就关不了对话框了。 补充回答,点叉叉会发送WM_CLOSE消息,如果需要重载的话,应该在对话框的属性窗口中,选择WM_CLOSE消息来添加消息处理函数。 VS的IDE会自动添加如下三段: 1. xxx.h文件,类声明中加入OnClose()函数声明 afx_msg void OnClose(); 2. xxx.cpp文件,加入消息映射宏 ON_WM_CLOSE() / 对于Windows标准消息,都是这种简短的格式。 3. xxx.cpp文件,加入函数体 void CMyDlg:OnClose() CDialog:OnClose(); 上述3处如果都正常的话,叉叉就映射到OnClose()了。你说的映射到OnCancel()个人觉得有两种可能,第一、缺ON_WM_CLOSE()宏,却多个一个ON_BN_CLICKED(IDCLOSE, &CMyDlg:OnCancel)宏第二、在OnClose()中调用了OnCancel()论模式和非模式对话框2009-03-23 17:11论模式和非模式对话框. 11:摘要. 12:模式对话框的显示. 13:模式对话框的循环等待. 34:模式对话框的循环终止. 65:与OK和Cancle按钮的联系. 61:摘要模式对话框使用dlg.DoModal()函数,程序会在你按下OK或者Cancle按钮之前处于等待状态。然后点击OK或者Cancle按钮,就可以调用EndDialog函数消除模式对话框。相比之下,非模式对话框可能要显得复杂,你要使用Create函数创建非模式对话框,并且在推出时,必须调用CWnd:DestroyWindow函数销毁窗口。 而且要注意的是,你若想点击OK按钮使非模式对话框推出,要重写OnOK函数,使其调用CWnd:DestroyWindow。那么,这是为什么呢?模式对话框的实现真的比非模式要简单吗?让我们看一下CDialog:DoModal()的源代码。2:模式对话框的显示INT_PTR CDialog:DoModal()*/加载模板资源*ASSERT(m_lpszTemplateName != NULL | m_hDialogTemplate != NULL |m_lpDialogTemplate != NULL);/ load resource as necessaryLPCDLGTEMPLATE lpDialogTemplate = m_lpDialogTemplate;HGLOBAL hDialogTemplate = m_hDialogTemplate;HINSTANCE hInst = AfxGetResourceHandle();if (m_lpszTemplateName != NULL)hInst = AfxFindResourceHandle(m_lpszTemplateName, RT_DIALOG);HRSRC hResource = :FindResource(hInst, m_lpszTemplateName, RT_DIALOG);hDialogTemplate = LoadResource(hInst, hResource);if (hDialogTemplate != NULL)lpDialogTemplate = (LPCDLGTEMPLATE)LockResource(hDialogTemplate);/ return -1 in case of failure to load the dialog template resourceif (lpDialogTemplate = NULL)return -1;*/使父窗口无效*HWND hWndParent = PreModal();AfxUnhookWindowCreate();BOOL bEnableParent = FALSE;if (hWndParent & hWndParent != :GetDesktopWindow() & :IsWindowEnabled(hWndParent):EnableWindow(hWndParent, FALSE);bEnableParent = TRUE;TRY*/创建非模式对话框*AfxHookWindowCreate(this);if (CreateDlgIndirect(lpDialogTemplate,CWnd:FromHandle(hWndParent), hInst)if (m_nFlags & WF_CONTINUEMODAL)/ enter modal loopDWORD dwFlags = MLF_SHOWONIDLE;if (GetStyle() & DS_NOIDLEMSG)dwFlags |= MLF_NOIDLEMSG;*/关键:调用RunModalLoop函数,程序进入其内的for循环/所以,模式对话框在点击OK或Cancel前,程序会暂时等待。*VERIFY(RunModalLoop(dwFlags) = m_nModalResult);*/在父窗口可用前,先隐藏对话框(注:暂时还没有销毁)*if (m_hWnd != NULL)SetWindowPos(NULL, 0, 0, 0, 0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);CATCH_ALL(e)DELETE_EXCEPTION(e);m_nModalResult = -1;END_CATCH_ALL*/使父窗口可用,并且激活父窗口*if (bEnableParent):EnableWindow(hWndParent, TRUE);if (hWndParent != NULL & :GetActiveWindow() = m_hWnd):SetActiveWindow(hWndParent);*/销毁对话框*/ destroy modal windowDestroyWindow();PostModal();/ unlock/free resources as necessaryif (m_lpszTemplateName != NULL | m_hDialogTemplate != NULL)UnlockResource(hDialogTemplate);if (m_lpszTemplateName != NULL)FreeResource(hDialogTemplate);return m_nModalResult;3:模式对话框的循环等待从上面的代码,我们可以发现,模式对话框的底层为我们实现了对话框的create和destroywindow,所以我们可以只管dlg.domoadl()来显示,然后调用EndDialog来结束。那么EndDialog 的作用是什么呢?我们看它里面的循环函数,就可以理解,原来Enddialog的作用其实是为了跳出循环函数RunModalLoop,使程序继续执行。具体代码如下:int CWnd:RunModalLoop(DWORD dwFlags)ASSERT(:IsWindow(m_hWnd); / window must be createdASSERT(!(m_nFlags & WF_MODALLOOP); / window must not already be in modal state/ for tracking the idle time stateBOOL bIdle = TRUE;LONG lIdleCount = 0;BOOL bShowIdle = (dwFlags & MLF_SHOWONIDLE) & !(GetStyle() & WS_VISIBLE);HWND hWndParent = :GetParent(m_hWnd);m_nFlags |= (WF_MODALLOOP|WF_CONTINUEMODAL);MSG *pMsg = AfxGetCurrentMessage();*/通过for (;),使程序处于循环等待状态。*for (;)ASSERT(ContinueModal();/ phase1: check to see if we can do idle workwhile (bIdle &!:PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE)ASSERT(ContinueModal();/ show the dialog when the message queue goes idleif (bShowIdle)ShowWindow(SW_SHOWNORMAL);UpdateWindow();bShowIdle = FALSE;/ call OnIdle while in bIdle stateif (!(dwFlags & MLF_NOIDLEMSG) & hWndParent != NULL & lIdleCount = 0)/ send WM_ENTERIDLE to the parent:SendMessage(hWndParent, WM_ENTERIDLE, MSGF_DIALOGBOX, (LPARAM)m_hWnd);if (dwFlags & MLF_NOKICKIDLE) |!SendMessage(WM_KICKIDLE, MSGF_DIALOGBOX, lIdleCount+)/ stop idle processing next timebIdle = FALSE;/ phase2: pump messages while availabledoASSERT(ContinueModal();/ pump message, but quit on WM_QUITif (!AfxPumpMessage()AfxPostQuitMessage(0);return -1;/ show the window when certain special messages recdif (bShowIdle &(pMsg-message = 0x118 | pMsg-message = WM_SYSKEYDOWN)ShowWindow(SW_SHOWNORMAL);UpdateWindow();bShowIdle = FALSE;*8/通过判断,跳出循环,可以断定,EndDialog 和ContinueModal有联系*if (!ContinueModal()goto ExitModal;/ reset no idle state after pumping normal messageif (AfxIs
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年安徽师范大学出版社招聘4人考前自测高频考点模拟试题及参考答案详解一套
- 2025年甘肃交通职业技术学院招聘工作人员模拟试卷含答案详解
- 2025江西吉水县某行政单位招聘4人模拟试卷及答案详解(考点梳理)
- 2025江苏南通市公安局招聘警务辅助人员66人考前自测高频考点模拟试题及一套答案详解
- 2025届春季中核集团校园招聘正式启动考前自测高频考点模拟试题及答案详解(典优)
- 2025年洛阳古墓博物馆人才引进招录专业技术人员2名模拟试卷及完整答案详解1套
- 2025年延安通和电业有限责任公司招聘(5人)模拟试卷及答案详解(易错题)
- 2025湖南湘西州泸溪县妇幼保健计划生育服务中心招聘高校见习生5人模拟试卷及完整答案详解一套
- 2025年陕西师范大学校医院招聘(2人)考前自测高频考点模拟试题及1套参考答案详解
- 2025年滁州职业技术学院引进急需紧缺高层次人才25人模拟试卷及答案详解(易错题)
- 2025四川成都高新投资集团有限公司选聘中高层管理人员4人笔试参考题库附答案解析
- 水利工程水利工程施工技术规范
- 从安全感缺失剖析《榆树下的欲望》中爱碧的悲剧根源与启示
- 2025中证金融研究院招聘11人考试参考题库及答案解析
- 人教版(2024)八年级上册英语Unit 2 Home Sweet Home教案
- 城镇住宅建设调查技术实施方案
- 渔民安全培训课件
- 时空数据建模与预测算法-洞察阐释
- 汽车电路原理培训课件
- 2025年长江引航中心招聘笔试备考题库(带答案详解)
- 压力性损伤的个案护理
评论
0/150
提交评论