上一篇我们学习了菜单的基本编程,本篇来了解一下通用对话框的使用。Windows系统之所以是目前最流行的桌面系统,也是因为Windows有一套标准化,统一友好的交互界面,比如菜单、工具栏、状态栏以及各个控件。当然除了这些单独的控件之外,对于像文件打开、保存对话框,字体对话,颜色对话框等对于Windows本身会用到,在很多第三方的应用程序中也会用到。因此微软公司也早就清楚这种现实情况会存在,所以Windows把这种常见的公共对话就做了统一的接口函数,供Windows自己和第三方开发者使用。
Windows提供的公用对话框在不同的版本有所不一样,但常见的公用对话框有:颜色选择对话框、打开文件对话框、保存文件对话框、字体选择对话框、查找对话框、替换对话框、打印对话框以及打印设置对话框等。
本篇以最常见的文件打开/保存对话框、字体对话框、颜色对话框为例,来学习如何创建这些对话框,其他的对话框使用大同小异,且在MSDN上基本都有使用实例。
要使用公用对话框函数,需要包含commdlg.h头文件,相关的数据结构和函数定义都在该头文件中定义。
- 文件打开对话框
文件打开对话框主要用于选择需要的文件,把选择的文件全路径名传给用户,至于取到文件全路径之后怎么操作完全是开发者自己决定。也就是说它提供了一个在电脑中选择任何文件的公共操作接口。API函数定义如下:
1 |
BOOL GetOpenFileName(LPOPENFILENAME lpofn); |
参数lpofn的定义如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
typedef struct tagOFN { DWORD lStructSize; HWND hwndOwner; HINSTANCE hInstance; LPCTSTR lpstrFilter; LPTSTR lpstrCustomFilter; DWORD nMaxCustFilter; DWORD nFilterIndex; LPTSTR lpstrFile; DWORD nMaxFile; LPTSTR lpstrFileTitle; DWORD nMaxFileTitle; LPCTSTR lpstrInitialDir; LPCTSTR lpstrTitle; DWORD Flags; WORD nFileOffset; WORD nFileExtension; LPCTSTR lpstrDefExt; LPARAM lCustData; LPOFNHOOKPROC lpfnHook; LPCTSTR lpTemplateName; #if (_WIN32_WINNT >= 0x0500) void * pvReserved; DWORD dwReserved; DWORD FlagsEx; #endif // (_WIN32_WINNT >= 0x0500) } OPENFILENAME, *LPOPENFILENAME; |
该接口定义的各个参数成员请参考MSDN的详细解释,这里我们最常用到的几项如下:
lpstrFilter:该参数用于设置打开或保存对话的文件格式过滤,比如下图中的文件过滤情景,相信所有的读者朋友都见过:
lpstrFile:该参数用于保存选择结束后的选择文件。
nMaxFile:该参数指出上面用于保存结果文件的buffer字符长度。
Flags:该参数最常见用于设置是否可以多选,其他请查看MSDN。
- 文件保存对话框
文件保存对话框跟文件打开对话几乎完全一样,参数相同。功能也是为用户保存文件时选择或新建文件名、保存路径进行选择的公共操作接口。API函数定义如下:
1 |
BOOL GetSaveFileName(LPOPENFILENAME lpofn); |
该函数的参数与上面完全一样,只是有些不能在文件保存对话框函数中使用,保存文件时不能多选名字。
- 颜色选择对话框
该对话框函数提供统一接口用于选择颜色,API函数定义如下:
1 |
BOOL ChooseColor(LPCHOOSECOLOR lpcc); |
参数lpcc最重要的参数:
lpCustColors,它指向一个包含16个值的数组,该数组包含了对话框中自定义颜色的红、绿、蓝(RGB)值。如果用户修改这些颜色,系统将用新的颜色值更新这个数组。如果要在多个ChooseColor函数中保存这个新的数组,我们应该为该数组分配静态内存空间。
rgbResult:该参数保存了选择的颜色值。
- 字体选择对话框:
该对话框函数用于浏览并选择字体,包括颜色。API函数定义如下:
1 |
BOOL ChooseFont(LPCHOOSEFONT lpcf); |
对话框函数运行结束后的字体在rgbColors参数中,我们可以用它来创建选择的字体。
以上各个结构的其他成员请参考MSDN。
下面我们以一个demo程序演示以上几种公共对话框的基本用法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
#include <windows.h> #include <tchar.h> #pragma comment(linker,"\"/manifestdependency:type='win32' "\ "name='Microsoft.Windows.Common-Controls' "\ "version='6.0.0.0' processorArchitecture='*' "\ "publicKeyToken='6595b64144ccf1df' language='*'\"") #define IDC_FILE_DIALOG 1001 #define IDC_COLOR_DIALOG 1002 #define IDC_FONT_DIALOG 1003 static TCHAR szAppName[] = TEXT("CommonDialog"); static LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { HWND hWnd; MSG msg; WNDCLASS wndclass; wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = szAppName; if (!RegisterClass(&wndclass)) { MessageBox (NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR); return 0; } hWnd = CreateWindow(szAppName, // window class name szAppName, // window caption WS_OVERLAPPEDWINDOW, // window style CW_USEDEFAULT, // initial x position CW_USEDEFAULT, // initial y position 400, // initial x size 300, // initial y size NULL, // parent window handle NULL, // window menu handle hInstance, // program instance handle NULL); // creation parameters ShowWindow(hWnd, iCmdShow); UpdateWindow(hWnd); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hDC; switch (message) { case WM_CREATE: CreateWindow(TEXT("BUTTON"), TEXT("file dialog"), WS_CHILD|WS_VISIBLE, 20, 40, 160, 40, hWnd, (HMENU)IDC_FILE_DIALOG, NULL, NULL); CreateWindow(TEXT("BUTTON"), TEXT("color dialog"),WS_CHILD|WS_VISIBLE, 20, 100, 160, 40, hWnd, (HMENU)IDC_COLOR_DIALOG, NULL, NULL); CreateWindow(TEXT("BUTTON"), TEXT("font dialog"), WS_CHILD|WS_VISIBLE, 20, 160, 160, 40, hWnd, (HMENU)IDC_FONT_DIALOG, NULL, NULL); return 0; case WM_COMMAND: { int wmId = LOWORD(wParam); switch (wmId) { case IDC_FILE_DIALOG: { OPENFILENAME ofn; TCHAR ext[] = TEXT(".dat"); TCHAR szFile[MAX_PATH] = TEXT("default"); TCHAR szFilter[] = TEXT("文本文件 (*.txt)\0*.txt\0") TEXT("数据文件 (*.dat)\0*.dat\0") TEXT("All Files (*.*)\0*.*\0\0"); ZeroMemory(&ofn, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = hWnd; ofn.lpstrFilter = szFilter; ofn.nFilterIndex = 1; // 1 to default show *.txt type file; 2 to default show *.dat type file. ofn.lpstrFile = szFile; ofn.nMaxFile = MAX_PATH; ofn.lpstrDefExt = ext; ofn.Flags = OFN_PATHMUSTEXIST|OFN_OVERWRITEPROMPT; if (GetOpenFileName(&ofn))//GetOpenFileName, GetSaveFileName { //将选择的文件输出到窗口 LPTSTR file = ofn.lpstrFile; //file就是保存或者打开的文件名 hDC = GetDC(hWnd); TextOut(hDC, 200, 50, ofn.lpstrFile, _tcslen(ofn.lpstrFile)); ReleaseDC(hWnd, hDC); } } break; case IDC_COLOR_DIALOG: { CHOOSECOLOR cc; static COLORREF acrCustClr[16]; ZeroMemory(&cc, sizeof(cc)); cc.lStructSize = sizeof(cc); cc.hwndOwner = hWnd; cc.lpCustColors = (LPDWORD)acrCustClr; if (ChooseColor(&cc)) { //用选择的颜色画一个实心矩形 RECT rect = {240, 100, 340, 140}; hDC = GetDC(hWnd); HBRUSH hBrush = CreateSolidBrush(cc.rgbResult); SelectObject(hDC, hBrush); FillRect(hDC, &rect, hBrush); DeleteObject(hBrush); ReleaseDC(hWnd, hDC); } } break; case IDC_FONT_DIALOG: { CHOOSEFONT cf; LOGFONT lf; ZeroMemory(&cf, sizeof(cf)); cf.lStructSize = sizeof(cf); cf.hwndOwner = hWnd; cf.lpLogFont = &lf; cf.Flags = CF_SCREENFONTS | CF_EFFECTS; if (ChooseFont(&cf)) { //用选择的字体输出一行测试文本 TCHAR str[] = TEXT("Font 测试!"); HFONT hFont = CreateFontIndirect(cf.lpLogFont); DWORD rgbCurrent = cf.rgbColors; hDC = GetDC(hWnd); SelectObject(hDC, hFont); SetTextColor(hDC, cf.rgbColors); TextOut(hDC, 200, 170, str, _tcslen(str)); DeleteObject(hFont); ReleaseDC(hWnd, hDC); } } break; default: break; } } return 0; case WM_DESTROY: PostQuitMessage(0); return 0 ; } return DefWindowProc (hWnd, message, wParam, lParam); } |
以上demo运行后的文件选择对话框如下:
选择颜色对话框如下:
选择字体对话框如下:
在demo中选择三个对话框后,选择的文件、颜色和字体均画在窗口上:
以上只是演示了文件打开/保存、颜色选择和字体选择对话框,虽然只演示了最简单的功能,但也是最基本、最常用的功能,能满足不少应用需求,更多的函数及用法请参考MSDN,学会查MSDN是Windows平台上开发的必备基础。
更多经验交流可以加入Windows编程讨论QQ群:454398517。
关注微信公众平台:程序员互动联盟(coder_online),你可以第一时间获取原创技术文章,和(java/C/C++/Android/Windows/Linux)技术大牛做朋友,在线交流编程经验,获取编程基础知识,解决编程问题。程序员互动联盟,开发人员自己的家。
转载请注明出处http://www.coderonline.net/?p=1670,谢谢合作!
本站所有文章,除特别注明外,均为本站原创,转载请注明出处来自http://www.coderonline.net/
否则保留追究法律责任的权利!
先推!
嗯,准备试试window的窗口编程,做个小应用