一般而言,在 Windows编程中创建对话框需要先定义一个对话框资源。我想能不能不用资源文件单纯通过代码创建对话框呢?晚上搜索了一些资料,研究了一下,基本实现了。
我写了一个KDialog,代码如下(代码中有一些注释,相信大家能基本看懂):
头文件的代码:
- <span style="font-size:16px;">// 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
- </span>
Cpp文件的代码:
- <span style="font-size:16px;">#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;
- }
- </span>
外部调用的方法也很简单(把应用程序句柄和对话框的所有者窗口句柄传进来即可):
- <span style="font-size:16px;"> KDialog dlg(m_hInst,m_hWnd);
- dlg.DoModal();
- </span>
上面创建的是模式对话框,下面是创建非模式对话框的代码:
- 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++
分类:
VC/MFC
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
2012-11-21 assert()函数用法总结 .
2012-11-21 堆和栈的区别(转过无数次的文章) .
2012-11-21 Win32 多线程的创建方法和基本使用 .
2012-11-21 stdcall、cdecl 和pascal简介 .
2012-11-21 windows程序调试
2012-11-21 VS2005设置可以在Release模式下调试 .
2012-11-21 如何在对话框中实现文件拖放功能