上一篇我們學習了菜單的基本編程,本篇來了解一下通用對話框的使用。Windows系統之所以是目前最流行的桌面系統,也是因為Windows有一套標准化,統一友好的交互界面,比如菜單、工具欄、狀態欄以及各個控件。當然除了這些單獨的控件之外,對於像文件打開、保存對話框,字體對話,顏色對話框等對於Windows本身會用到,在很多第三方的應用程序中也會用到。因此微軟公司也早就清楚這種現實情況會存在,所以Windows把這種常見的公共對話就做了統一的接口函數,供Windows自己和第三方開發者使用。
Windows提供的公用對話框在不同的版本有所不一樣,但常見的公用對話框有:顏色選擇對話框、打開文件對話框、保存文件對話框、字體選擇對話框、查找對話框、替換對話框、打印對話框以及打印設置對話框等。
本篇以最常見的文件打開/保存對話框、字體對話框、顏色對話框為例,來學習如何創建這些對話框,其他的對話框使用大同小異,且在MSDN上基本都有使用實例。
要使用公用對話框函數,需要包含commdlg.h頭文件,相關的數據結構和函數定義都在該頭文件中定義。
- 文件打開對話框
文件打開對話框主要用於選擇需要的文件,把選擇的文件全路徑名傳給用戶,至於取到文件全路徑之后怎么操作完全是開發者自己決定。也就是說它提供了一個在電腦中選擇任何文件的公共操作接口。API函數定義如下:
BOOL GetOpenFileName(LPOPENFILENAME lpofn);
參數lpofn的定義如下:
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函數定義如下:
BOOL GetSaveFileName(LPOPENFILENAME lpofn);
該函數的參數與上面完全一樣,只是有些不能在文件保存對話框函數中使用,保存文件時不能多選名字。
- 顏色選擇對話框
該對話框函數提供統一接口用於選擇顏色,API函數定義如下:
BOOL ChooseColor(LPCHOOSECOLOR lpcc);
參數lpcc最重要的參數:
lpCustColors,它指向一個包含16個值的數組,該數組包含了對話框中自定義顏色的紅、綠、藍(RGB)值。如果用戶修改這些顏色,系統將用新的顏色值更新這個數組。如果要在多個ChooseColor函數中保存這個新的數組,我們應該為該數組分配靜態內存空間。
rgbResult:該參數保存了選擇的顏色值。
- 字體選擇對話框:
該對話框函數用於瀏覽並選擇字體,包括顏色。API函數定義如下:
BOOL ChooseFont(LPCHOOSEFONT lpcf);
對話框函數運行結束后的字體在rgbColors參數中,我們可以用它來創建選擇的字體。
以上各個結構的其他成員請參考MSDN。
下面我們以一個demo程序演示以上幾種公共對話框的基本用法。
#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/,謝謝合作!





