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


    作者:朱金灿

    来源:http://blog.csdn.net/clever101

     

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

     

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

    头文件的代码:

    // kdialog.h
    #ifndef KDIALOG_H_INCLUDED
    #define KDIALOG_H_INCLUDED
    
    #define ID_HELP   150
    #define ID_EDIT	  180
    #define ID_TEXT   200
    
    class KDialog
    {
    public:
    
        KDialog(HINSTANCE hinst, HWND hwndOwner);
    
        ~KDialog();
    
        virtual INT_PTR DoModal();
    
    protected:
    
        // API中注册的消息处理函数,不能是成员函数,因为成员函数有this指针
        static BOOL CALLBACK DialogProc(HWND hWnd,
                                           UINT uMsg, WPARAM wParam, LPARAM lParam);
    
    private:
    
        HWND  m_hOwnerWnd;
    
        HINSTANCE m_hInst;
    
    };
    
    
    
    #endif // KDIALOG_H_INCLUDED
    

         

    Cpp文件的代码:

        

    #include "kdialog.h"
    
    #include "resource.h"
    
    BOOL CALLBACK DialogProc (HWND, UINT, WPARAM, LPARAM) ;
    
    LPWORD lpwAlign ( LPWORD lpIn)
    {
        ULONG ul;
    
        ul = (ULONG) lpIn;
        ul +=3;
        ul >>=2;
        ul <<=2;
        return (LPWORD) ul;
    }
    
    KDialog::KDialog(HINSTANCE hinst, HWND hwndOwner)
    {
        m_hInst = hinst;
        m_hOwnerWnd = hwndOwner;
    }
    
    KDialog::~KDialog()
    {
    
    }
    
    char nEditTwo[128]= "从这儿输入字符串." ;
    
    BOOL CALLBACK KDialog::DialogProc(HWND hDlg,
                                         UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
           switch (uMsg)
    	 {
              case WM_INITDIALOG :
    			   SetDlgItemText ( hDlg, ID_EDIT, nEditTwo );
                   return TRUE ;
    
              case WM_COMMAND :
                   switch (LOWORD (wParam))
                   {
    					case ID_EDIT :
    						 GetDlgItemText (hDlg, ID_EDIT, nEditTwo, 127);
    						 return TRUE;
    					case ID_HELP :
    						 MessageBox( NULL, nEditTwo, "输入数据", MB_OK | MB_SYSTEMMODAL | MB_NOFOCUS);
    						 return TRUE;
    		            case IDOK :
                             EndDialog (hDlg, 0) ;
    			             return TRUE ;
    			   }
                  break ;
                case WM_CLOSE:
                      EndDialog (hDlg, 0) ;
                      return TRUE ;
            default:
              break;
         }
         return FALSE ;
    }
    
    INT_PTR KDialog::DoModal()
    {
        HGLOBAL hgbl;
        LPDLGTEMPLATE lpdt;
        LPDLGITEMTEMPLATE lpdit;
        LPWORD lpw;
        LPWSTR lpwsz;
        LRESULT ret;
        int nchar;
    
        hgbl = GlobalAlloc(GMEM_ZEROINIT, 1024);
        if (!hgbl)
            return -1;
    
        lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl);
    
        // Define a dialog box.
    
        lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU
                      | DS_MODALFRAME | WS_CAPTION;
        lpdt->cdit = 3;  // number of controls
        lpdt->x  = 10;
        lpdt->y  = 10;
        lpdt->cx = 100;
        lpdt->cy = 70;
    
        lpw = (LPWORD) (lpdt + 1);
        *lpw++ = 0;   // no menu
        *lpw++ = 0;   // predefined dialog box class (by default)
    
        lpwsz = (LPWSTR) lpw;
        nchar = 1+ MultiByteToWideChar (CP_ACP, 0, "内存对话框", -1,
                                        lpwsz, 50);
        lpw   += nchar;
    
        //-----------------------
        // Define an OK button.
        //-----------------------
        lpw = lpwAlign (lpw);
    
        lpdit = (LPDLGITEMTEMPLATE) lpw;
        lpdit->x  = 10;
        lpdit->y  = 50;
        lpdit->cx = 80;
        lpdit->cy = 15;
        lpdit->id = IDOK;  // OK button identifier
        lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON;
    
        lpw = (LPWORD) (lpdit + 1);
        *lpw++ = 0xFFFF;
        *lpw++ = 0x0080;    // button class
    
        lpwsz = (LPWSTR) lpw;
        nchar = 1+MultiByteToWideChar (CP_ACP, 0, "退出", -1, lpwsz, 50);
        lpw   += nchar;
        *lpw++ = 0;              // no creation data
    
    
        //-----------------------
        // Define a Help button.
        //-----------------------
        lpw = lpwAlign (lpw);
    
        lpdit = (LPDLGITEMTEMPLATE) lpw;
        lpdit->x  = 10;
        lpdit->y  = 30;
        lpdit->cx = 80;
        lpdit->cy = 15;
        lpdit->id = ID_HELP;    // Help button identifier
        lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON;
    
        lpw = (LPWORD) (lpdit + 1);
        *lpw++ = 0xFFFF;
        *lpw++ = 0x0080;                 // button class atom
    
        lpwsz = (LPWSTR) lpw;
        nchar = 1+MultiByteToWideChar (CP_ACP, 0, "显示输入", -1, lpwsz, 50);
        lpw   += nchar;
        *lpw++ = 0;                      // no creation data
    
    
        //-----------------------
        // Define a EDIT.
        //-----------------------
        lpw = lpwAlign (lpw);
    
        lpdit = (LPDLGITEMTEMPLATE) lpw;
        lpdit->x  = 10;
        lpdit->y  = 10;
        lpdit->cx = 80;
        lpdit->cy = 12;
        lpdit->id = ID_EDIT;    // Help button identifier
        lpdit->style = ES_LEFT | WS_BORDER | WS_TABSTOP | WS_CHILD | WS_VISIBLE;
    
        lpw = (LPWORD) (lpdit + 1);
        *lpw++ = 0xFFFF;
        *lpw++ = 0x0081;                 // edit class atom
        *lpw++ = 0;                      // no creation data
    
        GlobalUnlock(hgbl);
    
        ret = DialogBoxIndirect(m_hInst,
                                (LPDLGTEMPLATE) hgbl,
                                m_hOwnerWnd,
                                (DLGPROC) DialogProc);
    
        GlobalFree(hgbl);
        return ret;
    }
    

       

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

        
                 KDialog dlg(m_hInst,m_hWnd);
                  dlg.DoModal();
    


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

    BOOL KDialog::DoModeless()
    {
            HGLOBAL hgbl;
        LPDLGTEMPLATE lpdt;
        LPDLGITEMTEMPLATE lpdit;
        LPWORD lpw;
        LPWSTR lpwsz;
        LRESULT ret;
        int nchar;
    
        hgbl = GlobalAlloc(GMEM_ZEROINIT, 1024);
        if (!hgbl)
            return FALSE;
    
        lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl);
    
        // Define a dialog box.
    
        lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU
                      | DS_MODALFRAME | WS_CAPTION;
        lpdt->cdit = 3;  // number of controls
        lpdt->x  = 10;
        lpdt->y  = 10;
        lpdt->cx = 100;
        lpdt->cy = 70;
    
        lpw = (LPWORD) (lpdt + 1);
        *lpw++ = 0;   // no menu
        *lpw++ = 0;   // predefined dialog box class (by default)
    
        lpwsz = (LPWSTR) lpw;
        nchar = 1+ MultiByteToWideChar (CP_ACP, 0, "内存对话框", -1,
                                        lpwsz, 50);
        lpw   += nchar;
    
        //-----------------------
        // Define an OK button.
        //-----------------------
        lpw = lpwAlign (lpw);
    
        lpdit = (LPDLGITEMTEMPLATE) lpw;
        lpdit->x  = 10;
        lpdit->y  = 50;
        lpdit->cx = 80;
        lpdit->cy = 15;
        lpdit->id = IDOK;  // OK button identifier
        lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON;
    
        lpw = (LPWORD) (lpdit + 1);
        *lpw++ = 0xFFFF;
        *lpw++ = 0x0080;    // button class
    
        lpwsz = (LPWSTR) lpw;
        nchar = 1+MultiByteToWideChar (CP_ACP, 0, "退出", -1, lpwsz, 50);
        lpw   += nchar;
        *lpw++ = 0;              // no creation data
    
    
        //-----------------------
        // Define a Help button.
        //-----------------------
        lpw = lpwAlign (lpw);
    
        lpdit = (LPDLGITEMTEMPLATE) lpw;
        lpdit->x  = 10;
        lpdit->y  = 30;
        lpdit->cx = 80;
        lpdit->cy = 15;
        lpdit->id = ID_HELP;    // Help button identifier
        lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON;
    
        lpw = (LPWORD) (lpdit + 1);
        *lpw++ = 0xFFFF;
        *lpw++ = 0x0080;                 // button class atom
    
        lpwsz = (LPWSTR) lpw;
        nchar = 1+MultiByteToWideChar (CP_ACP, 0, "显示输入", -1, lpwsz, 50);
        lpw   += nchar;
        *lpw++ = 0;                      // no creation data
    
    
        //-----------------------
        // Define a EDIT.
        //-----------------------
        lpw = lpwAlign (lpw);
    
        lpdit = (LPDLGITEMTEMPLATE) lpw;
        lpdit->x  = 10;
        lpdit->y  = 10;
        lpdit->cx = 80;
        lpdit->cy = 12;
        lpdit->id = ID_EDIT;    // Help button identifier
        lpdit->style = ES_LEFT | WS_BORDER | WS_TABSTOP | WS_CHILD | WS_VISIBLE;
    
        lpw = (LPWORD) (lpdit + 1);
        *lpw++ = 0xFFFF;
        *lpw++ = 0x0081;                 // edit class atom
        *lpw++ = 0;                      // no creation data
    
        GlobalUnlock(hgbl);
    
        HWND hDlg = CreateDialogIndirect(m_hInst,
                                (LPDLGTEMPLATE) hgbl,
                                m_hOwnerWnd,
                                (DLGPROC) DialogProc);
        if(NULL==hDlg)
           return FALSE;
    
        ::ShowWindow(hDlg,SW_SHOW);
    
        GlobalFree(hgbl);
        return TRUE;
    }
    


    效果图如下:


     

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



  • 相关阅读:
    关于投资的思考(95) 熊市的几个感性指标,Luna暴雷的次级灾害,美联储加息75个基点,俄乌冲突升级能源价格大涨
    关于投资的思考(94) 以太跌到1000附近,大饼跌到2万附近,熊市的几个感性指标和段子
    关于投资的思考(93) 以太大跌的原因和抄底策略讨论,马丁策略,关于NFT国内数藏,抢鲸探的经验
    关于投资的思考(96) 比特币跌破18000关机价,以太跌破882,是否可以抄底了?塔勒布三部曲,熊市的几个参考指标
    string to base64 or base64 to string in ms sql server
    convert datetime to timestamp in ms sql server
    React Suspense 尝鲜,处理前后端IO异步操作
    基于Vite+React构建在线Excel
    CentOS中实现基于Docker部署BI数据分析
    BI与SaaS碰撞,让数据处理更加轻松(下)
  • 原文地址:https://www.cnblogs.com/lanzhi/p/6470859.html
Copyright © 2020-2023  润新知