文章来源 https://www.freesion.com/article/730931766/

Visual Studio的MFC向导可以生成基于对话框的程序,而win32向导却不支持,是不是很不给力呢?虽然VAX可以直接插入对话框的代码段,但还是没有直接生成来得爽,下面就动手来改造吧。

本文所做的修改仅在自己的VS里测试通过,大家修改之前请备份原文件。

那我们需要改什么呢?看图吧:

首先,找到"VS安装目录\VC\VCWizards\AppWiz\Generic\Application",如我电脑上的目录就是
“D:\Program Files\Microsoft Visual Studio 11.0\VC\VCWizards\AppWiz\Generic\Application” 这个目录下就是Win向导的文件了,有四个文件夹,分别是:

不同语言版本的VS,这些目录下会有不同名字的文件夹,都是按LCID来命名,关于LCID,可以参考 MSDN

例如英文版的LCID就是1033,简体中文的就是2052。

html\1033目录下有两个htm文件,AppSettings.htm、和Default.htm,这里先修改AppSettings.htm,

我这里用DW打开AppSettings.htm,然后定位到35行,按下图插入代码:

这一段就是定义了顶部的图片,依样画葫芦,插入的代码内容如下:

1
2
3
<DIV CLASS="SMALL" ID="WIN_DLG_APP_IMAGE" STYLE="DISPLAY:NONE;">
<IMG CLASS="SMALL" SRC="..\..\Images\Dialog.gif" ALT="" BORDER="0">
</DIV>

这里我为了偷懒,直接将

“D:\Program Files\Microsoft Visual Studio 11.0\VC\VCWizards\AppWiz\MFC\Application\images\Dialog.gif”

复制到

"D:\Program Files\Microsoft Visual Studio 11.0\VC\VCWizards\AppWiz\Generic\Application\images"目录下。

接着,定位到197行,按图插入代码:

看到这里懂点html的同学应该知道了吧?这里就是向导对话框中那几单选按钮。还是和之前一样,依样画葫芦。插入的代码内容如下:

1
2
3
4
5
 <INPUT TYPE="radio" CLASS="Radio" onPropertyChange="InitControls();" NAME="apptype" ID="WIN_DLG_APP" ACCESSKEY="B" TITLE="Creates a dialog-based Windows application. The application files include a <projectname>.cpp file that contains the _tWinMain function, and stdafx.cpp and stdafx.h files that are used to create the precompiled header file.">
<DIV CLASS="itemTextRadioB" ID="WIN_DLG_APP_DIV" TITLE="Creates a dialog-based Windows application. The application files include a <projectname>.cpp file that contains the _tWinMain function, and stdafx.cpp and stdafx.h files that are used to create the precompiled header file.">
<LABEL FOR="WIN_DLG_APP" ID="WIN_DLG_APP_LABEL">Dialog-<U>b</U>ased windows application</LABEL>
</DIV>
<BR>

然后再定位到370行,按图插入代码:

插入的代码如下:

1
WIN_DLG_APP.disabled = true;

然后定位到425行,由于我们是要创建基于对话框的的程序,所以没理由是空项目。。所以这里不需要添加空项目的开关;插入的代码如图:

插入的代码如下:

1
2
3
4
5
if (WIN_DLG_APP.checked)
{
SUPPORT_ATL.disabled = false;
support_atl_title.disabled = false;
}

定位到526行,插入代码如图:

插入的代码内容如下:

1
2
3
4
5
6
7

if (WIN_DLG_APP.checked)
{
SUPPORT_ATL.disabled = false;
support_atl_title.disabled = false;
}

定位到第562行,插入代码如图:

插入的代码如下:

1
2
3
4
5
6
 WIN_DLG_APP_IMAGE.style.display = 'none';
if (WIN_DLG_APP.checked)
{
WIN_DLG_APP_IMAGE.style.display = 'block';
return;
}

至此第一个文件修改完了。。好长呐。。。

继续修改第二个文件default.htm,依然是用DW来打开。定位到11行,插入代码如图:

插入的代码内容:

1
<SYMBOL NAME="WIN_DLG_APP" TYPE=checkbox VALUE=false></SYMBOL>

定位到342行,插入代码如图:

