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

作者:朱金灿

来源: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++



你可能感兴趣的:(不使用资源文件动态创建对话框的做法)