《Windows程序设计》读书笔十一 对话框

第十一章  对话框


基于模板的对话框,包含了弹出窗口,和子窗口控件,而且有一个窗口过程来处理对话框消息。 包括键盘和鼠标的输入。

称为 “对话框管理器”  和标准的Windows窗口消息处理略有不同。稍后能看到具体区别


许多消息不仅被对话框窗口过程处理,还会传递给你自己的程序中的某些函数。  称为对话框过程

对话框过程一般处理初始化自创控件以及子窗口传来的消息。不处理WM_PAINT 也不直接处理键盘和鼠标的输入


子窗口控件由windows对话框管理器来负责。对话框管理器来负责处理在多个控件中转义输入焦点的相关逻辑


11.1  模态对话框

用户不能在该对话框和该程序的其他对话框之间切换。但是可以切换到其他的程序。有些系统模态不允许切换程序。必须结束系统模态才可以进行其他操作。

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;
}

About1.rc

// 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

《Windows程序设计》读书笔十一 对话框_第1张图片
11.1.2 对话框及其模板


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函数   使用数据结构来定义对话框模板。

常用控件类型的相应窗口类和窗口样式

《Windows程序设计》读书笔十一 对话框_第2张图片

《Windows程序设计》读书笔十一 对话框_第3张图片

除了表中的样式,每个控件默认还有以下样式

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;
}

About2.rc

//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


Resource.h

//{{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

运行结果

《Windows程序设计》读书笔十一 对话框_第4张图片


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;
}


11.1.10 TAB停靠和选项组

需要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);
}


about3.rc

//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


resource.h

//{{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


运行结果

《Windows程序设计》读书笔十一 对话框_第5张图片

11.2 非模态对话框

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;
}

colors2.rc

// 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


resource.h

//{{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

运行结果

《Windows程序设计》读书笔十一 对话框_第6张图片

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);
}

hexcalc.rc

//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

/*---------------------------
   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
}

resource.h

//{{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


运行结果

《Windows程序设计》读书笔十一 对话框_第7张图片


11.3 公用对话框

打开,存储文件,查找和替换,选择颜色字体的对话框。

创建某一结构并传递给公用对话框的某一函数,就能够显示公用对话框。


11.3.1 完善POPPAD


该项目的加入内存泄漏检测 ,加入设置zi

poppad3.cpp


popfile.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;
}


popfind.cpp

#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
}



popprint0.cpp

#include 
#include "DetectMemoryLeak.h"

BOOL PopPrntPrintFile(HINSTANCE hInst, HWND hwnd, HWND hwndEdit,
	PTSTR pstrTitleName)
{
	return FALSE;
}

Detectmemoryleak.h

#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  

poppad.rc

// 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



resource.h

//{{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



运行结果

《Windows程序设计》读书笔十一 对话框_第8张图片


可以改变和设置字体颜色

《Windows程序设计》读书笔十一 对话框_第9张图片



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);
}
运行结果

《Windows程序设计》读书笔十一 对话框_第10张图片

ChooseColor使用一个类型为 CHOOSECOLOR的结构和一个用来存储用户通过对话框选择的颜色含有16个DWORD值的数组。如果Flags字段
设定CC_RGBINIT,那么rgbResult字段可以被初始化为锁要显示的颜色。一般情况下,rgbResult字段会被设置为用户选择的颜色。


hwndOwnver 为NULL, 这是完全合法的。表示该对话框不属于任何窗口所有,会出现在windows任务列表中,并且对话框看上去和一般窗口狠相似。

也可以在自己的程序对话框中使用这种技巧。Windows程序完全可以只创建一个对话框,并在该对话框过程中完成所有操作。

你可能感兴趣的:(Windows)