作者:朱金灿
来源: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++