基于模板的对话框,包含了弹出窗口,和子窗口控件,而且有一个窗口过程来处理对话框消息。 包括键盘和鼠标的输入。
称为 “对话框管理器” 和标准的Windows窗口消息处理略有不同。稍后能看到具体区别
许多消息不仅被对话框窗口过程处理,还会传递给你自己的程序中的某些函数。 称为对话框过程
对话框过程一般处理初始化自创控件以及子窗口传来的消息。不处理WM_PAINT 也不直接处理键盘和鼠标的输入
子窗口控件由windows对话框管理器来负责。对话框管理器来负责处理在多个控件中转义输入焦点的相关逻辑
用户不能在该对话框和该程序的其他对话框之间切换。但是可以切换到其他的程序。有些系统模态不允许切换程序。必须结束系统模态才可以进行其他操作。
11.1.1 创建一个about对话框
About.cpp
#include
#include "resource.h"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //window procedure.
BOOL CALLBACK AboutDlgProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("About1");
HACCEL hAccel;
HWND hwnd;
MSG msg;
WNDCLASS wndClass; //The window Class
wndClass.style = CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = WndProc;// assign the window procedure to windows class.
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = hInstance;
wndClass.hIcon = LoadIcon(hInstance, szAppName);// LoadIcon(NULL, IDI_APPLICATION);
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndClass.lpszMenuName = szAppName;
wndClass.lpszClassName = szAppName;
//Register the Window Class to the Windows System.
if (!RegisterClass(&wndClass))
{
MessageBox(NULL, TEXT("This program require Windows NT!"),
szAppName, MB_ICONERROR);
return 0;
}
//This function will generate an WM_CREATE message.
hwnd = CreateWindow(szAppName, //Window class name
TEXT("About Box Demo Program"), //Window caption
WS_OVERLAPPEDWINDOW, //Window Style
CW_USEDEFAULT, //initial x position
CW_USEDEFAULT, //initial y position
CW_USEDEFAULT, //initial x size
CW_USEDEFAULT, //initial y size
NULL, //parent window handle
NULL, //window menu handle
hInstance, //program instance handle
NULL); //creation parameters
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd); //This function will generate a WM_PAINT message.
/* The message loop for this program.
if received the WM_QUIT message, the function will return 0.*/
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//define the Window Procedure WndProc
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HINSTANCE hInstance;
switch (message) //get the message
{
case WM_CREATE:
hInstance = ((LPCREATESTRUCT)lParam)->hInstance;
return 0;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDM_APP_ABOUT:
DialogBox(hInstance, TEXT("AboutBox"), hwnd, AboutDlgProc);
break;
}
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
BOOL CALLBACK AboutDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
case IDCANCEL:
EndDialog(hDlg, 0);
return TRUE;
}
break;
}
return FALSE;
}
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/
#undef APSTUDIO_READONLY_SYMBOLS
/
// English (United States) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#ifdef APSTUDIO_INVOKED
/
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/
//
// Dialog
//
ABOUTBOX DIALOGEX 32, 32, 180, 102
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP
FONT 8, "MS Sans Serif", 0, 0, 0x0
BEGIN
DEFPUSHBUTTON "OK",IDOK,66,81,50,14
ICON "ABOUT1",IDC_STATIC,7,7,20,20
CTEXT "About1",IDC_STATIC,40,12,100,8
CTEXT "About Box Demo Program",IDC_STATIC,7,40,166,8
CTEXT "(c) Charles Petzold, 1998",IDC_STATIC,7,52,166,8
END
/
//
// Menu
//
ABOUT1 MENU
BEGIN
POPUP "&Help"
BEGIN
MENUITEM "&About About1...", IDM_APP_ABOUT
END
END
/
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
ABOUT1 ICON "About1.ico"
/
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
"ABOUTBOX", DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 173
TOPMARGIN, 7
BOTTOMMARGIN, 95
END
END
#endif // APSTUDIO_INVOKED
/
//
// AFX_DIALOG_LAYOUT
//
ABOUTBOX AFX_DIALOG_LAYOUT
BEGIN
0
END
#endif // English (United States) resources
/
#ifndef APSTUDIO_INVOKED
/
//
// Generated from the TEXTINCLUDE 3 resource.
//
/
#endif // not APSTUDIO_INVOKED
resource.h
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by About1.rc
//
#define IDM_APP_ABOUT 40001
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 104
#define _APS_NEXT_COMMAND_VALUE 40004
#define _APS_NEXT_CONTROL_VALUE 1003
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
DEFPUSHBUTTON, ICON 和CTEXT只被用于对话框。他们是一些特殊类和窗口样式的缩写。 CTEXT指定窗口控件的类型是静态的,同时其样式是
WS_CHILD | SS_CENTER | WS_VISIBLE | WS_GROUP
文本设定等价于Caption参数
当子窗口像父窗口发送WM_COMMAND时,id字段是子窗口用来表示自己的标识符。 子窗口控件的父窗口是对话框本身。它会把这些消息发送给某个windows的窗口过程。
这里的ID和CreateWindow中 (HMENU)id 参数相同。 由于文本和图标并不需要向父窗口发送消息。所以ID被设定为ID_STATIC 按钮的ID为IDOK 在winuser.h中定义为1
接下来设定子窗口控件的位置和大小。 单位是 字符评均宽度的1/4 和 平均高度的1/8
11.1.3 对话框过程
发送给对话框的消息是用户程序中的对话框过程来处理的。和窗口过程很像,但是其实是不一样的。 对话框的窗口过程属于windows。 而对话框过程是独立的。
对话框的窗口过程会调用这个对话框的过程来处理许多消息。
对话框过程
BOOL CALLBACK AboutDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
case IDCANCEL:
EndDialog(hDlg, 0);
return TRUE;
}
break;
}
return FALSE;
}
对话框过程 和 对话框的窗口过程的区别
1)窗口过程返回值是 LRESULT 而对话框过程的返回值是BOOL
2)窗口过程不处理一条消息时,会调用DefWindowProc。 对话框过程处理一条消息会返回TRUE,不处理则返回FALSE
3) 对话框过程不需要处理WM_PAINT和WM_DESTROY消息。他也不会收到WM_CREATE消息。 然后他会在一条处理WM_INITDIALOG消息时进行初始化,这是对话框过程接收到的第一条消息。当其返回TRUE时,windows会把输入焦点放在第对话框第一个含有WS_TABSTOP样式的窗口子空间。本例中是按钮。
另外在WM_INITDIALOG也可以调用SetFocus来设置焦点,并返回FALSE
除此之外,对话框过程只处理WM_COMMAND,当鼠标单击按钮或者当焦点在按钮控件时按下空格键,按钮控件会像父窗口发送WM_COMMAND消息。wParam低位时控件ID
其他任何消息,对话框过程会返回FALSE来通知对话框的窗口过程该消息未处理。
模态对话框的消息并不通过程序的消息循环。
11.1.4 激活对话框
Dialog(hInstance, TEXT("AboutBox"), hwnd, AboutDlgProc);
实例句柄, 对话框名称在资源该脚本中定义, 父窗口句柄 和对话框过程的地址。
也可以使用MAKEINTRESOURCE宏来将其转换为字符。
当回车或空格被按下,windows会向对话框发送WM_COMMAND消息。 wParam的低位时默认按钮ID。 也可以按ESC来结束对话框。
直到对话框结束以后,用来显示对话框的DialogBox才将控制返回给WndProc。 DialogBox的返回值等于EndDialog函数的第二个参数。并将控制权返回给Windows.
对话框在显示使,WndProc依旧可以处理消息。比如SendMessage(GetParent(Dlg), ...);
11.1.5 主题变换
对话框资源脚本
对话框常用样式
STYLE WS_POPUP | DS_MODALFRAME
带标题栏 WS_CAPTION
CAPTION "Dialog Box Caption" 标题栏文本
或者当对话框过程处理WM_INITDIALOG消息时,你可以使用
SetWindowText(hDlg, TEXT("Dialog Box Caption"));
使用WS_CAPTION样式 还运行使用WS_SYSMENU 增加系统菜单框。这一样式允许用户通过系统菜单来选择Move或Close
WS_THICKFRAME (Resizing) 允许用户改变对话框的大小。甚至还可以给对话框添加菜单
MENU 菜单名
FONT 语句用来设置对话框文本为系统字体以外的字体。 早起VS创建对话框默认的字体是 8pt的 MS Scans Serif。 现在VS2015使用的是 8pt的 MS Shell Dlg 字体
可以指定某个窗口过程来处理对话框消息。
CLASS “类名”
调用DialogBox函数, windows会从对话框资源模板中获取信息来CreateWindow ,windows从DialogBox函数的参数获取hInstance 和 父窗口hwnd
windows所需的唯一其他信息是一个窗口类,假设对话框模板没有指定。 window设为对话框注册一个特殊的窗口类。窗口类用于对话框过程的访问地址。
因此弹出式窗口可以向程序传递其收到的消息。 也可以自己使用CreateWindow并注册窗口类来创建自己的对话框,DialogBox函数只是一种简便的方法。
也可以动态创建对话框,不需要写资源脚本。DialogBoxIndirect函数 使用数据结构来定义对话框模板。
常用控件类型的相应窗口类和窗口样式
除了表中的样式,每个控件默认还有以下样式
WS_CHILD | WS_VISIBLE
EDITTEXT, SCROLLBAR, LISTBOX 和COMBOBOX以下格式
控件类型 id, xPos, yPos, xWidth, yHeight, iStyle
除此之外所有控件的定义都有以下格式
控件类型 "文本" , id, xpos, ypos, xwidth, yHeight, iStyle
对话框模板中的单位是平均字符宽度的1/4 和 高度的 1/8 。
例如复选框
CHECKBOX "TEXT", id, xPos, yPos, xWidth, yHeight, BS_LEFTTEXT checkbox上的说明文本左对齐
EDITTEXT id, xPos, yPos, xWidth, yHeight, NOT WS_BORDER 不带边框的EDITTEXT
资源编辑器还承认这样的一般化语句
CONTROL "文本" , id, "类", IStyle, xPos, yPos, xWidth, yHeight
创建任何类型的子窗口控件
比如
PUSHBUTTON "OK", IDOK, 10, 20, 32, 14
可以使用下面语句
CONTROL "OK" , IDOK, "button", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP,
10, 20, 32, 14
可使用VS中自定义控件选项来生成以上语句
在模板资源中,则无需WS_CHILD | WS_VISIBLE 样式
上面的CONTROL语句转换成如下调用
hCtrl1 = CreateWindow( TEXT("button"), TEXT("OK"),
WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON,
10 * cxChar / 4, 20 * cyChar / 8,
32 * cxChar / 4, 14 * cyChar / 8,
hDlg, IDOK, hInstance, NULL);
11.1.6 更复杂的对话框
about2.cpp
#include
#include "resource.h"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //window procedure.
BOOL CALLBACK AboutDlgProc(HWND, UINT, WPARAM, LPARAM);
int iCurrentColor = IDC_BLACK,
iCurrentFigure = IDC_RECT;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("About2");
HWND hwnd;
MSG msg;
WNDCLASS wndClass; //The window Class
wndClass.style = CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = WndProc;// assign the window procedure to windows class.
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = hInstance;
wndClass.hIcon = LoadIcon(hInstance, szAppName);// LoadIcon(NULL, IDI_APPLICATION);
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndClass.lpszMenuName = szAppName;
wndClass.lpszClassName = szAppName;
//Register the Window Class to the Windows System.
if (!RegisterClass(&wndClass))
{
MessageBox(NULL, TEXT("This program require Windows NT!"),
szAppName, MB_ICONERROR);
return 0;
}
//This function will generate an WM_CREATE message.
hwnd = CreateWindow(szAppName, //Window class name
TEXT("About Box Demo Program"), //Window caption
WS_OVERLAPPEDWINDOW, //Window Style
CW_USEDEFAULT, //initial x position
CW_USEDEFAULT, //initial y position
CW_USEDEFAULT, //initial x size
CW_USEDEFAULT, //initial y size
NULL, //parent window handle
NULL, //window menu handle
hInstance, //program instance handle
NULL); //creation parameters
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd); //This function will generate a WM_PAINT message.
/* The message loop for this program.
if received the WM_QUIT message, the function will return 0.*/
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
void PaintWindow(HWND hwnd, int iColor, int iFigure)
{
static COLORREF crColor[8] = { RGB(0, 0, 0), RGB(0, 0, 255),
RGB(0, 255, 0), RGB(0, 255, 255),
RGB(255, 0, 0), RGB(255, 0, 255),
RGB(255, 255, 0), RGB(255, 255, 255) };
HBRUSH hBrush;
HDC hdc;
RECT rect;
hdc = GetDC(hwnd);
GetClientRect(hwnd, &rect);
hBrush = CreateSolidBrush(crColor[iColor - IDC_BLACK]);
hBrush = (HBRUSH)SelectObject(hdc, hBrush);
if (iFigure == IDC_RECT)
Rectangle(hdc, rect.left, rect.top, rect.right, rect.bottom);
else
Ellipse(hdc, rect.left, rect.top, rect.right, rect.bottom);
DeleteObject(SelectObject(hdc, hBrush));
ReleaseDC(hwnd, hdc);
}
void PaintTheBlock(HWND hCtrl, int iColor, int iFigure)
{
InvalidateRect(hCtrl, NULL, TRUE);
UpdateWindow(hCtrl);
PaintWindow(hCtrl, iColor, iFigure);
}
//define the Window Procedure WndProc
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HINSTANCE hInstance;
PAINTSTRUCT ps;
switch (message) //get the message
{
case WM_CREATE:
hInstance = ((LPCREATESTRUCT)lParam)->hInstance;
return 0;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDM_APP_ABOUT:
if (DialogBox(hInstance, TEXT("AboutBox"), hwnd, AboutDlgProc))
InvalidateRect(hwnd, NULL, TRUE);
break;
}
break;
case WM_PAINT:
BeginPaint(hwnd, &ps);
EndPaint(hwnd, &ps);
PaintWindow(hwnd, iCurrentColor, iCurrentFigure);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
BOOL CALLBACK AboutDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
static HWND hCtrlBlock;
static int iColor, iFigure;
switch (message)
{
case WM_INITDIALOG:
iColor = iCurrentColor;
iFigure = iCurrentFigure;
CheckRadioButton(hDlg, IDC_BLACK, IDC_WHITE, iColor);
CheckRadioButton(hDlg, IDC_RECT, IDC_ELLIPSE, iFigure);
hCtrlBlock = GetDlgItem(hDlg, IDC_PAINT);
SetFocus(GetDlgItem(hDlg, iColor));
return FALSE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
iCurrentColor = iColor;
iCurrentFigure = iFigure;
EndDialog(hDlg, TRUE);
return TRUE;
case IDCANCEL:
EndDialog(hDlg, FALSE);
return TRUE;
case IDC_BLACK:
case IDC_RED:
case IDC_GREEN:
case IDC_YELLOW:
case IDC_BLUE:
case IDC_MAGENTA:
case IDC_CYAN:
case IDC_WHITE:
iColor = LOWORD(wParam);
CheckRadioButton(hDlg, IDC_BLACK, IDC_WHITE, LOWORD(wParam)); //The LOWORD(wParam) is the current ID of the command.
PaintTheBlock(hCtrlBlock, iColor, iFigure);
return TRUE;
case IDC_RECT:
case IDC_ELLIPSE:
iFigure = LOWORD(wParam);
CheckRadioButton(hDlg, IDC_RECT, IDC_ELLIPSE, LOWORD(wParam));
PaintTheBlock(hCtrlBlock, iColor, iFigure);
return TRUE;
}
break;
case WM_PAINT:
PaintTheBlock(hCtrlBlock, iColor, iFigure);
break;
}
return FALSE;
}
//Microsoft Developer Studio generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/
#undef APSTUDIO_READONLY_SYMBOLS
/
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/
//
// Dialog
//
ABOUTBOX DIALOG DISCARDABLE 32, 32, 200, 234
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION
FONT 8, "MS Sans Serif"
BEGIN
ICON "ABOUT2",IDC_STATIC,7,7,20,20
CTEXT "About2",IDC_STATIC,57,12,86,8
CTEXT "About Box Demo Program",IDC_STATIC,7,40,186,8
LTEXT "",IDC_PAINT,114,67,72,72
GROUPBOX "&Color",IDC_STATIC,7,60,84,143
RADIOBUTTON "&Black",IDC_BLACK,16,76,64,8,WS_GROUP | WS_TABSTOP
RADIOBUTTON "B&lue",IDC_BLUE,16,92,64,8
RADIOBUTTON "&Green",IDC_GREEN,16,108,64,8
RADIOBUTTON "Cya&n",IDC_CYAN,16,124,64,8
RADIOBUTTON "&Red",IDC_RED,16,140,64,8
RADIOBUTTON "&Magenta",IDC_MAGENTA,16,156,64,8
RADIOBUTTON "&Yellow",IDC_YELLOW,16,172,64,8
RADIOBUTTON "&White",IDC_WHITE,16,188,64,8
GROUPBOX "&Figure",IDC_STATIC,109,156,84,46,WS_GROUP
RADIOBUTTON "Rec&tangle",IDC_RECT,116,172,65,8,WS_GROUP | WS_TABSTOP
RADIOBUTTON "&Ellipse",IDC_ELLIPSE,116,188,64,8
DEFPUSHBUTTON "OK",IDOK,35,212,50,14,WS_GROUP
PUSHBUTTON "Cancel",IDCANCEL,113,212,50,14,WS_GROUP
END
/
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
ABOUT2 ICON DISCARDABLE "About2.ico"
/
//
// Menu
//
ABOUT2 MENU DISCARDABLE
BEGIN
POPUP "&Help"
BEGIN
MENUITEM "&About", IDM_APP_ABOUT
END
END
/
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO DISCARDABLE
BEGIN
"ABOUTBOX", DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 193
TOPMARGIN, 7
BOTTOMMARGIN, 227
END
END
#endif // APSTUDIO_INVOKED
#endif // English (U.S.) resources
/
#ifndef APSTUDIO_INVOKED
/
//
// Generated from the TEXTINCLUDE 3 resource.
//
/
#endif // not APSTUDIO_INVOKED
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by About2.rc
//
#define IDC_BLACK 1000
#define IDC_BLUE 1001
#define IDC_GREEN 1002
#define IDC_CYAN 1003
#define IDC_RED 1004
#define IDC_MAGENTA 1005
#define IDC_YELLOW 1006
#define IDC_WHITE 1007
#define IDC_RECT 1008
#define IDC_ELLIPSE 1009
#define IDC_PAINT 1010
#define IDM_APP_ABOUT 40001
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 105
#define _APS_NEXT_COMMAND_VALUE 40002
#define _APS_NEXT_CONTROL_VALUE 1011
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
11.1.7 对话框控件的应用
当一个单选按钮被鼠标按下或有焦点时按下空格, 子窗口像父窗口发送WM_COMMAND消息 LOWPRD(wParam) 是控件ID,高位是通知码
lParam是控件的窗口句柄
对于单选按钮通知码是 BN_CLICKED ,他等于0. 然后windows的对话框窗口过程把该消息发送给About2.c中的对话框过程。
当对话框过程收到单选按钮的WM_COMMAND消息以后表明他被选中,斌给取消选中同组所有其他按钮
CP9中 取消或选中单选需要发送一条BM_SETCHECK消息
SendMessage(hwndCtrl, BM_SETCHECK, 1, 0); 选中
SendMessage(hwndCtrl, BM_SETCHECK, 0, 0); 取消选中
hwndCtrl = GetDlgItem(hDlg, id);
id = GetWindowLong(hwndCtrl, GWL_ID);
可以使用下面代码来选择和取消单选框。
case IDC_BLACK:
case IDC_RED:
case IDC_GREEN:
case IDC_YELLOW:
case IDC_BLUE:
case IDC_MAGENTA:
case IDC_CYAN:
case IDC_WHITE:
iColor = LOWORD(wParam);
for (i = IDC_BLACK; i <= IDC_WHITE; i++)
{
SendMessage(GetDlgItem(hDlg, i),
BM_SETCHECK, i == LOWORD(wParam), 0);
}
SendDlgItemMessage(hDlg, id, iMsg, wParam, lParam);
等价于 SendMessage(GetDlgItem(hDlg, id), BM_SETCHECK, wParam, lParam);
for (i = IDC_BLACK; i <= IDC_WHITE; i++)
SendDlgMessage(hDlg, i, BM_SETCHECK, i == LOWORD (wParam), lParam);
或者使用
CheckRadioButton(hDlg, idFirst, idLast, idCheck);
对复选框也可以这样使用
CheckDlgButton(hDlg, idCheckbox, iCheck); 1选择 0 取消
iCheck = IsDlgButtonChecked(hDlg, idCheckbox);
或者 SendMessage(hwndCtrl, BM_GETCHECK, 0, 0);
在WM_COMMAND消息中切换状态
CheckDlgButton(hDlg, idCheckbox, !IsDlgButtonChecked(hDlg, idCheckbox));
如果是一个BS_AUTOCHECKBOX控件,则程序不需要处理WM_COMMAND消息 ,在对话框终止前使用IsDlgButtonChecked来获得按钮的选取状态。
11.1.8 OK和Cancel按钮
当用户按回车时,对话框窗口过程会产生一个WM_COMMAND消息,该消息的wParam参数的LOWORD会被设为默认的按钮的ID值,除非另一个按键有输入焦点。如果对话框没有按键是默认按钮。windows会像对话框过程发送一条LOWORD(wParam) 为IDOK的WM_COMMAND消息。 如果用户按下ESC或者Ctrl-Break, Windows会发送一条wParam参数为 LOWORD等于IDCANCEL的WM_COMMAND消息。
EndDialog 第二个参数成为DialogBox函数的返回值
11.1.9 避免全局变量
定义一个数据结构和About对话框关联
typedef struct
{
int iColor;
int iFigure;
}
ABOUTBOX_DATA;
在WndProc中 定义 static ABOUTBOX_DATA ad = { IDC_BLACK, IDC_RECT};
然后将iCurrentColor和iCurrentFigure替换为 ad.iColor 和 ad.iFigure
当调用对话框使用DialogBoxParam
if(DialogBoxParam(hInstance, TEXT("AboutBox"),
hwnd, AboutDlgProc, &ad))
最后一个参数将作为WM_INITDIALOG消息的lParam参数传递给对话框过程。
对话框过程有两个基于ABOUTBOX_DATA结构的静态变量
static ABOUTBOX_DATA ad, * pad;
pad = (ABOUTBOX_DATA *) lParam;
ad = * pad;
在 Case IDOK
* pad = ad;
EndDialog(hDlg, TRUE);
return TRUE;
修改成非全局变量的版本
#include
#include "resource.h"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //window procedure.
BOOL CALLBACK AboutDlgProc(HWND, UINT, WPARAM, LPARAM);
typedef struct
{
int iColor;
int iFigure;
}
ABOUTBOX_DATA;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("About2");
HWND hwnd;
MSG msg;
WNDCLASS wndClass; //The window Class
wndClass.style = CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = WndProc;// assign the window procedure to windows class.
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = hInstance;
wndClass.hIcon = LoadIcon(hInstance, szAppName);// LoadIcon(NULL, IDI_APPLICATION);
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndClass.lpszMenuName = szAppName;
wndClass.lpszClassName = szAppName;
//Register the Window Class to the Windows System.
if (!RegisterClass(&wndClass))
{
MessageBox(NULL, TEXT("This program require Windows NT!"),
szAppName, MB_ICONERROR);
return 0;
}
//This function will generate an WM_CREATE message.
hwnd = CreateWindow(szAppName, //Window class name
TEXT("About Box Demo Program"), //Window caption
WS_OVERLAPPEDWINDOW, //Window Style
CW_USEDEFAULT, //initial x position
CW_USEDEFAULT, //initial y position
CW_USEDEFAULT, //initial x size
CW_USEDEFAULT, //initial y size
NULL, //parent window handle
NULL, //window menu handle
hInstance, //program instance handle
NULL); //creation parameters
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd); //This function will generate a WM_PAINT message.
/* The message loop for this program.
if received the WM_QUIT message, the function will return 0.*/
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
void PaintWindow(HWND hwnd, int iColor, int iFigure)
{
static COLORREF crColor[8] = { RGB(0, 0, 0), RGB(0, 0, 255),
RGB(0, 255, 0), RGB(0, 255, 255),
RGB(255, 0, 0), RGB(255, 0, 255),
RGB(255, 255, 0), RGB(255, 255, 255) };
HBRUSH hBrush;
HDC hdc;
RECT rect;
hdc = GetDC(hwnd);
GetClientRect(hwnd, &rect);
hBrush = CreateSolidBrush(crColor[iColor - IDC_BLACK]);
hBrush = (HBRUSH)SelectObject(hdc, hBrush);
if (iFigure == IDC_RECT)
Rectangle(hdc, rect.left, rect.top, rect.right, rect.bottom);
else
Ellipse(hdc, rect.left, rect.top, rect.right, rect.bottom);
DeleteObject(SelectObject(hdc, hBrush));
ReleaseDC(hwnd, hdc);
}
void PaintTheBlock(HWND hCtrl, int iColor, int iFigure)
{
InvalidateRect(hCtrl, NULL, TRUE);
UpdateWindow(hCtrl);
PaintWindow(hCtrl, iColor, iFigure);
}
//define the Window Procedure WndProc
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HINSTANCE hInstance;
static ABOUTBOX_DATA ad = { IDC_BLACK, IDC_RECT };
PAINTSTRUCT ps;
switch (message) //get the message
{
case WM_CREATE:
hInstance = ((LPCREATESTRUCT)lParam)->hInstance;
return 0;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDM_APP_ABOUT:
if (DialogBoxParam(hInstance, TEXT("AboutBox"), hwnd, AboutDlgProc, (LPARAM)(&ad)))
InvalidateRect(hwnd, NULL, TRUE);
break;
}
break;
case WM_PAINT:
BeginPaint(hwnd, &ps);
EndPaint(hwnd, &ps);
PaintWindow(hwnd, ad.iColor, ad.iFigure);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
BOOL CALLBACK AboutDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
static HWND hCtrlBlock;
static ABOUTBOX_DATA ad, *pad;
switch (message)
{
case WM_INITDIALOG:
pad = (ABOUTBOX_DATA *)lParam;
ad = *pad;
CheckRadioButton(hDlg, IDC_BLACK, IDC_WHITE, ad.iColor);
CheckRadioButton(hDlg, IDC_RECT, IDC_ELLIPSE, ad.iFigure);
hCtrlBlock = GetDlgItem(hDlg, IDC_PAINT);
SetFocus(GetDlgItem(hDlg, ad.iColor));
return FALSE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
*pad = ad;
EndDialog(hDlg, TRUE);
return TRUE;
case IDCANCEL:
EndDialog(hDlg, FALSE);
return TRUE;
case IDC_BLACK:
case IDC_RED:
case IDC_GREEN:
case IDC_YELLOW:
case IDC_BLUE:
case IDC_MAGENTA:
case IDC_CYAN:
case IDC_WHITE:
ad.iColor = LOWORD(wParam);
CheckRadioButton(hDlg, IDC_BLACK, IDC_WHITE, LOWORD(wParam)); //The LOWORD(wParam) is the current ID of the command.
PaintTheBlock(hCtrlBlock, ad.iColor, ad.iFigure);
return TRUE;
case IDC_RECT:
case IDC_ELLIPSE:
ad.iFigure = LOWORD(wParam);
CheckRadioButton(hDlg, IDC_RECT, IDC_ELLIPSE, LOWORD(wParam));
PaintTheBlock(hCtrlBlock, ad.iColor, ad.iFigure);
return TRUE;
}
break;
case WM_PAINT:
PaintTheBlock(hCtrlBlock, ad.iColor, ad.iFigure);
break;
}
return FALSE;
}
需要TAB访问的控件 加入 WS_TABSTOP
不含TABSTOP样式的控件不应该获取输入焦点。 除非在WM_INITDIALOG 中强制设置焦点并返回FALSE, 否则windows会把输入焦点设置为对话框中第一个含有WS_TABSTOP格式的控件
当焦点在单选按钮上时,添加WS_GROUP样式使得可以使用方向键来切换选择同一个GROUP中的其他单选。再下一个WS_GROUP之前的控件为一组
&使得其后面的字母带下划线,同时增加了一个键盘接口。用户可以通过按下带有下划线的字母来将输入焦点移动到任何单选按钮。
windows提供下列函数来查找下一个或前一个tab停靠位或者选项组
hwndCtrl = GetNextDlgTabItem(hDlg, hwndCtrl, bPrevious);
hwndCtrl= GetNextDlgGroupItem(hDlg, hwndCtrl, bPrevious);
bPrevious是TRUE, 函数返回掐你个TAB停靠位或选项组; 如果是FALSE 返回下一个
11.1.11 在对话框上绘图
在对话框过程的WM_PAINT消息 或者切换图形时候调用
PaintTheBlock(hCtrlBlock, iColor, iFigure);
在WM_INITDIALOG消息时
hCtrlBlock = GetDlgItem(hDlg, IDC_PAINT);
MapDialogRect 函数把对话框中的以字符为单位的坐标转换为客户区中以像素为单位的坐标。
实际上是在子窗口控件上绘图。
11.1.12 关于对话框的其他函数
MoveWindow
EnableWindow(hwndCtrl, bEnable);
不要禁用含有输入焦点的控件
11.1.13 定义程序自己的控件
About3.cpp
#include
#include "resource.h"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //window procedure.
BOOL CALLBACK AboutDlgProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK EllipPushWndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("About3");
HWND hwnd;
MSG msg;
WNDCLASS wndClass; //The window Class
wndClass.style = CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = WndProc;// assign the window procedure to windows class.
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = hInstance;
wndClass.hIcon = LoadIcon(hInstance, szAppName);// LoadIcon(NULL, IDI_APPLICATION);
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndClass.lpszMenuName = szAppName;
wndClass.lpszClassName = szAppName;
//Register the Window Class to the Windows System.
if (!RegisterClass(&wndClass))
{
MessageBox(NULL, TEXT("This program require Windows NT!"),
szAppName, MB_ICONERROR);
return 0;
}
wndClass.style = CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = EllipPushWndProc;// assign the window procedure to windows class.
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = hInstance;
wndClass.hIcon = NULL;// LoadIcon(NULL, IDI_APPLICATION);
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
wndClass.lpszMenuName = NULL;
wndClass.lpszClassName = TEXT("EllipPush");
RegisterClass(&wndClass);
//This function will generate an WM_CREATE message.
hwnd = CreateWindow(szAppName, //Window class name
TEXT("About Box Demo Program"), //Window caption
WS_OVERLAPPEDWINDOW, //Window Style
CW_USEDEFAULT, //initial x position
CW_USEDEFAULT, //initial y position
CW_USEDEFAULT, //initial x size
CW_USEDEFAULT, //initial y size
NULL, //parent window handle
NULL, //window menu handle
hInstance, //program instance handle
NULL); //creation parameters
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd); //This function will generate a WM_PAINT message.
/* The message loop for this program.
if received the WM_QUIT message, the function will return 0.*/
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//define the Window Procedure WndProc
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HINSTANCE hInstance;
switch (message) //get the message
{
case WM_CREATE:
hInstance = ((LPCREATESTRUCT)lParam)->hInstance;
return 0;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDM_APP_ABOUT:
DialogBox(hInstance, TEXT("AboutBox"), hwnd, AboutDlgProc);
return 0;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
BOOL CALLBACK AboutDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
EndDialog(hDlg, TRUE);
return TRUE;
}
break;
}
return FALSE;
}
LRESULT CALLBACK EllipPushWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
TCHAR szText[40];
HBRUSH hBrush;
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
switch (message)
{
case WM_PAINT:
GetClientRect(hwnd, &rect);
GetWindowText(hwnd, szText, sizeof(szText));
hdc = BeginPaint(hwnd, &ps);
hBrush = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
hBrush = (HBRUSH)SelectObject(hdc, hBrush);
SetBkColor(hdc, GetSysColor(COLOR_WINDOW));
SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
Ellipse(hdc, rect.left, rect.top, rect.right, rect.bottom);
DrawText(hdc, szText, -1, &rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER);
DeleteObject(SelectObject(hdc, hBrush));
EndPaint(hwnd, &ps);
return 0;
case WM_KEYUP:
if (wParam != VK_SPACE)
break;
case WM_LBUTTONUP:
SendMessage(GetParent(hwnd), WM_COMMAND, GetWindowLong(hwnd, GWL_ID),
(LPARAM)hwnd);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
//Microsoft Developer Studio generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/
#undef APSTUDIO_READONLY_SYMBOLS
/
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/
//
// Dialog
//
ABOUTBOX DIALOG DISCARDABLE 32, 32, 180, 100
STYLE DS_MODALFRAME | WS_POPUP
FONT 8, "MS Sans Serif"
BEGIN
CONTROL "OK",IDOK,"EllipPush",WS_GROUP | WS_TABSTOP,73,79,32,14
ICON "ABOUT3",IDC_STATIC,7,7,20,20
CTEXT "About3",IDC_STATIC,40,12,100,8
CTEXT "About Box Demo Program",IDC_STATIC,7,40,166,8
CTEXT "(c) Charles Petzold, 1998",IDC_STATIC,7,52,166,8
END
/
//
// Menu
//
ABOUT3 MENU DISCARDABLE
BEGIN
POPUP "&Help"
BEGIN
MENUITEM "&About About3...", IDM_APP_ABOUT
END
END
/
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO DISCARDABLE
BEGIN
"ABOUTBOX", DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 173
TOPMARGIN, 7
BOTTOMMARGIN, 93
END
END
#endif // APSTUDIO_INVOKED
/
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
ABOUT3 ICON DISCARDABLE "icon1.ico"
#endif // English (U.S.) resources
/
#ifndef APSTUDIO_INVOKED
/
//
// Generated from the TEXTINCLUDE 3 resource.
//
/
#endif // not APSTUDIO_INVOKED
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by About3.rc
//
#define IDM_APP_ABOUT 40001
#define IDC_STATIC -1
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 105
#define _APS_NEXT_COMMAND_VALUE 40002
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
hDlgModeless = CreateDialog(hInstance, szTemplate, hwndParent, DialogProc); //创建非模态对话框
11.2.1 模态与非模态对话框的区别
1.非模态对话框通常包含 标题栏和系统菜单栏
STYLE WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE
而模态通常不需要。
2. 通常非模态对话框包含WS_VISIBLE样式 ,否则需要在CreateDialog以后调用ShowWindow显示
hDlgModeless = CraeteDialog(...);
ShowWindow (hDlgModeless, SW_SHOW);
3. 非模态对话框的消息要进入你程序的消息队列。而消息队列必须经过改动才能把这些消息传递给对话框窗口过程。
hDlgModeless = CreateDialog(...);
修改消息循环
while (GetMessage(&msg, NULL, 0, 0))
{
if (hDlgModeless == 0 || !IsDialogMessage(hDlgModeless, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
如果消息是针对对话框的,IsDialogMessage就会把消息发送给对话框的窗口过程并返回TRUE,否则返回FALSE
如果应用程序使用了键盘加速键,修改以后的消息循环如下
while (GetMessage(&msg, NULL, 0, 0))
{
if (hDlgModeless == 0 || !IsDialogMessage(hDlgModeless, &msg))
{
if (!TranslateAccelerator(HWND, hAccel, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
在创建非模态对话框之前hDlgModeless保持为0 ,在销毁以后也至于0
4. 使用Destroywindow 来结束非模态对话框。当调用DestroyWindow时,还要把hDlgModeless全局变量设置为NULL.
在非模态对话框的对话框过程中处理WM_CLOSE消息
case WM_CLOSE:
DestroyWindow(hDlg);
hDlgModeless = NULL;
break;
避免使用全局变量可以使用CreateDialogParam来创建费莫泰对话框,并给他传递一个指向结构的指针。
11.2.2 新的COLORS程序
color2.cpp
#include
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //window procedure.
BOOL CALLBACK ColorScrDlg(HWND, UINT, WPARAM, LPARAM);
HWND hDlgModeless;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("Colors2");
HWND hwnd;
MSG msg;
WNDCLASS wndClass; //The window Class
wndClass.style = CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = WndProc;// assign the window procedure to windows class.
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = hInstance;
wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground = CreateSolidBrush(0L);//(HBRUSH)GetStockObject(WHITE_BRUSH);
wndClass.lpszMenuName = NULL;
wndClass.lpszClassName = szAppName;
//Register the Window Class to the Windows System.
if (!RegisterClass(&wndClass))
{
MessageBox(NULL, TEXT("This program require Windows NT!"),
szAppName, MB_ICONERROR);
return 0;
}
//This function will generate an WM_CREATE message.
hwnd = CreateWindow(szAppName, //Window class name
TEXT("Color Scroll"), //Window caption
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, //Window Style
CW_USEDEFAULT, //initial x position
CW_USEDEFAULT, //initial y position
CW_USEDEFAULT, //initial x size
CW_USEDEFAULT, //initial y size
NULL, //parent window handle
NULL, //window menu handle
hInstance, //program instance handle
NULL); //creation parameters
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd); //This function will generate a WM_PAINT message.
hDlgModeless = CreateDialog(hInstance, TEXT("ColorScrDlg"),
hwnd, ColorScrDlg);
/* The message loop for this program.
if received the WM_QUIT message, the function will return 0.*/
while (GetMessage(&msg, NULL, 0, 0))
{
if (hDlgModeless == 0 || !IsDialogMessage(hDlgModeless, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
//define the Window Procedure WndProc
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) //get the message
{
case WM_DESTROY:
DeleteObject((HGDIOBJ)SetClassLong(hwnd, GCL_HBRBACKGROUND,
(LONG)GetStockObject(WHITE_BRUSH)));
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
BOOL CALLBACK ColorScrDlg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
static int iColor[3];
HWND hwndParent, hCtrl;
int iCtrlID, iIndex;
switch (message)
{
case WM_INITDIALOG:
for (iCtrlID = 10; iCtrlID < 13; iCtrlID++)
{
hCtrl = GetDlgItem(hDlg, iCtrlID);
SetScrollRange(hCtrl, SB_CTL, 0, 255, FALSE);
SetScrollPos(hCtrl, SB_CTL, 0, FALSE);
}
return TRUE;
case WM_VSCROLL:
hCtrl = (HWND)lParam;
iCtrlID = GetWindowLong(hCtrl, GWL_ID);
iIndex = iCtrlID - 10;
hwndParent = GetParent(hDlg);
switch (LOWORD(wParam))
{
case SB_PAGEDOWN:
iColor[iIndex] += 15; //fall through
case SB_LINEDOWN:
iColor[iIndex] = min(255, iColor[iIndex] + 1);
break;
case SB_PAGEUP:
iColor[iIndex] -= 15; //fall through
case SB_LINEUP:
iColor[iIndex] = max(0, iColor[iIndex] - 1);
break;
case SB_TOP:
iColor[iIndex] = 0;
break;
case SB_BOTTOM:
iColor[iIndex] = 255;
break;
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
iColor[iIndex] = HIWORD(wParam);
break;
default:
return FALSE;
}
SetScrollPos(hCtrl, SB_CTL, iColor[iIndex], TRUE);
SetDlgItemInt(hDlg, iCtrlID + 3, iColor[iIndex], FALSE);
DeleteObject((HGDIOBJ)SetClassLong(hwndParent, GCL_HBRBACKGROUND,
(LONG)CreateSolidBrush(
RGB(iColor[0], iColor[1], iColor[2]))));
InvalidateRect(hwndParent, NULL, TRUE);
return TRUE;
case WM_CLOSE:
DestroyWindow(hDlg);
hDlgModeless = NULL;
break;
}
return FALSE;
}
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/
#undef APSTUDIO_READONLY_SYMBOLS
/
// English (United States) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#ifdef APSTUDIO_INVOKED
/
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/
//
// Dialog
//
COLORSCRDLG DIALOGEX 16, 16, 120, 141
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Color Scroll Scrollbars"
FONT 8, "MS Sans Serif", 0, 0, 0x0
BEGIN
CTEXT "&Red",IDC_STATIC,8,8,24,8,NOT WS_GROUP
SCROLLBAR 10,8,20,24,100,SBS_VERT | WS_TABSTOP
CTEXT "0",13,8,124,24,8,NOT WS_GROUP
CTEXT "&Green",IDC_STATIC,48,8,24,8,NOT WS_GROUP
SCROLLBAR 11,48,20,24,100,SBS_VERT | WS_TABSTOP
CTEXT "0",14,48,124,24,8,NOT WS_GROUP
CTEXT "&Blue",IDC_STATIC,89,8,24,8,NOT WS_GROUP
SCROLLBAR 12,89,20,24,100,SBS_VERT | WS_TABSTOP
CTEXT "0",15,89,124,24,8,NOT WS_GROUP
END
/
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
"COLORSCRDLG", DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 113
TOPMARGIN, 7
BOTTOMMARGIN, 134
END
END
#endif // APSTUDIO_INVOKED
/
//
// AFX_DIALOG_LAYOUT
//
COLORSCRDLG AFX_DIALOG_LAYOUT
BEGIN
0
END
#endif // English (United States) resources
/
#ifndef APSTUDIO_INVOKED
/
//
// Generated from the TEXTINCLUDE 3 resource.
//
/
#endif // not APSTUDIO_INVOKED
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by Colors2.rc
//
#define IDC_STATIC -1
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 102
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1003
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
11.2.3 HEXCALC:窗口还是对话框?
hexcalc.cpp
#include
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //window procedure.
HWND hDlgModeless;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("HexCalc");
HWND hwnd;
MSG msg;
WNDCLASS wndClass; //The window Class
wndClass.style = CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = WndProc;// assign the window procedure to windows class.
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = DLGWINDOWEXTRA; // Note!
wndClass.hInstance = hInstance;
wndClass.hIcon = LoadIcon(NULL, szAppName);
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);//(HBRUSH)GetStockObject(WHITE_BRUSH);
wndClass.lpszMenuName = NULL;
wndClass.lpszClassName = szAppName;
//Register the Window Class to the Windows System.
if (!RegisterClass(&wndClass))
{
MessageBox(NULL, TEXT("This program require Windows NT!"),
szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateDialog(hInstance, szAppName, 0, NULL);
ShowWindow(hwnd, iCmdShow);
/* The message loop for this program.
if received the WM_QUIT message, the function will return 0.*/
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
void ShowNumber(HWND hwnd, UINT iNumber)
{
TCHAR szBuffer[20];
wsprintf(szBuffer, TEXT("%X"), iNumber);
SetDlgItemText(hwnd, VK_ESCAPE, szBuffer);
}
DWORD CalcIt(UINT iFirstNum, int iOperation, UINT iNum)
{
switch (iOperation)
{
case '=': return iNum;
case '+': return iFirstNum + iNum;
case '-': return iFirstNum - iNum;
case '*': return iFirstNum * iNum;
case '&': return iFirstNum & iNum;
case '|': return iFirstNum | iNum;
case '^': return iFirstNum ^ iNum;
case '<': return iFirstNum << iNum;
case '>': return iFirstNum >> iNum;
case '/': return iNum ? iFirstNum / iNum : MAXDWORD;
case '%': return iNum ? iFirstNum % iNum : MAXDWORD;
default: return 0;
}
}
//define the Window Procedure WndProc
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static BOOL bNewNumber = TRUE;
static int iOperation = '=';
static UINT iNumber, iFirstNum;
HWND hButton;
switch (message) //get the message
{
case WM_KEYDOWN:
if (wParam != VK_LEFT) //left arrow --> backspace
break;
wParam = VK_BACK;
// fall through
case WM_CHAR:
if ((wParam = (WPARAM)CharUpper((TCHAR *)wParam)) == VK_RETURN)
wParam = '=';
if (hButton = GetDlgItem(hwnd, wParam))
{
SendMessage(hButton, BM_SETSTATE, 1, 0);
Sleep(100);
SendMessage(hButton, BM_SETSTATE, 0, 0);
}
else
{
MessageBeep(0);
break;
}
// fall through
case WM_COMMAND:
SetFocus(hwnd);
if (LOWORD(wParam) == VK_BACK) // backspace
ShowNumber(hwnd, iNumber /= 16);
else if (LOWORD(wParam) == VK_ESCAPE) // escape
ShowNumber(hwnd, iNumber = 0);
else if (isxdigit(LOWORD(wParam))) // hex digit
{
if (bNewNumber)
{
iFirstNum = iNumber;
iNumber = 0;
}
bNewNumber = FALSE;
if (iNumber <= MAXDWORD >> 4)
ShowNumber(hwnd, iNumber = 16 * iNumber + wParam -
(isdigit(wParam) ? '0' : 'A' - 10));
else
MessageBeep(0);
}
else //Operation
{
if (!bNewNumber)
ShowNumber(hwnd, iNumber =
CalcIt(iFirstNum, iOperation, iNumber));
bNewNumber = TRUE;
iOperation = LOWORD(wParam);
}
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
//Microsoft Developer Studio generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/
#undef APSTUDIO_READONLY_SYMBOLS
/
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""hexcalc.dlg""\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
HEXCALC ICON DISCARDABLE "HexCalc.ico"
#endif // English (U.S.) resources
/
#ifndef APSTUDIO_INVOKED
/
//
// Generated from the TEXTINCLUDE 3 resource.
//
#include "hexcalc.dlg"
/
#endif // not APSTUDIO_INVOKED
/*---------------------------
HEXCALC.DLG dialog script
---------------------------*/
HexCalc DIALOG -1, -1, 102, 122
STYLE WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX
CLASS "HexCalc"
CAPTION "Hex Calculator"
{
PUSHBUTTON "D", 68, 8, 24, 14, 14
PUSHBUTTON "A", 65, 8, 40, 14, 14
PUSHBUTTON "7", 55, 8, 56, 14, 14
PUSHBUTTON "4", 52, 8, 72, 14, 14
PUSHBUTTON "1", 49, 8, 88, 14, 14
PUSHBUTTON "0", 48, 8, 104, 14, 14
PUSHBUTTON "0", 27, 26, 4, 50, 14
PUSHBUTTON "E", 69, 26, 24, 14, 14
PUSHBUTTON "B", 66, 26, 40, 14, 14
PUSHBUTTON "8", 56, 26, 56, 14, 14
PUSHBUTTON "5", 53, 26, 72, 14, 14
PUSHBUTTON "2", 50, 26, 88, 14, 14
PUSHBUTTON "Back", 8, 26, 104, 32, 14
PUSHBUTTON "C", 67, 44, 40, 14, 14
PUSHBUTTON "F", 70, 44, 24, 14, 14
PUSHBUTTON "9", 57, 44, 56, 14, 14
PUSHBUTTON "6", 54, 44, 72, 14, 14
PUSHBUTTON "3", 51, 44, 88, 14, 14
PUSHBUTTON "+", 43, 62, 24, 14, 14
PUSHBUTTON "-", 45, 62, 40, 14, 14
PUSHBUTTON "*", 42, 62, 56, 14, 14
PUSHBUTTON "/", 47, 62, 72, 14, 14
PUSHBUTTON "%", 37, 62, 88, 14, 14
PUSHBUTTON "Equals", 61, 62, 104, 32, 14
PUSHBUTTON "&&", 38, 80, 24, 14, 14
PUSHBUTTON "|", 124, 80, 40, 14, 14
PUSHBUTTON "^", 94, 80, 56, 14, 14
PUSHBUTTON "<", 60, 80, 72, 14, 14
PUSHBUTTON ">", 62, 80, 88, 14, 14
}
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by HexCalc.rc
//
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 103
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1003
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
打开,存储文件,查找和替换,选择颜色字体的对话框。
创建某一结构并传递给公用对话框的某一函数,就能够显示公用对话框。
11.3.1 完善POPPAD
该项目的加入内存泄漏检测 ,加入设置zi
poppad3.cpp
#include
#include
#include "resource.h"
#include "DetectMemoryLeak.h"
#define EDITID 1
#define UNTITLED TEXT("(untitled)")
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //window procedure.
BOOL CALLBACK AboutDlgProc(HWND, UINT, WPARAM, LPARAM);
// Functions in POPFILE.cpp
void PopFileInitialize(HWND);
BOOL PopFileOpenDlg(HWND, PTSTR, PTSTR);
BOOL PopFileSaveDlg(HWND, PTSTR, PTSTR);
BOOL PopFileRead(HWND, PTSTR);
BOOL PopFileWrite(HWND, PTSTR);
// Function in POPFIND.cpp
HWND PopFindFindDlg(HWND);
HWND PopFindReplaceDlg(HWND);
BOOL PopFindFindText(HWND, int *, LPFINDREPLACE);
BOOL PopFindReplaceText(HWND, int *, LPFINDREPLACE);
BOOL PopFindNextText(HWND, int *);
BOOL PopFindValidFind(void);
// Functions in POPFONT.c
void PopFontInitialize(HWND);
BOOL PopFontChooseFont(HWND);
void PopFontSetFont(HWND);
void PopFontDeinitialize(void);
BOOL PopFontChooseFontColor(HWND);
void PopFontSetFontColor(HWND, COLORREF *);
// Functions in POPPRINT.c
BOOL PopPrntPrintFile(HINSTANCE, HWND, HWND, PTSTR);
// Global variables
// These variable could only be accessed in poppad3.cpp
static HWND hDlgModeless;
static TCHAR szAppName[] = TEXT("PopPad");
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
HACCEL hAccel;
HWND hwnd;
MSG msg;
WNDCLASS wndClass; //The window Class
wndClass.style = CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = WndProc;// assign the window procedure to windows class.
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = hInstance;
wndClass.hIcon = LoadIcon(hInstance, szAppName);// LoadIcon(NULL, IDI_APPLICATION);
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndClass.lpszMenuName = szAppName;
wndClass.lpszClassName = szAppName;
//Register the Window Class to the Windows System.
if (!RegisterClass(&wndClass))
{
MessageBox(NULL, TEXT("This program require Windows NT!"),
szAppName, MB_ICONERROR);
return 0;
}
//This function will generate an WM_CREATE message.
hwnd = CreateWindow(szAppName, //Window class name
NULL, //Window caption
WS_OVERLAPPEDWINDOW, //Window Style
CW_USEDEFAULT, //initial x position
CW_USEDEFAULT, //initial y position
CW_USEDEFAULT, //initial x size
CW_USEDEFAULT, //initial y size
NULL, //parent window handle
NULL, //window menu handle
hInstance, //program instance handle
NULL); //creation parameters
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd); //This function will generate a WM_PAINT message.
hAccel = LoadAccelerators(hInstance, szAppName);
/* The message loop for this program.
if received the WM_QUIT message, the function will return 0.*/
while (GetMessage(&msg, NULL, 0, 0))
{
if (hDlgModeless == NULL || !IsDialogMessage(hDlgModeless, &msg))
{
if (!TranslateAccelerator(hwnd, hAccel, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
return msg.wParam;
}
void DoCaption(HWND hwnd, TCHAR * szTitleName)
{
TCHAR szCaption[64 + MAX_PATH];
wsprintf(szCaption, TEXT("%s - %s"), szAppName,
szTitleName[0] ? szTitleName : UNTITLED);
SetWindowText(hwnd, szCaption);
}
void OkMessage(HWND hwnd, TCHAR * szMessage, TCHAR * szTitleName)
{
TCHAR szBuffer[64 + MAX_PATH];
wsprintf(szBuffer, szMessage, szTitleName[0] ? szTitleName : UNTITLED);
MessageBox(hwnd, szBuffer, szAppName, MB_OK | MB_ICONEXCLAMATION);
}
short AskAboutSave(HWND hwnd, TCHAR * szTitleName)
{
TCHAR szBuffer[64 + MAX_PATH];
int iReturn;
wsprintf(szBuffer, TEXT("Save current changes in %s?"),
szTitleName[0] ? szTitleName : UNTITLED);
iReturn = MessageBox(hwnd, szBuffer, szAppName,
MB_YESNOCANCEL | MB_ICONQUESTION);
if (iReturn == IDYES)
if (!SendMessage(hwnd, WM_COMMAND, IDM_FILE_SAVE, 0))
iReturn = IDCANCEL;
return iReturn;
}
//define the Window Procedure WndProc
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static BOOL bNeedSave = FALSE;
static HINSTANCE hInst;
static HWND hwndEdit;
static int iOffset;
static TCHAR szFileName[MAX_PATH], szTitleName[MAX_PATH];
static UINT messageFindReplace;
int iSelBeg, iSelEnd, iEnable;
static COLORREF iColor;
static HBRUSH hBrushEdit;
LPFINDREPLACE pfr;
switch (message) //get the message
{
case WM_CREATE:
hInst = ((LPCREATESTRUCT)lParam)->hInstance;
hwndEdit = CreateWindow(TEXT("edit"), NULL,
WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL |
WS_BORDER | ES_LEFT | ES_MULTILINE |
ES_NOHIDESEL | ES_AUTOHSCROLL | ES_AUTOVSCROLL,
0, 0, 0, 0,
hwnd, (HMENU)EDITID,
hInst, NULL);
SendMessage(hwndEdit, EM_LIMITTEXT, 3200, 0L);
// Initialize common dialog box stuff
PopFileInitialize(hwnd);
PopFontInitialize(hwndEdit);
messageFindReplace = RegisterWindowMessage(FINDMSGSTRING);
DoCaption(hwnd, szTitleName);
hBrushEdit = CreateSolidBrush(GetSysColor(COLOR_BTNHILIGHT));
return 0;
case WM_SETFOCUS:
SetFocus(hwndEdit);
return 0;
case WM_SIZE:
MoveWindow(hwndEdit, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
return 0;
case WM_INITMENUPOPUP:
switch (lParam)
{
case 1: // The index of edit menu
// Enable Undo if edit control can do it.
EnableMenuItem((HMENU)wParam, IDM_EDIT_UNDO,
SendMessage(hwndEdit, EM_CANUNDO, 0, 0) ?
MF_ENABLED : MF_GRAYED);
// Enable Paste if text is in the clipboard
EnableMenuItem((HMENU)wParam, IDM_EDIT_PASTE,
IsClipboardFormatAvailable(CF_TEXT) ?
MF_ENABLED : MF_GRAYED);
// Enable Cut, Copy, and Del if text is selected.
SendMessage(hwndEdit, EM_GETSEL, (WPARAM)&iSelBeg, (LPARAM)&iSelEnd);
iEnable = iSelBeg != iSelEnd ? MF_ENABLED : MF_GRAYED;
EnableMenuItem((HMENU)wParam, IDM_EDIT_CUT, iEnable);
EnableMenuItem((HMENU)wParam, IDM_EDIT_COPY, iEnable);
EnableMenuItem((HMENU)wParam, IDM_EDIT_CLEAR, iEnable);
break;
case 2: // Search menu
// Enable Find, Next, and Replace if modeless
// dialogs are not already active
iEnable = hDlgModeless == NULL ?
MF_ENABLED : MF_GRAYED;
EnableMenuItem((HMENU)wParam, IDM_SEARCH_FIND, iEnable);
EnableMenuItem((HMENU)wParam, IDM_SEARCH_NEXT, iEnable);
EnableMenuItem((HMENU)wParam, IDM_SEARCH_REPLACE, iEnable);
break;
}
return 0;
case WM_CTLCOLOREDIT:
if (EDITID == GetWindowLong((HWND)lParam, GWL_ID))
{
SetTextColor((HDC)wParam, iColor);
SetBkColor((HDC)wParam, GetSysColor(COLOR_BTNHIGHLIGHT));
return (LRESULT)hBrushEdit;
}
break;
case WM_COMMAND:
if (lParam && LOWORD(wParam) == EDITID) //edit control command.
{
switch (HIWORD(wParam))
{
case EN_UPDATE:
bNeedSave = TRUE;
return 0;
case EN_ERRSPACE:
case EN_MAXTEXT:
MessageBox(hwnd, TEXT("Edit control out of space."),
szAppName, MB_OK | MB_ICONSTOP);
return 0;
case EM_SETSEL:
return 0;
}
break;
}
switch (LOWORD(wParam))
{
// Messages from File menu
case IDM_FILE_NEW:
if (bNeedSave && IDCANCEL == AskAboutSave(hwnd, szTitleName))
return 0;
SetWindowText(hwndEdit, TEXT("\0"));
szFileName[0] = TEXT('\0');
szTitleName[0] = TEXT('\0');
DoCaption(hwnd, szTitleName);
bNeedSave = FALSE;
return 0;
case IDM_FILE_OPEN:
if (bNeedSave && IDCANCEL == AskAboutSave(hwnd, szTitleName))
return 0;
if (PopFileOpenDlg(hwnd, szFileName, szTitleName))
{
if (!PopFileRead(hwndEdit, szFileName))
{
OkMessage(hwnd, TEXT("Could not read file %s!"),
szTitleName);
szFileName[0] = TEXT('\0');
szTitleName[0] = TEXT('\0');
}
}
DoCaption(hwnd, szTitleName);
bNeedSave = FALSE;
return 0;
case IDM_FILE_SAVE:
if (szFileName[0])
{
if (PopFileWrite(hwndEdit, szFileName))
{
bNeedSave = FALSE;
return 1;
}
else
{
OkMessage(hwnd, TEXT("Could not write file %s"),
szTitleName);
return 0;
}
}
// fall through
case IDM_FILE_SAVE_AS:
if (PopFileSaveDlg(hwnd, szFileName, szTitleName))
{
DoCaption(hwnd, szTitleName);
if (PopFileWrite(hwndEdit, szFileName))
{
bNeedSave = FALSE;
return 1;
}
else
{
OkMessage(hwnd, TEXT("Could not write file %s"),
szTitleName);
return 0;
}
}
return 0;
case IDM_FILE_PRINT:
if (!PopPrntPrintFile(hInst, hwnd, hwndEdit, szTitleName))
OkMessage(hwnd, TEXT("Could not print file %s"), szTitleName);
return 0;
case IDM_APP_EXIT:
SendMessage(hwnd, WM_CLOSE, 0, 0);
return 0;
// Messages from Edit menu
case IDM_EDIT_UNDO:
SendMessage(hwndEdit, WM_UNDO, 0, 0);
return 0;
case IDM_EDIT_CUT:
SendMessage(hwndEdit, WM_CUT, 0, 0);
return 0;
case IDM_EDIT_COPY:
SendMessage(hwndEdit, WM_COPY, 0, 0);
return 0;
case IDM_EDIT_PASTE:
SendMessage(hwndEdit, WM_PASTE, 0, 0);
return 0;
case IDM_EDIT_CLEAR:
SendMessage(hwndEdit, WM_CLEAR, 0, 0);
return 0;
case IDM_EDIT_SELECT_ALL:
SendMessage(hwndEdit, EM_SETSEL, 0, -1);
return 0;
// Messages from Search menu
case IDM_SEARCH_FIND:
SendMessage(hwndEdit, EM_GETSEL, 0, (LPARAM)&iOffset);
hDlgModeless = PopFindFindDlg(hwnd);
return 0;
case IDM_SEARCH_NEXT:
SendMessage(hwndEdit, EM_GETSEL, 0, (LPARAM)&iOffset);
if (PopFindValidFind())
PopFindNextText(hwndEdit, &iOffset);
else
hDlgModeless = PopFindFindDlg(hwnd);
return 0;
case IDM_SEARCH_REPLACE:
SendMessage(hwndEdit, EM_GETSEL, 0, (LPARAM)&iOffset);
hDlgModeless = PopFindReplaceDlg(hwnd);
return 0;
case IDM_FORMAT_FONT:
if (PopFontChooseFont(hwnd))
PopFontSetFont(hwndEdit);
return 0;
case IDM_FORMAT_COLOR:
if (PopFontChooseFontColor((hwnd)))
PopFontSetFontColor(hwndEdit, &iColor);
return 0;
// Messages from Help menu
case IDM_HELP:
OkMessage(hwnd, TEXT("Help not yet implemented!"),
TEXT("\0"));
return 0;
case IDM_APP_ABOUT:
DialogBox(hInst, TEXT("AboutBox"), hwnd, AboutDlgProc);
return 0;
}
break;
case WM_CLOSE:
if (!bNeedSave || IDCANCEL != AskAboutSave(hwnd, szTitleName))
DestroyWindow(hwnd);
return 0;
case WM_QUERYENDSESSION:
if (!bNeedSave || IDCANCEL != AskAboutSave(hwnd, szTitleName))
return 1;
return 0;
case WM_DESTROY:
DeleteObject(hBrushEdit);
PopFontDeinitialize();
PostQuitMessage(0);
return 0;
default:
// Process "Find-Replace" messages
if (message == messageFindReplace)
{
pfr = (LPFINDREPLACE)lParam;
if (pfr->Flags & FR_DIALOGTERM)
hDlgModeless = NULL;
if (pfr->Flags & FR_FINDNEXT)
if (!PopFindFindText(hwndEdit, &iOffset, pfr))
OkMessage(hwnd, TEXT("Text not found!"),
TEXT("\0"));
if (pfr->Flags & FR_REPLACE || pfr->Flags & FR_REPLACEALL)
if (!PopFindReplaceText(hwndEdit, &iOffset, pfr))
OkMessage(hwnd, TEXT("Text not found!"),
TEXT("\0"));
if (pfr->Flags & FR_REPLACEALL)
while (PopFindReplaceText(hwndEdit, &iOffset, pfr))
;
return 0;
}
break;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
BOOL CALLBACK AboutDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
EndDialog(hDlg, 0);
return TRUE;
}
break;
}
return FALSE;
}
#include
#include
#include // for _tcsstr (strstr for Unicode & non-unicode)
#include "DetectMemoryLeak.h"
#define MAX_STRING_LEN 256
static TCHAR szFindText[MAX_STRING_LEN];
static TCHAR szReplText[MAX_STRING_LEN];
HWND PopFindFindDlg(HWND hwnd)
{
static FINDREPLACE fr; // must be static for modeless dialog!!!
fr.lStructSize = sizeof(FINDREPLACE);
fr.hwndOwner = hwnd;
fr.hInstance = NULL;
fr.Flags = FR_HIDEUPDOWN | FR_HIDEMATCHCASE | FR_HIDEWHOLEWORD;
fr.lpstrFindWhat = szFindText;
fr.lpstrReplaceWith = NULL;
fr.wFindWhatLen = MAX_STRING_LEN;
fr.wReplaceWithLen = 0;
fr.lCustData = 0;
fr.lpfnHook = NULL;
fr.lpTemplateName = NULL;
return FindText(&fr);
}
HWND PopFindReplaceDlg(HWND hwnd)
{
static FINDREPLACE fr; // must be static for modeless dialog!!!
fr.lStructSize = sizeof(FINDREPLACE);
fr.hwndOwner = hwnd;
fr.hInstance = NULL;
fr.Flags = FR_HIDEUPDOWN | FR_HIDEMATCHCASE | FR_HIDEWHOLEWORD;
fr.lpstrFindWhat = szFindText;
fr.lpstrReplaceWith = szReplText;
fr.wFindWhatLen = MAX_STRING_LEN;
fr.wReplaceWithLen = MAX_STRING_LEN;
fr.lCustData = 0;
fr.lpfnHook = NULL;
fr.lpTemplateName = NULL;
return ReplaceText(&fr);
}
BOOL PopFindFindText(HWND hwndEdit, int * piSearchOffset, LPFINDREPLACE pfr)
{
int iLength, iPos;
PTSTR pstrDoc, pstrPos;
// Read in the edit document
iLength = GetWindowTextLength(hwndEdit);
if (NULL == (pstrDoc = (PTSTR)malloc((iLength + 1) * sizeof(TCHAR))))
return FALSE;
GetWindowText(hwndEdit, pstrDoc, iLength + 1);
// Search the document for the find string
pstrPos = _tcsstr(pstrDoc + *piSearchOffset, pfr->lpstrFindWhat);
free(pstrDoc);
// Return an error code if the string cannot be found
if (pstrPos == NULL)
return FALSE;
// Find the position in the document and the new start offset
iPos = pstrPos - pstrDoc;
*piSearchOffset = iPos + lstrlen(pfr->lpstrFindWhat);
// Select the found text
SendMessage(hwndEdit, EM_SETSEL, iPos, *piSearchOffset);
SendMessage(hwndEdit, EM_SCROLLCARET, 0, 0);
return TRUE;
}
BOOL PopFindNextText(HWND hwndEdit, int * piSearchOffset)
{
FINDREPLACE fr;
fr.lpstrFindWhat = szFindText;
return PopFindFindText(hwndEdit, piSearchOffset, &fr);
}
BOOL PopFindReplaceText(HWND hwndEdit, int * piSearchOffset, LPFINDREPLACE pfr)
{
// Find the text
if (!PopFindFindText(hwndEdit, piSearchOffset, pfr))
return FALSE;
// Replace it
SendMessage(hwndEdit, EM_REPLACESEL, 0, (LPARAM)pfr->lpstrReplaceWith);
return TRUE;
}
BOOL PopFindValidFind(void)
{
return *szFindText != '\0';
}
popfont.cpp
#include
#include
#include "DetectMemoryLeak.h"
static LOGFONT logfont;
static HFONT hFont;
static CHOOSECOLOR cc;
static COLORREF crCustColors[16];
BOOL PopFontChooseFont(HWND hwnd)
{
CHOOSEFONT cf;
cf.lStructSize = sizeof(CHOOSEFONT);
cf.hwndOwner = hwnd;
cf.hDC = NULL;
cf.lpLogFont = &logfont;
cf.iPointSize = 0;
cf.Flags = CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS | CF_EFFECTS;
cf.rgbColors = 0;
cf.lCustData = 0;
cf.lpfnHook = NULL;
cf.lpTemplateName = NULL;
cf.hInstance = NULL;
cf.lpszStyle = NULL;
cf.nFontType = 0; // Returned from ChooseFont
cf.nSizeMin = 0;
cf.nSizeMax = 0;
return ChooseFont(&cf);
}
void PopFontInitialize(HWND hwndEdit)
{
GetObject(GetStockObject(SYSTEM_FONT), sizeof(LOGFONT),
(PTSTR)&logfont);
hFont = CreateFontIndirect(&logfont);
SendMessage(hwndEdit, WM_SETFONT, (WPARAM)hFont, 0);
}
void PopFontSetFont(HWND hwndEdit)
{
HFONT hFontNew;
RECT rect;
hFontNew = CreateFontIndirect(&logfont);
SendMessage(hwndEdit, WM_SETFONT, (WPARAM)hFontNew, 0);
DeleteObject(hFont);
hFont = hFontNew;
GetClientRect(hwndEdit, &rect);
InvalidateRect(hwndEdit, &rect, TRUE);
}
void PopFontDeinitialize(void)
{
DeleteObject(hFont);
}
BOOL PopFontChooseFontColor(HWND hwnd)
{
cc.lStructSize = sizeof(CHOOSECOLOR);
cc.hwndOwner = hwnd;
cc.hInstance = NULL;
cc.lpCustColors = crCustColors;
cc.Flags = CC_RGBINIT | CC_FULLOPEN;
cc.lCustData = 0;
cc.lpfnHook = NULL;
cc.lpTemplateName = NULL;
return ChooseColor(&cc);
}
void PopFontSetFontColor(HWND hwndEdit, COLORREF * iColor)
{
*iColor = cc.rgbResult;
InvalidateRect(hwndEdit, NULL, TRUE); // Redraw the edit control . It will cause the WM_CTLCOLOREDIT message
}
#include
#include "DetectMemoryLeak.h"
BOOL PopPrntPrintFile(HINSTANCE hInst, HWND hwnd, HWND hwndEdit,
PTSTR pstrTitleName)
{
return FALSE;
}
#pragma once
#ifndef _UT_DETECT_MEMLEAK_H
#define _UT_DETECT_MEMLEAK_H
#ifdef _DEBUG
#define new DEBUG_CLIENTBLOCK
#define DebugCodeCRT(m) {m;}
#endif
#ifdef _DEBUG
#define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__)
#else
#define DEBUG_CLIENTBLOCK
#endif
#define _CRTDBG_MAP_ALLOC
#include
#ifdef _DEBUG
#define new DEBUG_CLIENTBLOCK
#endif
#endif _UT_DETECT_MEMLEAK_H
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/
#undef APSTUDIO_READONLY_SYMBOLS
/
// English (United States) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#ifdef APSTUDIO_INVOKED
/
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/
//
// Dialog
//
ABOUTBOX DIALOG 32, 32, 180, 100
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "OK",IDOK,66,80,50,14
ICON "POPPAD",IDC_STATIC,7,7,20,20
CTEXT "PopPad",IDC_STATIC,40,12,100,8
CTEXT "Popup Editor for Windows",IDC_STATIC,7,40,166,8
CTEXT "(c) Charles Petzold, 1998",IDC_STATIC,7,52,166,8
END
PRINTDLGBOX DIALOG 32, 32, 186, 95
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "PopPad"
FONT 8, "MS Sans Serif"
BEGIN
PUSHBUTTON "Cancel",IDCANCEL,67,74,50,14
CTEXT "Sending",IDC_STATIC,8,8,172,8
CTEXT "",IDC_FILENAME,8,28,172,8
CTEXT "to print spooler.",IDC_STATIC,8,48,172,8
END
/
//
// Menu
//
POPPAD MENU
BEGIN
POPUP "&File"
BEGIN
MENUITEM "&New\tCtrl+N", IDM_FILE_NEW
MENUITEM "&Open...\tCtrl+O", IDM_FILE_OPEN
MENUITEM "&Save\tCtrl+S", IDM_FILE_SAVE
MENUITEM "Save &As...", IDM_FILE_SAVE_AS
MENUITEM SEPARATOR
MENUITEM "&Print\tCtrl+P", IDM_FILE_PRINT
MENUITEM SEPARATOR
MENUITEM "E&xit", IDM_APP_EXIT
END
POPUP "&Edit"
BEGIN
MENUITEM "&Undo\tCtrl+Z", IDM_EDIT_UNDO
MENUITEM SEPARATOR
MENUITEM "Cu&t\tCtrl+X", IDM_EDIT_CUT
MENUITEM "&Copy\tCtrl+C", IDM_EDIT_COPY
MENUITEM "&Paste\tCtrl+V", IDM_EDIT_PASTE
MENUITEM "De&lete\tDel", IDM_EDIT_CLEAR
MENUITEM SEPARATOR
MENUITEM "&Select All", IDM_EDIT_SELECT_ALL
END
POPUP "&Search"
BEGIN
MENUITEM "&Find...\tCtrl+F", IDM_SEARCH_FIND
MENUITEM "Find &Next\tF3", IDM_SEARCH_NEXT
MENUITEM "&Replace...\tCtrl+R", IDM_SEARCH_REPLACE
END
POPUP "F&ormat"
BEGIN
MENUITEM "&Font...", IDM_FORMAT_FONT
MENUITEM "Color...", IDM_FORMAT_COLOR
END
POPUP "&Help"
BEGIN
MENUITEM "&Help", IDM_HELP
MENUITEM "&About PopPad...", IDM_APP_ABOUT
END
END
/
//
// Accelerator
//
POPPAD ACCELERATORS
BEGIN
VK_BACK, IDM_EDIT_UNDO, VIRTKEY, ALT, NOINVERT
VK_DELETE, IDM_EDIT_CLEAR, VIRTKEY, NOINVERT
VK_DELETE, IDM_EDIT_CUT, VIRTKEY, SHIFT, NOINVERT
VK_F1, IDM_HELP, VIRTKEY, NOINVERT
VK_F3, IDM_SEARCH_NEXT, VIRTKEY, NOINVERT
VK_INSERT, IDM_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT
VK_INSERT, IDM_EDIT_PASTE, VIRTKEY, SHIFT, NOINVERT
"^C", IDM_EDIT_COPY, ASCII, NOINVERT
"^F", IDM_SEARCH_FIND, ASCII, NOINVERT
"^N", IDM_FILE_NEW, ASCII, NOINVERT
"^O", IDM_FILE_OPEN, ASCII, NOINVERT
"^P", IDM_FILE_PRINT, ASCII, NOINVERT
"^R", IDM_SEARCH_REPLACE, ASCII, NOINVERT
"^S", IDM_FILE_SAVE, ASCII, NOINVERT
"^V", IDM_EDIT_PASTE, ASCII, NOINVERT
"^X", IDM_EDIT_CUT, ASCII, NOINVERT
"^Z", IDM_EDIT_UNDO, ASCII, NOINVERT
END
/
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
POPPAD ICON "poppad.ico"
/
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
"ABOUTBOX", DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 179
TOPMARGIN, 7
BOTTOMMARGIN, 88
END
"PRINTDLGBOX", DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 179
TOPMARGIN, 7
BOTTOMMARGIN, 88
END
END
#endif // APSTUDIO_INVOKED
#endif // English (United States) resources
/
#ifndef APSTUDIO_INVOKED
/
//
// Generated from the TEXTINCLUDE 3 resource.
//
/
#endif // not APSTUDIO_INVOKED
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by POPPAD.RC
//
#define IDC_FILENAME 1000
#define IDM_FILE_NEW 40001
#define IDM_FILE_OPEN 40002
#define IDM_FILE_SAVE 40003
#define IDM_FILE_SAVE_AS 40004
#define IDM_FILE_PRINT 40005
#define IDM_APP_EXIT 40006
#define IDM_EDIT_UNDO 40007
#define IDM_EDIT_CUT 40008
#define IDM_EDIT_COPY 40009
#define IDM_EDIT_PASTE 40010
#define IDM_EDIT_CLEAR 40011
#define IDM_EDIT_SELECT_ALL 40012
#define IDM_SEARCH_FIND 40013
#define IDM_SEARCH_NEXT 40014
#define IDM_SEARCH_REPLACE 40015
#define IDM_FORMAT_FONT 40016
#define IDM_HELP 40017
#define IDM_APP_ABOUT 40018
#define IDM_FORMAT_COLOR 40019
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 110
#define _APS_NEXT_COMMAND_VALUE 40021
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
可以改变和设置字体颜色
11.3.2 Unicode 文件的读写操作
在写入Unicode文件时先写入文件头 0xFEFF 表示此文本文件含有Unicode
在读取时,使用IsTextUnicode函数来判断是否含有字节顺序标志,还会检测字节顺序标志是否反序的。 这意味此Unicode文本文件是在Macintosh或其他与Intel
处理器字节顺序相反的机器上生成的。
Unicode 转 ANSI
WideCharToMultiChar
WideCharToMultiByte(CP_ACP, 0, (PWSTR)pText, -1, pConv, iFileLength + 2, NULL, NULL);
ANSI 转Unicode
MultiByteToWideChar(CP_ACP, 0, (LPCCH)pText, -1, (PTSTR)pConv,iFileLength + 1);
11.3.3 改变字体
在处理WM_CREATE的时候,调用PopFontInitialize函数
获取基于系统字体的LOGFONT结构,并由他创建一个字体,然后向编辑控件发送WM_SETFONT消息来设定新字体。
GetObject(GetStockObject(SYSTEM_FONT), sizeof(LOGFONT),
(PTSTR)&logfont);
hFont = CreateFontIndirect(&logfont);
SendMessage(hwndEdit, WM_SETFONT, (WPARAM)hFont, 0);
当用户选择字体时
会初始化CHOOSEFONT结构,然后调用ChooseFont来显示字体选择对话框,用户按下OK此函数会返回TRUE
然后POPPAD调用PopFontSetFont函数为编辑控件设置新字体,旧字体会被删除。
最后在WM_DESTROY时,POPPAD会调用PopFontDeinitialize函数来删除PopFontSetFont最后创建的字体
11.3.4 查找和替换
FindText 和ReplaceText 使用FINDREPLACE的结构
在查找和替换函数时由一些需要注意的事项。
1, 他们使用的对话框是非模态对话框,这意味着当对话框在使用时消息循环应该调用IsDialogMessage函数。
2,传递给FindText和ReplaceText的FINDREPLACE结构必须是静态变量。
3,在FindText和ReplaceText时,他们与拥有他们的对窗口通过一种特殊的消息进行通信。这个消息对应值可以通过messageFindReplace = RegisterWindowMessage(FINDMSGSTRING); 来获取。
在处理默认消息时,WndProc比较messageFindReplace, 消息参数lParam是一个指向FINDREPLACE结构的指针,该结构的Flags表示用户是否已经在用对话框来查找或替换文本,或正在关闭该对话框。
通过调用PopFindFindText和PopFindReplaceText函数来实现查找和替换文本的功能。
11.3.5 只调用一个函数的Windows程序
Color3
#include
#include
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static CHOOSECOLOR cc;
static COLORREF crCustColors[16];
cc.lStructSize = sizeof(CHOOSECOLOR);
cc.hwndOwner = NULL;
cc.hInstance = NULL;
cc.rgbResult = RGB(0x80, 0x80, 0x80);
cc.lpCustColors = crCustColors;
cc.Flags = CC_RGBINIT | CC_FULLOPEN;
cc.lCustData = 0;
cc.lCustData = 0;
cc.lpfnHook = NULL;
cc.lpTemplateName = NULL;
return ChooseColor(&cc);
}
运行结果
ChooseColor使用一个类型为 CHOOSECOLOR的结构和一个用来存储用户通过对话框选择的颜色含有16个DWORD值的数组。如果Flags字段
设定CC_RGBINIT,那么rgbResult字段可以被初始化为锁要显示的颜色。一般情况下,rgbResult字段会被设置为用户选择的颜色。
hwndOwnver 为NULL, 这是完全合法的。表示该对话框不属于任何窗口所有,会出现在windows任务列表中,并且对话框看上去和一般窗口狠相似。
也可以在自己的程序对话框中使用这种技巧。Windows程序完全可以只创建一个对话框,并在该对话框过程中完成所有操作。