• 八、MFC对话框


    一、Win32对话框

            模式对话框:子对话框未关闭,父对话框无法拖拽和关闭

            无模式对话框:子对话框未关闭,父对话框可以拖拽和关闭

    1、创建项目

    (1)创建Win32项目(WinDlg)

    (2)添加资源文件(.rc文件),添加菜单项

    (3)添加对话框

     (4)编写程序

    1. #include
    2. #include "resource.h"
    3. HINSTANCE g_hInstance = 0;
    4. INT CALLBACK DlgProc( HWND hwndlg, UINT msgID, WPARAM wParam, LPARAM lParam ){
    5. switch( msgID ){
    6. case WM_DESTROY:
    7. MessageBox( NULL, "我要死了", "Infor", MB_OK );
    8. break;
    9. case WM_SYSCOMMAND:
    10. if( wParam == SC_CLOSE ){
    11. HWND hWnd = GetParent( hwndlg );
    12. EnableWindow( hWnd ,TRUE );
    13. DestroyWindow( hwndlg );//销毁无模式对话框, 切忌不能EndDialog
    14. // EndDialog( hwndlg, 1001 );//只能隐藏无模式对话框, 可以销毁模式对话框
    15. }
    16. break;
    17. }
    18. return FALSE;//对话框的消息交给真正对话框窗口处理函数处理。
    19. }
    20. void OnNoModel( HWND hWnd ){
    21. EnableWindow( hWnd, FALSE );
    22. // HWND hDlg = CreateDialog( g_hInstance, MAKEINTRESOURCE(IDD_DIALOG1), hWnd, DlgProc );//直接创建
    23. HRSRC hRs = FindResource( g_hInstance, MAKEINTRESOURCE(IDD_DIALOG1), RT_DIALOG );
    24. HGLOBAL hGl = LoadResource( g_hInstance, hRs );
    25. LPCDLGTEMPLATE pTemplate = (LPCDLGTEMPLATE)LockResource( hGl );
    26. HWND hDlg = CreateDialogIndirect( g_hInstance, pTemplate, hWnd, DlgProc );
    27. ShowWindow( hDlg, SW_SHOW );
    28. }
    29. void OnCommand( HWND hWnd, WPARAM wParam ){
    30. switch(LOWORD(wParam)){
    31. case ID_NOMODEL:
    32. OnNoModel( hWnd );
    33. break;
    34. }
    35. }
    36. //窗口处理函数( 自定义,处理消息)
    37. LRESULT CALLBACK WndProc( HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam ){
    38. switch(msgID){
    39. case WM_COMMAND:
    40. OnCommand( hWnd, wParam );
    41. break;
    42. case WM_DESTROY:
    43. PostQuitMessage( 0 );
    44. break;
    45. }
    46. return DefWindowProc( hWnd, msgID, wParam, lParam );
    47. }
    48. //入口函数
    49. int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns, LPSTR lpCmdLine, int nCmdShow){
    50. g_hInstance = hIns;
    51. //注册窗口类
    52. WNDCLASS wc = { 0 };
    53. wc.cbClsExtra = 0;
    54. wc.cbWndExtra = 0;
    55. wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    56. wc.hCursor = NULL;
    57. wc.hIcon = NULL;
    58. wc.hInstance = hIns;
    59. wc.lpfnWndProc = WndProc;
    60. wc.lpszClassName = "Main";
    61. wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);//(CHAR*)IDR_MENU1;
    62. wc.style = CS_HREDRAW | CS_VREDRAW;
    63. RegisterClass( &wc );//将以上所有赋值全部写入操作系统。
    64. //在内存创建窗口
    65. HWND hWnd = CreateWindowEx( 0, "Main", "window", WS_OVERLAPPEDWINDOW,
    66. 100, 100, 500, 500, NULL, NULL, hIns, NULL );
    67. //显示窗口
    68. ShowWindow( hWnd, SW_SHOW );
    69. UpdateWindow( hWnd );
    70. //消息循环
    71. MSG nMsg = { 0 };
    72. while( GetMessage(&nMsg,NULL,0,0) ){
    73. TranslateMessage( &nMsg );
    74. DispatchMessage( &nMsg );//将消息交给窗口处理函数来处理。
    75. }
    76. return 0;
    77. }

    二、MFC无模式对话框

            对话框分类:模式对话框(假,由无模式对话框实现);无模式对话框

    1、对话框框架的使用

    (1)参与架构的类

            CDialog / CWinApp

    2、创建MFC无模式对话框项目

    (1)创建(Win32)项目(MFCDlg)

    (2)创建资源文件(.rc),创建对话框

    (3)编写程序

    1. #include
    2. #include "resource.h"
    3. class CMyDlg:public CDialog
    4. {
    5. DECLARE_MESSAGE_MAP()
    6. public:
    7. void OnOK();
    8. };
    9. BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
    10. ON_COMMAND(IDOK, OnOK)
    11. END_MESSAGE_MAP()
    12. void CMyDlg::OnOK()
    13. {
    14. CDialog::OnOK();
    15. }
    16. class CMyWinApp:public CWinApp
    17. {
    18. public:
    19. virtual BOOL InitInstance();
    20. };
    21. BOOL CMyWinApp::InitInstance()
    22. {
    23. CMyDlg* pdlg = new CMyDlg;
    24. pdlg->Create(IDD_DIALOG1);
    25. m_pMainWnd = pdlg;
    26. pdlg->ShowWindow(SW_SHOW);
    27. return TRUE;
    28. }
    29. CMyWinApp theApp;

    (4)执行过程

    1. AFX_MODULE_STATE aaa;//当前程序模块状态信息
    2. AFX_MODULE_THREAD_STATE bbb; //当前程序线程状态信息
    3. CWinApp::CWinApp()//构造全局对象CMyWinApp theApp
    4. {
    5. AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
    6. //获取全局变量&aaa
    7. AFX_MODULE_THREAD_STATE* pThreadState = pModuleState->m_thread;
    8. //获取全局变量&bbb
    9. pThreadState->m_pCurrentWinThread = this;//将&theApp保存到bbb的一个成员中
    10. AfxGetThread()
    11. {
    12. AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();//获取&bbb
    13. CWinThread* pThread = pState->m_pCurrentWinThread;
    14. return pThread;//返回的为&theApp
    15. }
    16. pModuleState->m_pCurrentWinApp = this;//将&theApp保存到aaa的一个成员中
    17. AfxGetApp()
    18. {
    19. return AfxGetModuleState()->m_pCurrentWinApp;//返回&theApp
    20. }
    21. }
    22. 进入入口函数
    23. WinMain(...)
    24. {
    25. AfxWinMain(..)
    26. {
    27. CWinThread* pThread = AfxGetThread();
    28. CWinApp* pApp = AfxGetApp();//获取&theApp
    29. pApp->InitApplication();//利用theApp调用应用程序类的成员 虚函数(初始化)
    30. pThread->InitInstance()//利用theApp调用应用程序类的成员 虚函数(创建并显示无模式对话框)
    31. {
    32. CMyDlg* pdlg = new CMyDlg;
    33. pdlg->Create( IDD_DIALOG1 )//函数内部this为pdlg(自己new的对话框类对象地址)
    34. {
    35. CDialog::Create(MAKEINTRESOURCE(IDD_DIALOG1), ..)//函数内部this为pdlg
    36. {
    37. //查找对话框资源
    38. HRSRC hResource = ::FindResource(hInst, lpszTemplateName, RT_DIALOG);
    39. //加载对话框资源
    40. HGLOBAL hTemplate = LoadResource(hInst, hResource);
    41. //以上两行代码,查找并加载对话框资源
    42. CreateIndirect(MAKEINTRESOURCE(IDD_DIALOG1), ...)
    43. {
    44. //锁定对话框资源
    45. LPCDLGTEMPLATE lpDialogTemplate = LockResource(hDialogTemplate);
    46. CreateIndirect(lpDialogTemplate..)
    47. {
    48. CreateDlgIndirect(...)
    49. {
    50. ::CreateDialogIndirect(...);//以间接方式创建无模式对话框
    51. }
    52. }
    53. }
    54. }
    55. }
    56. }
    57. pThread->Run()//函数内部this为&theApp
    58. {
    59. CWinThread::Run()//函数内部this为&theApp
    60. {
    61. for (;;)
    62. {
    63. while(没有消息时)
    64. {
    65. OnIdle(..);//空闲处理(虚函数)
    66. }
    67. do
    68. {
    69. if(::GetMessage抓到WM_QUIT消息)
    70. return ExitInstance(..);//善后处理(虚函数)
    71. }while(...)
    72. }
    73. }
    74. }
    75. }
    76. }

    (5)点击OK/确定处理流程

    1. CDialog::OnOK()
    2. {
    3. EndDialog(IDOK)
    4. {
    5. ::EndDialog(m_hWnd, nResult);//只能将无模式对话框隐藏
    6. }
    7. }

    (6)在命令IDOK与IDCANCEL销毁对话框,可以实现关闭对话框

    1. #include
    2. #include "resource.h"
    3. class CMyDlg:public CDialog
    4. {
    5. DECLARE_MESSAGE_MAP()
    6. public:
    7. void OnOK();
    8. void OnCancel();
    9. };
    10. BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
    11. ON_COMMAND(IDOK, OnOK)
    12. ON_COMMAND(IDCANCEL, OnCancel)
    13. END_MESSAGE_MAP()
    14. void CMyDlg::OnOK()
    15. {
    16. //::DestroyWindow(this->m_hWnd);
    17. this->DestroyWindow();
    18. }
    19. void CMyDlg::OnCancel()
    20. {
    21. //::DestroyWindow(this->m_hWnd);
    22. this->DestroyWindow();
    23. }
    24. class CMyWinApp:public CWinApp
    25. {
    26. public:
    27. virtual BOOL InitInstance();
    28. };
    29. BOOL CMyWinApp::InitInstance()
    30. {
    31. CMyDlg* pdlg = new CMyDlg;
    32. pdlg->Create(IDD_DIALOG1);
    33. m_pMainWnd = pdlg;
    34. pdlg->ShowWindow(SW_SHOW);
    35. return TRUE;
    36. }
    37. CMyWinApp theApp;

    三、模式对话框(由无模式对话框实现)

    1、无模式对话框使用

    参与框架的类

            CDialog / CWinApp

    2、创建项目

    (1)创建(Win32)项目(MFCModelDlg)

    (2)添加资源文件(.rc)

    (3)添加对话框资源

    (4)编写程序

    1. #include
    2. #include "resource.h"
    3. class CMyDlg:public CDialog
    4. {
    5. public:
    6. enum{IDD=IDD_DIALOG1};
    7. CMyDlg():CDialog(IDD)
    8. {
    9. };
    10. };
    11. class CMyWinApp:public CWinApp
    12. {
    13. public:
    14. virtual BOOL InitInstance();
    15. };
    16. BOOL CMyWinApp::InitInstance()
    17. {
    18. CMyDlg dlg;
    19. m_pMainWnd = &dlg;
    20. dlg.DoModal();
    21. return TRUE;
    22. }
    23. CMyWinApp theApp;

    (5)执行过程

    1. AFX_MODULE_STATE aaa;//当前程序模块状态信息
    2. AFX_MODULE_THREAD_STATE bbb; //当前程序线程状态信息
    3. CWinApp::CWinApp()//构造全局对象CMyWinApp theApp
    4. {
    5. AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
    6. //获取全局变量&aaa
    7. AFX_MODULE_THREAD_STATE* pThreadState = pModuleState->m_thread;
    8. //获取全局变量&bbb
    9. pThreadState->m_pCurrentWinThread = this;//将&theApp保存到bbb的一个成员中
    10. AfxGetThread()
    11. {
    12. AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();//获取&bbb
    13. CWinThread* pThread = pState->m_pCurrentWinThread;
    14. return pThread;//返回的为&theApp
    15. }
    16. pModuleState->m_pCurrentWinApp = this;//将&theApp保存到aaa的一个成员中
    17. AfxGetApp()
    18. {
    19. return AfxGetModuleState()->m_pCurrentWinApp;//返回&theApp
    20. }
    21. }
    22. 进入入口函数
    23. WinMain(...)
    24. {
    25. AfxWinMain(..)
    26. {
    27. CWinThread* pThread = AfxGetThread();
    28. CWinApp* pApp = AfxGetApp();//获取&theApp
    29. pApp->InitApplication();//利用theApp调用应用程序类的成员 虚函数(初始化)
    30. pThread->InitInstance()
    31. {
    32. CMyDlg dlg===CDialog(IDD)//函数内部this为&dlg
    33. {
    34. m_lpszTemplateName=MAKEINTRESOURCE(IDD)//将对话框资源ID保存dlg的一个成员中
    35. }
    36. m_pMainWnd = &dlg;
    37. dlg.DoModal( )//函数内部this为&dlg
    38. {
    39. HRSRC hResource = ::FindResource(hInst, m_lpszTemplateName, RT_DIALOG);
    40. hDialogTemplate = LoadResource(hInst, hResource);
    41. lpDialogTemplate = (LPCDLGTEMPLATE)LockResource(hDialogTemplate);
    42. //以上三行代码,查找加载并锁定对话框资源
    43. HWND hWndParent = PreModal();//获取父窗口的句柄
    44. ::EnableWindow(hWndParent, FALSE);//将父窗口设置为不可用状态
    45. CreateDlgIndirect(...);//间接方式创建无模式对话框
    46. RunModalLoop(...)//函数内部this为&dlg
    47. {
    48. for (;;) //消息循环
    49. {
    50. while(没有消息){ 空闲处理 }
    51. do{
    52. 消息循环的相关函数;
    53. if (!ContinueModal())//函数内部this为&dlg(m_nFlags(24/8) & 0x0010)
    54. goto ExitModal;
    55. }while(....);
    56. }
    57. ExitModal:
    58. return m_nModalResult;
    59. }
    60. }
    61. ::EnableWindow(hWndParent, TRUE);//将父窗口设置为可用
    62. DestroyWindow();//销毁无模式对话框
    63. return m_nModalResult;//????dlg的一个成员变量
    64. }
    65. }
    66. }

    (6)点击确认按钮

    1. class CMyDlg:public CDialog
    2. {
    3. DECLARE_MESSAGE_MAP()
    4. public:
    5. enum{IDD=IDD_DIALOG1};
    6. CMyDlg():CDialog(IDD)
    7. {
    8. };
    9. afx_msg void OnOK();
    10. };
    11. BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
    12. ON_COMMAND(IDOK, OnOK)
    13. END_MESSAGE_MAP()
    14. void CMyDlg::OnOK()
    15. {
    16. CDialog::OnOK();
    17. }

    消息处理流程

    1. CDialog::OnOK()//函数内部this为&dlg
    2. {
    3. EndDialog(IDOK) //参数为1
    4. {
    5. EndModalLoop(IDOK)//函数内部this为&dlg
    6. {
    7. m_nModalResult = IDOK; // 1
    8. m_nFlags = 8;
    9. }
    10. ::EndDialog(m_hWnd, nResult);//只能将无模式对话框隐藏
    11. }
    12. }
    13. CDialog::OnCancel()//函数内部this为&dlg
    14. {
    15. EndDialog(IDCANCEL) //参数为2
    16. {
    17. EndModalLoop(IDCANCEL)//函数内部this为&dlg
    18. {
    19. m_nModalResult = IDCANCEL; // 1
    20. m_nFlags = 8;
    21. }
    22. ::EndDialog(m_hWnd, nResult);//只能将无模式对话框隐藏
    23. }
    24. }

    (7)OnModal内部执行过程

            将父窗口设置为不可用

            创建无模式对话框

            进入消息循环(自带的)

            退出消息循环(父类的OnOK/OnCancel导致循环退出)

            将父窗口设置为可用状态

            销毁无模式对话框

    返回的值导致CWinApp的Run函数不再执行

  • 相关阅读:
    Karl Guttag:AR眼镜应根据用途来设计,VST并未解决技术难题
    微信加解密流程,证书作用讲解,官方SDK使用教程
    Linux生成UUID的算法方式(序列号C/C++代码实现)
    1.14 - 流水线
    每晚坚持10点前睡觉,半年后有什么变化?感觉自己年轻好几岁
    嵌入式开发:选择嵌入式GUI生成器时要注意什么
    超星平台——东电影答案
    宝,运维100+服务器很头疼怎么办?用行云管家!
    算法|Day49 动态规划17
    Spring Data JPA与Mybatis的对比
  • 原文地址:https://blog.csdn.net/liutit/article/details/126111210