Windows编程系列:通用对话框

打开文件对话框

打开文件对话框,主要用到GetOpenFileName函数,参数为指向OPENFILENAME结构体的指针

 

1 BOOL GetOpenFileName(
2   LPOPENFILENAME Arg1
3 );

 

使用方法如下:

 1 #include <windows.h>
 2 #include<iostream>
 3 
 4 int main()
 5 {
 6     OPENFILENAME ofn{};
 7     TCHAR szFile[260]{};       //文件名缓冲区
 8 
 9     ofn.lStructSize = sizeof(ofn);
10     ofn.hwndOwner = NULL; //设置对话框拥有者句柄
11     ofn.lpstrFile = szFile; //设置文件名缓冲区
12     ofn.lpstrFile[0] = '\0'; 
13     ofn.nMaxFile = sizeof(szFile); //设置所选文件路径缓冲区最大长度
14     ofn.lpstrFilter = L"全部文件\0*.*\0文本文件\0*.txt\0";  //指定文件类型
15     ofn.nFilterIndex = 1;  //文件类型选中的索引 从1开始
16     ofn.lpstrFileTitle = NULL;  //选中的文件名(不包含路径,包含扩展名)
17     ofn.nMaxFileTitle = 0;  //选中的文件名缓冲区最大长度
18     ofn.lpstrInitialDir = NULL;  //初始路径
19     ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; //用于初始化对话框的标志位 
20 
21 
22     if (GetOpenFileName(&ofn) == TRUE)
23         std::wcout << ofn.lpstrFile << std::endl;
24 }

 

 

保存文件对话框

保存文件对话框和打开文件对话框的使用差不多,只需要把GetOpenFileName换成GetSaveFileName即可。

 

 1 #include <windows.h>
 2 #include<iostream>
 3 
 4 int main()
 5 {
 6     OPENFILENAME ofn{};
 7     TCHAR szFile[260]{};       //文件名缓冲区
 8 
 9     ofn.lStructSize = sizeof(ofn);
10     ofn.hwndOwner = NULL; //设置对话框拥有者句柄
11     ofn.lpstrFile = szFile; //设置文件名缓冲区
12     ofn.lpstrFile[0] = '\0'; 
13     ofn.nMaxFile = sizeof(szFile); //设置所选文件路径缓冲区最大长度
14     ofn.lpstrFilter = L"全部文件\0*.*\0文本文件\0*.txt\0";  //指定文件类型
15     ofn.nFilterIndex = 1;  //文件类型选中的索引 从1开始
16     ofn.lpstrFileTitle = NULL;  //选中的文件名(不包含路径,包含扩展名)
17     ofn.nMaxFileTitle = 0;  //选中的文件名缓冲区最大长度
18     ofn.lpstrInitialDir = NULL;  //初始路径
19     ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; //用于初始化对话框的标志位 
20 
21 
22     if (GetSaveFileName(&ofn) == TRUE)
23         std::wcout << ofn.lpstrFile << std::endl;
24 }

 

选择文件夹对话框

 1 #include <iostream>
 2 #include<Windows.h>
 3 #include<shlobj_core.h>
 4 
 5 int main()
 6 {
 7     TCHAR szBuffer[MAX_PATH]{};
 8     BROWSEINFO bi{};
 9     bi.hwndOwner = ::GetForegroundWindow(); //对话框的拥有者名柄
10     bi.pszDisplayName = szBuffer;  //设置选中路径缓冲区
11     bi.pidlRoot = NULL; //默认选中的根路径
12     bi.lpszTitle = L"标题";  //标题
13     bi.ulFlags = BIF_NEWDIALOGSTYLE;  //对话框的选项
14 
15     LPITEMIDLIST idl = SHBrowseForFolder(&bi);  //显示对话框,并获取快捷方式
16 
17     if (NULL == idl)
18     {
19         return 0;
20     }
21 
22     SHGetPathFromIDList(idl, szBuffer);   //从快捷方式获取路径
23     std::wcout << szBuffer << std::endl;
24 
25     return 0;
26 }

 

 

字体选择对话框

选择字体对话框主要用到ChooseFont函数,参数为指向CHOOSEFONTA结构体的指针。

 

1 BOOL WINAPI ChooseFont(
2   _Inout_ LPCHOOSEFONT lpcf
3 );

 

