对话框管理器——Windows内置的对话框代码
①负责创建对话框窗口及其上面的子窗口控件;在创建对话框函数的内部,Windows使用用户自定义的对话框模板,并且使用Windows内部定义的窗口类(一般类名是“#32770”)来创建对话框。
②提供内置的窗口过程来处理对话框消息(包括所有鼠标和键盘输入)
③内置的窗口过程会将消息传递给我们自定义的“对话框过程”(也叫“对话过程”)。
④对话框中,Windows负责处理在多个控件中转移输入焦点的相关逻辑。
11.1 模态对话框
11.1.1 对话框及其模板
(1)对话框的坐标单位——基于对话框所用的字体的大小(本例为“"MS Shell Dlg"”)
X轴:以字符的平均宽度的1/4为单位。如x=32表示8个字符宽度处
Y轴:以字符的平均高度的1/8为单位。如y=32表示4个字符高度处。
★一般字体的字符高度是宽度的两倍,所以X轴与Y轴的尺寸基本相同
★可通过MapDialogRect函数将字符为单位的坐标转换为对话框客户区的像素坐标。
(2)对话框模板
①STYLE语句与CreateWindow中的样式相似,模态对话框用WS_POPUP|DS_MODALFRAME
样式 |
功能 |
备注 |
WM_POPUP |
弹出式窗口 |
模态对话框用WS_POPUP|DS_MODALFRAME |
DS_MODALFRAME |
去边框 |
|
WM_CAPTION |
标题栏,允许移动对话框 |
CAPTION “DialogBox Caption” SetWindowText(hDlg,TEXT(“对话框”)); |
WS_SYSMENU |
添加系统菜单 |
允许Move或Close对话框 |
WS_THICKFRAME |
允许改变对话框大小 |
等价于对话框Border属性中选择Resizing |
②MNEU 菜单名 ——允许为对话框添加菜单
③FONT 字号,字体名称 ——发布程序要一起打包
④CLASS “类名”
A、没指定窗口类名时——Windows会自动提供一个特殊的窗口类,该窗口类的内置过程会调用我们定义的对话框过程(由DialogBox最后一个参数提供)
B、指定窗口类名时——可以使用自己的窗口类及窗口过程来处理对话框消息,窗口类的cbWndExtra必须设定为DLGWINDOWEXTRA。
⑤定义子窗口控件格式
控件类型 “文本”,ID,xPos,yPos,xWidth,yHeight,iStyle
CONTROL “文本”,ID,“类”,iStyle,xPos,yPos,xWidth,yHeight //通用格式
A、控件类型
控件类型 |
窗口类 |
窗口样式 |
PUSHBUTTON |
button |
BS_PUSHBUTTON|WS_TABSTOP |
DEFPUSHBUTTON |
button |
BS_DEFPUSHBUTTON|WS_TABSTOP |
CHECKBOX |
button |
BS_CHECKBOX|WS_TABSTOP |
RADIOBUTTON |
button |
BS_RADIOBUTTON|WS_TABSTOP |
GROUPBOX |
button |
BS_GROUPBOX |
LTEXT |
static |
SS_LEFT|WS_GROUP |
CTEXT |
static |
SS_CENTER|WS_GROUP |
RTEXT |
static |
SS_RIGHT|WS_GROUP |
ICON |
static |
SS_ICON |
EDITTEXT |
edit |
ES_LEFT|WS_BORDER|WS_TABSTOP |
SCROLLBAR |
scrollbar |
SBS_HORZ |
LISTBOX |
listbox |
LBS_NOTIFY|WS_BORDER |
COMBOBOX |
combobox |
CBS_SIMPLE|WS_TABSTOP |
★子控件除以上样式外,还有WS_CHILD|WS_VISIBLE样式
★除EDITTEXT、SCROLLBAR、LISTBOX、COMBOBOX没“文本”,其他都有。
控件类型 ID,xPos,yPos,xWidth,yHeight,iStyle//注意,没“文本”这项。
B、文本字段中的符号加“&”会添加一个键盘接口,如“&Red”,按R时,焦点会转过来。
C、应用举例
功能需求 |
相应的模板语句 |
复选框,文本左侧 |
CHECKBOX “TEXT”,ID,xPos,yPos,xWidth,yHeight,BS_LEFTTEXT |
没边框的编辑框 |
EDITTEXT,ID,xPos,yPos,xWidth,yHeight,NOT WS_BORDER |
按钮及等价代码 |
PUSHBUTTON “OK”,IDOK,10,20,32,14 CONTROL “OK”,IDOK,“button”,WS_CHILD|WS_VISIBLE| BS_PUSHBUTTON|WS_TABSTOP,10,20,32,14 |
D、模板语句及等价调用(以上面创建按钮的模板语句为例)
hCtrl =CreateWindow(TEXT(“button”,TEXT(“OK”),
WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON|WS_TABSTOP|BS_PUSHBUTTON,10*cxChar/4 ,20*cyChar /8,32*cxChar/4, 14*cyChar/8,
hDlg,IDOK,hInstance,NULL);
⑥WS_TABSTOP——可以通过TAB键获得输入焦点,按TAB键,焦点只会在有WS_TABSTOP的控件间转移。
⑦WS_GROUP——定义一组控件
A、从第一个含有WS_GROUP样式开始,到下一个含有该样式的控件之间的为一组
B、组内控件可以通过方向键循环转移焦点。
C、同组中随着光标移动键,不但会转移焦点,还会赋于新的焦点控件WS_TABSTOP样式,这样下次再按Tab时会定位到该控件上。
⑧不向父窗口发送消息的子控件(如文本和图标),ID设为IDC_STATIC(-1)。
⑨IDOK、IDCANCEL在WINUSER.H中分别被定义为1、2
11.1.2 对话框过程
(1)子窗口向父窗口发送WM_COMMAND过程:子窗口→父窗口(对话框)内置的窗口过程→自定义的对话框过程
(2)对话框过程
BOOL CALLBACK AboutDlgProc(HWND hDlg,UINT msg,WPARAM wParam,lPARAMlParam)
{
switch(message)
{
case WM_INITDIALOG:
return TRUE; //表示消息处理过了,不让对话框内置的窗口过程处理了。
case WM_COMMAND:
switch(LOWORD(wParam)) //子控件ID
{
case IDOK:
case IDCANCEL:
EndDialog(hDlg,0); //结束模态对话框,0会返回给创建模态对话框的那个函数,如作为DialobBox函数的返回值。
return TRUE; //该消息处理好了,不让内置的窗口过程处理了。
}
}
return FALSE; //False表示其余消息不处理,留给内置对话框窗口过程去处理
}
|
对话框过程 |
一般窗口过程 |
返回值 |
BOOL |
LRESULT |
默认处理 |
当返回值为 ①TRUE时表示该消息在对话框过程巳处理,不再传递给内置的对话框处理。 ②FALSE 表示该消息未处理好,得再交给内置的对话框过程。 |
DefWindowProc |
接收的第1条消息 |
①WM_INIDIALOG消息(对话框独有的)进行初始化工作,并把焦点设置为第1个含有WS_TABSTOP的子窗口控件。自定义的对话框过程不会收到WM_CREATE。 ②在该消息中可手动设置焦点(SetFocus),但返回值有点特殊,应设为FALSE。如果为TRUE,Windows会自动将输入焦点设置到第一个有WS_TABSTOP的子控件上。 |
WM_CREATE |
创建 |
DialogBox或DialogBoxIndirectParam——模态 CreateDialog——非模态 |
CreateWindow |
销毁 |
用EndDialog通知Windows销毁(内部会调用WM_DESTROY) |
WM_DESTROY |
WM_COMMAND |
LOWORD(wParam):子控件、菜单、加速键ID HIWORD(wParam):通知码,加速键时为1,菜单为0,其它为子控件的通知码 LParam:子控件句柄 |
/*------------------------------------------ ABOUT1.C -- About Box Demo Program No. 1 (c) Charles Petzold, 1998 ------------------------------------------*/ #include <windows.h> #include "resource.h" LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); BOOL CALLBACK AboutDlgProc(HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT("About1"); MSG msg; HWND hwnd; WNDCLASS wndclass; wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(hInstance, szAppName); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.lpszMenuName = szAppName; wndclass.lpszClassName = szAppName; if (!RegisterClass(&wndclass)) { MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR); return 0; } hwnd = CreateWindow(szAppName, TEXT("About Box Demo Program"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); ShowWindow(hwnd, iCmdShow); UpdateWindow(hwnd); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static HINSTANCE hInstance; switch (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; }
//resource.h
//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
//About1.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 " END 2 TEXTINCLUDE DISCARDABLE BEGIN "#include ""afxres.h"" " "