顺便吐槽下:微软的coder原来用的是多层嵌套的if。。看着DT。于是我便改成了else if的。。看起来舒服。

插入的代码内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var L_APPTYPEWIN_DLG_TEXT = "Dialog-based windows application";

if (window.external.FindSymbol("DLL_APP"))
{
APPTYPE.innerText = L_APPTYPEDLL_TEXT;
}
else if (window.external.FindSymbol("CONSOLE_APP"))
{
APPTYPE.innerText = L_APPTYPECON_TEXT;
}
else if (window.external.FindSymbol("LIB_APP"))
{
APPTYPE.innerText = L_APPTYPELIB_TEXT;
}
else if (window.external.FindSymbol("WIN_DLG_APP"))
{
APPTYPE.innerText = L_APPTYPEWIN_DLG_TEXT;
}
else
{
APPTYPE.innerText = L_APPTYPEWIN_TEXT;
}

hoho,第二个文件改好了。

此时打开向导就可以看到已经添加好了,剩下的就是修改代码模板了,继续吧。

打开"scripts\1033\default.js",定位到96行,插入代码如图:

插入代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
if (wizard.FindSymbol("CONSOLE_APP"))
{
strAppType = "CONSOLE";
}
else if (wizard.FindSymbol("WIN_APP"))
{
strAppType = "WIN";
}
else if (wizard.FindSymbol("WIN_DLG_APP"))
{
strAppType = "WIN_DLG";
}
else if (wizard.FindSymbol("DLL_APP"))
{
strAppType = "DLL";
}
else if (wizard.FindSymbol("LIB_APP"))
{
strAppType = "LIB";
}

然后再定位到176行,插入代码如图:

插入代码内容如下:

1
case "WIN_DLG":

定位到192行,插入代码如图:

然后再定位到241行和261行做同样的修改。又改完一个文件了。。。。

找到"templates\1033"目录,打开readme.txt,分别定位到22行、73行、88行分别修改成如下文本:

22行:

1
[!if WIN_APP || WIN_DLG_APP]

73行:

1
[!if WIN_APP || WIN_DLG_APP || SUPPORT_MFC]

88行:

1
[!if WIN_APP || WIN_DLG_APP]

这个文件就完事了,下一个文件resource.h

将6-17行替换成如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[!if !WIN_DLG_APP]
#define IDS_APP_TITLE 103
[!endif]

[!if WIN_APP || WIN_DLG_APP]
[!if WIN_APP]
#define IDR_MAINFRAME 128
#define IDD_ABOUTBOX 103
#define IDM_ABOUT 104
#define IDM_EXIT 105
#define IDC_[!output UPPER_CASE_SAFE_PROJECT_IDENTIFIER_NAME] 109
#define IDC_MYICON 2
[!endif]
#define IDD_[!output UPPER_CASE_SAFE_PROJECT_IDENTIFIER_NAME]_DIALOG 102
#define IDI_[!output UPPER_CASE_SAFE_PROJECT_IDENTIFIER_NAME] 107
#define IDI_SMALL 108

接下来需要先在这个目录下创建一个文件,名为"CmnHdr.h",这个头文件的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#pragma once   // Include this header file once per compilation unit

/////////////////////////// chHANDLE_DLGMSG Macro /////////////////////////////


// The normal HANDLE_MSG macro in WindowsX.h does not work properly for dialog
// boxes because DlgProc returns a BOOL instead of an LRESULT (like
// WndProcs). This chHANDLE_DLGMSG macro corrects the problem:
#define chHANDLE_DLGMSG(hWnd, message, fn) \
case (message): return (SetDlgMsgResult(hWnd, uMsg, \
HANDLE_##message((hWnd), (wParam), (lParam), (fn))))


//////////////////////// Dialog Box Icon Setting Macro ////////////////////////


// Sets the dialog box icons
inline void chSETDLGICONS(HWND hWnd, int idi) {
SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM)
LoadIcon((HINSTANCE) GetWindowLongPtr(hWnd, GWLP_HINSTANCE),
MAKEINTRESOURCE(idi)));
SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM)
LoadIcon((HINSTANCE) GetWindowLongPtr(hWnd, GWLP_HINSTANCE),
MAKEINTRESOURCE(idi)));
}

看过《Windows 核心编程》的都应该见过上面这段代码吧。作用我就不解释了。