使用方法如下:

 1     CHOOSEFONT cf{};
 2     static LOGFONT lf{};        // 逻辑字体结构
 3     static DWORD rgbCurrent = 0;  // 当前字体颜色
 4     HFONT hfont;
 5 
 6     cf.lStructSize = sizeof(cf);
 7     cf.hwndOwner = NULL;
 8     cf.lpLogFont = &lf;  //指向一个逻辑 字体
 9     cf.rgbColors = rgbCurrent;
10     cf.Flags = CF_SCREENFONTS | CF_EFFECTS; //设置字体对话框选项
11 
12     if (ChooseFont(&cf) == TRUE)
13     {
14         hfont = CreateFontIndirect(cf.lpLogFont);  //创建逻辑字体
15         rgbCurrent = cf.rgbColors;  //保存字体颜色
16     }

 

颜色选择对话框

颜色选择对话框主要用到ChooseColor函数,参数为指向CHOOSECOLOR 结构体的指针。

 

1 BOOL WINAPI ChooseColor(
2   _Inout_ LPCHOOSECOLOR lpcc
3 );

 

使用方法如下:

 1 #include <windows.h>
 2 #include<iostream>
 3 
 4 int main()
 5 {
 6     CHOOSECOLOR cc{};
 7     static COLORREF acrCustClr[16]; //颜色对话框下面的16个自定义颜色存储空间
 8     HBRUSH hbrush;                
 9     static COLORREF rgbCurrent = 0;
10 
11     cc.lStructSize = sizeof(cc);
12     cc.hwndOwner = NULL;
13     cc.lpCustColors = (LPDWORD)acrCustClr;  
14     cc.rgbResult = rgbCurrent;
15     cc.Flags = CC_FULLOPEN | CC_RGBINIT;
16 
17     if (ChooseColor(&cc) == TRUE)
18     {
19         hbrush = CreateSolidBrush(cc.rgbResult);
20         rgbCurrent = cc.rgbResult;
21     }
22 }

 

打印对话框

打印对话框主要用到PrintDlg函数,参数为指向PRINTDLG结构体的指针。

1 BOOL WINAPI PrintDlg(
2   _Inout_ LPPRINTDLG lppd
3 );

 

使用方法如下:

 1 PRINTDLG pd{};
 2     
 3     pd.lStructSize = sizeof(pd);
 4     pd.hwndOwner = NULL;
 5     pd.hDevMode = NULL;
 6     pd.hDevNames = NULL;
 7     pd.Flags = PD_USEDEVMODECOPIESANDCOLLATE || PD_RETURNDC;
 8     pd.nCopies = 1;        //设置打印份数
 9     pd.nFromPage = 0xFFFF; //设置打印起始页号
10     pd.nToPage = 0xFFFF;   //设置打印结束页号
11     pd.nMinPage = 1;
12     pd.nMaxPage = 0xFFFF;
13 
14     if (PrintDlg(&pd) == TRUE)
15     {
16         //打印操作
17 
18         //释放dc
19         DeleteDC(pd.hDC);
20     }

 

 

打印属性页对话框(打印对话框增强版)

主要用到PrintDlgEx函数,参数为指向PRINTDLGEX结构体的指针。

1 HRESULT WINAPI PrintDlgEx(
2   _Inout_ LPPRINTDLGEX lppd
3 );

 

