不使用资源文件动态创建对话框的做法

一般而言,在 Windows编程中创建对话框需要先定义一个对话框资源。我想能不能不用资源文件单纯通过代码创建对话框呢?晚上搜索了一些资料,研究了一下,基本实现了。

 

我写了一个KDialog,代码如下(代码中有一些注释,相信大家能基本看懂):

头文件的代码:

[cpp]   view plain copy
  1. <span style="font-size:16px;">// kdialog.h  
  2. #ifndef KDIALOG_H_INCLUDED  
  3. #define KDIALOG_H_INCLUDED  
  4.   
  5. #define ID_HELP   150  
  6. #define ID_EDIT   180  
  7. #define ID_TEXT   200  
  8.   
  9. class KDialog  
  10. {  
  11. public:  
  12.   
  13.     KDialog(HINSTANCE hinst, HWND hwndOwner);  
  14.   
  15.     ~KDialog();  
  16.   
  17.     virtual INT_PTR DoModal();  
  18.   
  19. protected:  
  20.   
  21.     // API中注册的消息处理函数,不能是成员函数,因为成员函数有this指针  
  22.     static BOOL CALLBACK DialogProc(HWND hWnd,  
  23.                                        UINT uMsg, WPARAM wParam, LPARAM lParam);  
  24.   
  25. private:  
  26.   
  27.     HWND  m_hOwnerWnd;  
  28.   
  29.     HINSTANCE m_hInst;  
  30.   
  31. };  
  32.   
  33.   
  34.   
  35. #endif // KDIALOG_H_INCLUDED  
  36. </span>  

     

Cpp文件的代码:

    