接着修改root.cpp,这个文件里就引用到了刚才上一步添加的头文件,定位到第4行和第13行,修改成如下代码:

4行:

1
[!if WIN_APP || WIN_DLG_APP]

13行:

1
[!if WIN_APP || SUPPORT_MFC || WIN_DLG_APP]

然后再定位240行,在[!else]之后插入如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
[!if WIN_DLG_APP]
#include "CmnHdr.h"

// Global Variables:
const TCHAR g_szAppName[] = _T("[!output PROJECT_NAME]"); // The application title text

// Forward declarations of functions included in this code module:
INT_PTR CALLBACK Dlg_Proc(HWND, UINT, WPARAM, LPARAM);
BOOL Dlg_OnInitDialog(HWND, HWND, LPARAM);
void Dlg_OnCommand(HWND, int, HWND, UINT);

// entry function
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPTSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
INT_PTR nResult = DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_[!output UPPER_CASE_SAFE_PROJECT_IDENTIFIER_NAME]_DIALOG),
NULL, Dlg_Proc, _ttoi(lpCmdLine));
return nResult;
}

//
// FUNCTION: Dlg_Proc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Message handler for Dialog box
//
INT_PTR CALLBACK Dlg_Proc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
chHANDLE_DLGMSG(hwndDlg, WM_INITDIALOG, Dlg_OnInitDialog);
chHANDLE_DLGMSG(hwndDlg, WM_COMMAND, Dlg_OnCommand);
}
return FALSE;
}

//
// FUNCTION: Dlg_OnInitDialog(HWND, HWND, LPARAM)
//
// PURPOSE: Initialize the dialog box.
//
BOOL Dlg_OnInitDialog(HWND hwndDlg, HWND hwndFocus, LPARAM lParam)
{
// Sets the dialog box icons
chSETDLGICONS(hwndDlg, IDI_[!output UPPER_CASE_SAFE_PROJECT_IDENTIFIER_NAME]);
return TRUE;
}

//
// FUNCTION: Dlg_OnCommand(HWND, int, HWND, UINT)
//
// PURPOSE: Command message handler for dialog box
//
void Dlg_OnCommand(HWND hwndDlg, int id, HWND hwndCtl, UINT codeNotify)
{
switch (id)
{
case IDOK:
case IDCANCEL:
EndDialog(hwndDlg, id);
break;
default:break;
}
}
[!endif]

又一文件改好,继续下一个文件stdafx.h,将38行-43行的内容替换成如下的代码:

1
2
3
4
5
6
7
8
9
[!if DLL_APP || WIN_APP || WIN_DLG_APP]
// Windows Header Files:
#include <windows.h>
[!endif]
[!if WIN_DLG_APP]
// Message Crackers, Child Control Macros, and API Macros Header file:
#include <Windowsx.h>
[!endif]
[!if WIN_APP || WIN_DLG_APP]

然后在文件末尾加上下面这段代码:

1
2
3
4
5
6
7
8
9
#ifdef _UNICODE
#if defined _M_IX86
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_X64
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#else
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#endif
#endif

目的是为了在UNICODE环境下支持XP/Vista/Win7的样式.

然后再修改下一个文件,Templates.inf,将13行、17行、24行修改成如下代码:

13行:

1
[!if WIN_APP || WIN_DLG_APP || SUPPORT_MFC]

17行:

1
[!if WIN_APP || WIN_DLG_APP || SUPPORT_MFC]

24行:

1
[!if WIN_APP || WIN_DLG_APP]

然后再定位18行,在这行后面加上CmnHdr.h,这样在创建时就会自动把这个文件复制到工程目录下。

最后一个要修改的文件,root.rc,这是一个资源脚本文件,为了方便,我调整了代码结构,这里将整个文件的代码发出来:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
//Microsoft Visual C++ generated resource script.
//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
[!if WIN_APP || WIN_DLG_APP]
#ifndef APSTUDIO_INVOKED
#include "targetver.h"
#endif
#define APSTUDIO_HIDDEN_SYMBOLS
#include "windows.h"
#undef APSTUDIO_HIDDEN_SYMBOLS
[!else]
#include "afxres.h"
[!endif]
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_[!output LANG_SUFFIX])
LANGUAGE [!output PRIMARY_LANG_ID], [!output SUB_LANG_ID]