使用方法:

 1 #include <windows.h>
 2 #include<iostream>
 3 
 4 int main()
 5 {
 6     HRESULT hResult;
 7     PRINTDLGEX pdx = { 0 };
 8     LPPRINTPAGERANGE pPageRanges = NULL;
 9 
10     //分配PRINTPAGERANGE结构体数组内存
11     pPageRanges = (LPPRINTPAGERANGE)GlobalAlloc(GPTR, 10 * sizeof(PRINTPAGERANGE));
12 
13     if (!pPageRanges)
14         return 0;
15 
16     // 初始化PRINTDLGEX结构体
17     pdx.lStructSize = sizeof(PRINTDLGEX);
18     pdx.hwndOwner = GetConsoleWindow();  //拥有者窗体句柄 不能为NULL (这里使用控制台程序测试,所以传入控制台窗体句柄)
19     pdx.hDevMode = NULL;   
20     pdx.hDevNames = NULL;
21     pdx.hDC = NULL;     //设备上下文句柄
22     pdx.Flags = PD_RETURNDC | PD_COLLATE;
23     pdx.Flags2 = 0;
24     pdx.ExclusionFlags = 0;
25     pdx.nPageRanges = 0;
26     pdx.nMaxPageRanges = 10;
27     pdx.lpPageRanges = pPageRanges;
28     pdx.nMinPage = 1;
29     pdx.nMaxPage = 1000;
30     pdx.nCopies = 1;
31     pdx.hInstance = 0;
32     pdx.lpPrintTemplateName = NULL;
33     pdx.lpCallback = NULL;
34     pdx.nPropertyPages = 0;
35     pdx.lphPropertyPages = NULL;
36     pdx.nStartPage = START_PAGE_GENERAL; 
37     pdx.dwResultAction = 0;
38 
39     hResult = PrintDlgEx(&pdx);
40 
41     if ((hResult == S_OK) && pdx.dwResultAction == PD_RESULT_PRINT)
42     {
43         //打印操作
44     }
45 
46     //资源释放
47     if (pdx.hDevMode != NULL)
48         GlobalFree(pdx.hDevMode);
49     if (pdx.hDevNames != NULL)
50         GlobalFree(pdx.hDevNames);
51     if (pdx.lpPageRanges != NULL)
52         GlobalFree(pPageRanges);
53 
54     //删除dc
55     if (pdx.hDC != NULL)
56         DeleteDC(pdx.hDC);
57 
58     return 0;
59 }

 

 

页面设置对话框

页面设置对话框主要用到PageSetupDlg函数,参数为指向PAGESETUPDLG结构体的指针。

1 BOOL WINAPI PageSetupDlg(
2   _Inout_ LPPAGESETUPDLG lppsd
3 );

 

这里在进行页面预览时,需要设置一个钩子函数,用于对页面进行绘制。如下:

 1 UINT_PTR CALLBACK PaintHook(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
 2 {
 3     LPRECT lprc;
 4     COLORREF crMargRect;
 5     HDC hdc, hdcOld;
 6 
 7     switch (uMsg)
 8     {        
 9     case WM_PSD_MARGINRECT:
10         hdc = (HDC)wParam;
11         lprc = (LPRECT)lParam;
12 
13         // 获取系统High light颜色
14         crMargRect = GetSysColor(COLOR_HIGHLIGHT);
15 
16         //创建系统突出显示颜色的点划线笔,然后将其选择到示例页面的DC中。
17         hdcOld = (HDC)SelectObject(hdc, CreatePen(PS_DASHDOT, 1, crMargRect));
18 
19         //绘制Rectangle
20         Rectangle(hdc, lprc->left, lprc->top, lprc->right, lprc->bottom);
21 
22         //还原dc
23         SelectObject(hdc, hdcOld);
24         return TRUE;
25 
26     default:
27         return FALSE;
28     }
29     return TRUE;
30 }

 

使用方法:

 1 PAGESETUPDLG psd{};   
 2 
 3     psd.lStructSize = sizeof(psd);
 4     psd.hwndOwner = GetConsoleWindow(); // 演示使用控制台窗体
 5     psd.hDevMode = NULL; 
 6     psd.hDevNames = NULL; 
 7     psd.Flags = PSD_INTHOUSANDTHSOFINCHES | PSD_MARGINS |
 8         PSD_ENABLEPAGEPAINTHOOK;
 9     psd.rtMargin.top = 1000;
10     psd.rtMargin.left = 1250;
11     psd.rtMargin.right = 1250;
12     psd.rtMargin.bottom = 1000;
13     psd.lpfnPagePaintHook = PaintHook;
14 
15     if (PageSetupDlg(&psd) == TRUE)
16     {
17         //获取纸张尺寸和边距值。
18         
19     }

 

 有趣的是,按照MSDN文档上的说明,上述部分函数已经不推荐使用了。但在最新的.NET 5中,依旧使用了这些函数。

推荐阅读:

GetOpenFileName API

https://docs.microsoft.com/en-us/windows/win32/api/commdlg/nf-commdlg-getopenfilenamea

SHBrowseForFolder

https://docs.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shbrowseforfoldera

ChooseFont API

https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms646914(v=vs.85)

ChooseColor API

https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms646912(v=vs.85)

PrintDlgEx API

https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms646942(v=vs.85)

posted @ 2020-11-18 12:35  zhaotianff  阅读(879)  评论(0编辑  收藏  举报