[cpp]   view plain copy
  1. <span style="font-size:16px;">#include "kdialog.h"  
  2.   
  3. #include "resource.h"  
  4.   
  5. BOOL CALLBACK DialogProc (HWNDUINTWPARAMLPARAM) ;  
  6.   
  7. LPWORD lpwAlign ( LPWORD lpIn)  
  8. {  
  9.     ULONG ul;  
  10.   
  11.     ul = (ULONG) lpIn;  
  12.     ul +=3;  
  13.     ul >>=2;  
  14.     ul <<=2;  
  15.     return (LPWORD) ul;  
  16. }  
  17.   
  18. KDialog::KDialog(HINSTANCE hinst, HWND hwndOwner)  
  19. {  
  20.     m_hInst = hinst;  
  21.     m_hOwnerWnd = hwndOwner;  
  22. }  
  23.   
  24. KDialog::~KDialog()  
  25. {  
  26.   
  27. }  
  28.   
  29. char nEditTwo[128]= "从这儿输入字符串." ;  
  30.   
  31. BOOL CALLBACK KDialog::DialogProc(HWND hDlg,  
  32.                                      UINT uMsg, WPARAM wParam, LPARAM lParam)  
  33. {  
  34.        switch (uMsg)  
  35.      {  
  36.           case WM_INITDIALOG :  
  37.                SetDlgItemText ( hDlg, ID_EDIT, nEditTwo );  
  38.                return TRUE ;  
  39.   
  40.           case WM_COMMAND :  
  41.                switch (LOWORD (wParam))  
  42.                {  
  43.                     case ID_EDIT :  
  44.                          GetDlgItemText (hDlg, ID_EDIT, nEditTwo, 127);  
  45.                          return TRUE;  
  46.                     case ID_HELP :  
  47.                          MessageBox( NULL, nEditTwo, "输入数据", MB_OK | MB_SYSTEMMODAL | MB_NOFOCUS);  
  48.                          return TRUE;  
  49.                     case IDOK :  
  50.                          EndDialog (hDlg, 0) ;  
  51.                          return TRUE ;  
  52.                }  
  53.               break ;  
  54.             case WM_CLOSE:  
  55.                   EndDialog (hDlg, 0) ;  
  56.                   return TRUE ;  
  57.         default:  
  58.           break;  
  59.      }  
  60.      return FALSE ;  
  61. }  
  62.   
  63. INT_PTR KDialog::DoModal()  
  64. {  
  65.     HGLOBAL hgbl;  
  66.     LPDLGTEMPLATE lpdt;  
  67.     LPDLGITEMTEMPLATE lpdit;  
  68.     LPWORD lpw;  
  69.     LPWSTR lpwsz;  
  70.     LRESULT ret;  
  71.     int nchar;  
  72.   
  73.     hgbl = GlobalAlloc(GMEM_ZEROINIT, 1024);  
  74.     if (!hgbl)  
  75.         return -1;  
  76.   
  77.     lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl);  
  78.   
  79.     // Define a dialog box.  
  80.   
  81.     lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU  
  82.                   | DS_MODALFRAME | WS_CAPTION;  
  83.     lpdt->cdit = 3;  // number of controls  
  84.     lpdt->x  = 10;  
  85.     lpdt->y  = 10;  
  86.     lpdt->cx = 100;  
  87.     lpdt->cy = 70;  
  88.   
  89.     lpw = (LPWORD) (lpdt + 1);  
  90.     *lpw++ = 0;   // no menu  
  91.     *lpw++ = 0;   // predefined dialog box class (by default)  
  92.   
  93.     lpwsz = (LPWSTR) lpw;  
  94.     nchar = 1+ MultiByteToWideChar (CP_ACP, 0, "内存对话框", -1,  
  95.                                     lpwsz, 50);  
  96.     lpw   += nchar;  
  97.   
  98.     //-----------------------  
  99.     // Define an OK button.  
  100.     //-----------------------  
  101.     lpw = lpwAlign (lpw);  
  102.   
  103.     lpdit = (LPDLGITEMTEMPLATE) lpw;  
  104.     lpdit->x  = 10;  
  105.     lpdit->y  = 50;  
  106.     lpdit->cx = 80;  
  107.     lpdit->cy = 15;  
  108.     lpdit->id = IDOK;  // OK button identifier  
  109.     lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON;  
  110.   
  111.     lpw = (LPWORD) (lpdit + 1);  
  112.     *lpw++ = 0xFFFF;  
  113.     *lpw++ = 0x0080;    // button class  
  114.   
  115.     lpwsz = (LPWSTR) lpw;  
  116.     nchar = 1+MultiByteToWideChar (CP_ACP, 0, "退出", -1, lpwsz, 50);  
  117.     lpw   += nchar;  
  118.     *lpw++ = 0;              // no creation data  
  119.   
  120.   
  121.     //-----------------------  
  122.     // Define a Help button.  
  123.     //-----------------------  
  124.     lpw = lpwAlign (lpw);  
  125.   
  126.     lpdit = (LPDLGITEMTEMPLATE) lpw;  
  127.     lpdit->x  = 10;  
  128.     lpdit->y  = 30;  
  129.     lpdit->cx = 80;  
  130.     lpdit->cy = 15;  
  131.     lpdit->id = ID_HELP;    // Help button identifier  
  132.     lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON;  
  133.   
  134.     lpw = (LPWORD) (lpdit + 1);  
  135.     *lpw++ = 0xFFFF;  
  136.     *lpw++ = 0x0080;                 // button class atom  
  137.   
  138.     lpwsz = (LPWSTR) lpw;  
  139.     nchar = 1+MultiByteToWideChar (CP_ACP, 0, "显示输入", -1, lpwsz, 50);  
  140.     lpw   += nchar;  
  141.     *lpw++ = 0;                      // no creation data  
  142.   
  143.   
  144.     //-----------------------  
  145.     // Define a EDIT.  
  146.     //-----------------------  
  147.     lpw = lpwAlign (lpw);  
  148.   
  149.     lpdit = (LPDLGITEMTEMPLATE) lpw;  
  150.     lpdit->x  = 10;  
  151.     lpdit->y  = 10;  
  152.     lpdit->cx = 80;  
  153.     lpdit->cy = 12;  
  154.     lpdit->id = ID_EDIT;    // Help button identifier  
  155.     lpdit->style = ES_LEFT | WS_BORDER | WS_TABSTOP | WS_CHILD | WS_VISIBLE;  
  156.   
  157.     lpw = (LPWORD) (lpdit + 1);  
  158.     *lpw++ = 0xFFFF;  
  159.     *lpw++ = 0x0081;                 // edit class atom  
  160.     *lpw++ = 0;                      // no creation data  
  161.   
  162.     GlobalUnlock(hgbl);  
  163.   
  164.     ret = DialogBoxIndirect(m_hInst,  
  165.                             (LPDLGTEMPLATE) hgbl,  
  166.                             m_hOwnerWnd,  
  167.                             (DLGPROC) DialogProc);  
  168.   
  169.     GlobalFree(hgbl);  
  170.     return ret;  
  171. }  
  172. </span>  

   

    外部调用的方法也很简单(把应用程序句柄和对话框的所有者窗口句柄传进来即可):

    
[cpp]   view plain copy
  1. <span style="font-size:16px;">             KDialog dlg(m_hInst,m_hWnd);  
  2.               dlg.DoModal();  
  3. </span>  


上面创建的是模式对话框,下面是创建非模式对话框的代码:

[cpp]   view plain copy
  1. BOOL KDialog::DoModeless()  
  2. {  
  3.         HGLOBAL hgbl;  
  4.     LPDLGTEMPLATE lpdt;  
  5.     LPDLGITEMTEMPLATE lpdit;  
  6.     LPWORD lpw;  
  7.     LPWSTR lpwsz;  
  8.     LRESULT ret;  
  9.     int nchar;  
  10.   
  11.     hgbl = GlobalAlloc(GMEM_ZEROINIT, 1024);  
  12.     if (!hgbl)  
  13.         return FALSE;  
  14.   
  15.     lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl);  
  16.   
  17.     // Define a dialog box.  
  18.   
  19.     lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU  
  20.                   | DS_MODALFRAME | WS_CAPTION;  
  21.     lpdt->cdit = 3;  // number of controls  
  22.     lpdt->x  = 10;  
  23.     lpdt->y  = 10;  
  24.     lpdt->cx = 100;  
  25.     lpdt->cy = 70;  
  26.   
  27.     lpw = (LPWORD) (lpdt + 1);  
  28.     *lpw++ = 0;   // no menu  
  29.     *lpw++ = 0;   // predefined dialog box class (by default)  
  30.   
  31.     lpwsz = (LPWSTR) lpw;  
  32.     nchar = 1+ MultiByteToWideChar (CP_ACP, 0, "内存对话框", -1,  
  33.                                     lpwsz, 50);  
  34.     lpw   += nchar;  
  35.   
  36.     //-----------------------  
  37.     // Define an OK button.  
  38.     //-----------------------  
  39.     lpw = lpwAlign (lpw);  
  40.   
  41.     lpdit = (LPDLGITEMTEMPLATE) lpw;  
  42.     lpdit->x  = 10;  
  43.     lpdit->y  = 50;  
  44.     lpdit->cx = 80;  
  45.     lpdit->cy = 15;  
  46.     lpdit->id = IDOK;  // OK button identifier  
  47.     lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON;  
  48.   
  49.     lpw = (LPWORD) (lpdit + 1);  
  50.     *lpw++ = 0xFFFF;  
  51.     *lpw++ = 0x0080;    // button class  
  52.   
  53.     lpwsz = (LPWSTR) lpw;  
  54.     nchar = 1+MultiByteToWideChar (CP_ACP, 0, "退出", -1, lpwsz, 50);  
  55.     lpw   += nchar;  
  56.     *lpw++ = 0;              // no creation data  
  57.   
  58.   
  59.     //-----------------------  
  60.     // Define a Help button.  
  61.     //-----------------------  
  62.     lpw = lpwAlign (lpw);  
  63.   
  64.     lpdit = (LPDLGITEMTEMPLATE) lpw;  
  65.     lpdit->x  = 10;  
  66.     lpdit->y  = 30;  
  67.     lpdit->cx = 80;  
  68.     lpdit->cy = 15;  
  69.     lpdit->id = ID_HELP;    // Help button identifier  
  70.     lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON;  
  71.   
  72.     lpw = (LPWORD) (lpdit + 1);  
  73.     *lpw++ = 0xFFFF;  
  74.     *lpw++ = 0x0080;                 // button class atom  
  75.   
  76.     lpwsz = (LPWSTR) lpw;  
  77.     nchar = 1+MultiByteToWideChar (CP_ACP, 0, "显示输入", -1, lpwsz, 50);  
  78.     lpw   += nchar;  
  79.     *lpw++ = 0;                      // no creation data  
  80.   
  81.   
  82.     //-----------------------  
  83.     // Define a EDIT.  
  84.     //-----------------------  
  85.     lpw = lpwAlign (lpw);  
  86.   
  87.     lpdit = (LPDLGITEMTEMPLATE) lpw;  
  88.     lpdit->x  = 10;  
  89.     lpdit->y  = 10;  
  90.     lpdit->cx = 80;  
  91.     lpdit->cy = 12;  
  92.     lpdit->id = ID_EDIT;    // Help button identifier  
  93.     lpdit->style = ES_LEFT | WS_BORDER | WS_TABSTOP | WS_CHILD | WS_VISIBLE;  
  94.   
  95.     lpw = (LPWORD) (lpdit + 1);  
  96.     *lpw++ = 0xFFFF;  
  97.     *lpw++ = 0x0081;                 // edit class atom  
  98.     *lpw++ = 0;                      // no creation data  
  99.   
  100.     GlobalUnlock(hgbl);  
  101.   
  102.     HWND hDlg = CreateDialogIndirect(m_hInst,  
  103.                             (LPDLGTEMPLATE) hgbl,  
  104.                             m_hOwnerWnd,  
  105.                             (DLGPROC) DialogProc);  
  106.     if(NULL==hDlg)  
  107.        return FALSE;  
  108.   
  109.     ::ShowWindow(hDlg,SW_SHOW);  
  110.   
  111.     GlobalFree(hgbl);  
  112.     return TRUE;  
  113. }  


效果图如下:

不使用资源文件动态创建对话框的做法

 

      具体的实现原理,大家请参考这篇文章:对话框模板,RegexTest,微软官网上也有相关的文章:UsingDialog Boxes。此外CodeProject上的一个例子:UsingDialog Templates to create an InputBox() in C++


你可能感兴趣的:(对话框)