[!if WIN_APP || WIN_DLG_APP]
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//

// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.

IDI_[!output UPPER_CASE_SAFE_PROJECT_IDENTIFIER_NAME] ICON "[!output PROJECT_NAME].ico"
IDI_SMALL ICON "small.ico"
[!if WIN_DLG_APP]

/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//

#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_[!output UPPER_CASE_SAFE_PROJECT_IDENTIFIER_NAME]_DIALOG, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 313
TOPMARGIN, 7
BOTTOMMARGIN, 193
END
END
#endif // APSTUDIO_INVOKED

/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//

IDD_[!output UPPER_CASE_SAFE_PROJECT_IDENTIFIER_NAME]_DIALOG DIALOGEX 0, 0, 320, 200
STYLE DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
EXSTYLE WS_EX_APPWINDOW
CAPTION "[!output PROJECT_NAME]"
FONT 8, "MS Shell Dlg"
BEGIN
DEFPUSHBUTTON "OK",IDOK,209,179,50,14
PUSHBUTTON "Cancel",IDCANCEL,263,179,50,14
CTEXT "TODO: Place dialog controls here.",IDC_STATIC,10,96,300,8
END

[!else]
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//

IDC_[!output UPPER_CASE_SAFE_PROJECT_IDENTIFIER_NAME] MENU
BEGIN
POPUP "&File"
BEGIN
MENUITEM "E&xit", IDM_EXIT
END
POPUP "&Help"
BEGIN
MENUITEM "&About ...", IDM_ABOUT
END
END


/////////////////////////////////////////////////////////////////////////////
//
// Accelerator
//

IDC_[!output UPPER_CASE_SAFE_PROJECT_IDENTIFIER_NAME] ACCELERATORS
BEGIN
"?", IDM_ABOUT, ASCII, ALT
"/", IDM_ABOUT, ASCII, ALT
END

/////////////////////////////////////////////////////////////////////////////
//
// String Table
//

STRINGTABLE
BEGIN
IDC_[!output UPPER_CASE_SAFE_PROJECT_IDENTIFIER_NAME] "[!output UPPER_CASE_SAFE_PROJECT_IDENTIFIER_NAME]"
IDS_APP_TITLE "[!output PROJECT_NAME]"
END

/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//

IDD_ABOUTBOX DIALOGEX 0, 0, 170, 62
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "About [!output PROJECT_NAME]"
FONT [!output DLG_FONT_SIZE], "[!output DLG_FONT_NAME]"
BEGIN
ICON IDR_MAINFRAME,IDC_STATIC,14,14,21,20
LTEXT "[!output PROJECT_NAME], Version 1.0",IDC_STATIC,42,14,114,8,SS_NOPREFIX
LTEXT "Copyright (C) [!output YEAR]",IDC_STATIC,42,26,114,8
DEFPUSHBUTTON "OK",IDOK,113,41,50,14,WS_GROUP
END

/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//

#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_ABOUTBOX, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 163
TOPMARGIN, 7
BOTTOMMARGIN, 55
END
END
#endif // APSTUDIO_INVOKED
[!endif]
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
TEXTINCLUDE
BEGIN
"resource.h\0"
END
TEXTINCLUDE
BEGIN
"#ifndef APSTUDIO_INVOKED\r\n"
"#include ""targetver.h""\r\n"
"#endif\r\n"
"#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
"#include ""windows.h""\r\n"
"#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
"\0"
END
TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END

#endif // APSTUDIO_INVOKED


[!else]

#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
TEXTINCLUDE
BEGIN
"resource.h\0"
END
TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END

#endif // APSTUDIO_INVOKED

/////////////////////////////////////////////////////////////////////////////
//
// String Table
//

STRINGTABLE
BEGIN
IDS_APP_TITLE "[!output PROJECT_NAME]"
END

[!endif]
#endif
/////////////////////////////////////////////////////////////////////////////



#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
[!if SUPPORT_MFC]
#ifndef _AFXDLL
#include "[!output MFC_RC_INCLUDE_PREFIX]afxres.rc"
#endif
[!endif]

/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

终于修改完成了,赶紧创建一个新项目试试吧。。。

测试截图: