打开文件对话框
打开文件对话框,主要用到GetOpenFileName函数,参数为指向OPENFILENAME结构体的指针
BOOL GetOpenFileName(
LPOPENFILENAME Arg1
);
使用方法如下:
#include <windows.h>
#include<iostream>
int main()
{
OPENFILENAME ofn{};
TCHAR szFile[260]{}; //文件名缓冲区
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = NULL; //设置对话框拥有者句柄
ofn.lpstrFile = szFile; //设置文件名缓冲区
ofn.lpstrFile[0] = '\0';
ofn.nMaxFile = sizeof(szFile); //设置所选文件路径缓冲区最大长度
ofn.lpstrFilter = L"全部文件\0*.*\0文本文件\0*.txt\0"; //指定文件类型
ofn.nFilterIndex = 1; //文件类型选中的索引 从1开始
ofn.lpstrFileTitle = NULL; //选中的文件名(不包含路径,包含扩展名)
ofn.nMaxFileTitle = 0; //选中的文件名缓冲区最大长度
ofn.lpstrInitialDir = NULL; //初始路径
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; //用于初始化对话框的标志位
if (GetOpenFileName(&ofn) == TRUE)
std::wcout << ofn.lpstrFile << std::endl;
}
保存文件对话框和打开文件对话框的使用差不多,只需要把GetOpenFileName换成GetSaveFileName即可。
#include <windows.h>
#include<iostream>
int main()
{
OPENFILENAME ofn{};
TCHAR szFile[260]{}; //文件名缓冲区
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = NULL; //设置对话框拥有者句柄
ofn.lpstrFile = szFile; //设置文件名缓冲区
ofn.lpstrFile[0] = '\0';
ofn.nMaxFile = sizeof(szFile); //设置所选文件路径缓冲区最大长度
ofn.lpstrFilter = L"全部文件\0*.*\0文本文件\0*.txt\0"; //指定文件类型
ofn.nFilterIndex = 1; //文件类型选中的索引 从1开始
ofn.lpstrFileTitle = NULL; //选中的文件名(不包含路径,包含扩展名)
ofn.nMaxFileTitle = 0; //选中的文件名缓冲区最大长度
ofn.lpstrInitialDir = NULL; //初始路径
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; //用于初始化对话框的标志位
if (GetSaveFileName(&ofn) == TRUE)
std::wcout << ofn.lpstrFile << std::endl;
}
选择文件夹对话框
#include <iostream>
#include<Windows.h>
#include<shlobj_core.h>
int main()
{
TCHAR szBuffer[MAX_PATH]{};
BROWSEINFO bi{};
bi.hwndOwner = ::GetForegroundWindow(); //对话框的拥有者名柄
bi.pszDisplayName = szBuffer; //设置选中路径缓冲区
bi.pidlRoot = NULL; //默认选中的根路径
bi.lpszTitle = L"标题"; //标题
bi.ulFlags = BIF_NEWDIALOGSTYLE; //对话框的选项
LPITEMIDLIST idl = SHBrowseForFolder(&bi); //显示对话框,并获取快捷方式
if (NULL == idl)
{
return 0;
}
SHGetPathFromIDList(idl, szBuffer); //从快捷方式获取路径
std::wcout << szBuffer << std::endl;
return 0;
}
字体选择对话框
选择字体对话框主要用到ChooseFont函数,参数为指向CHOOSEFONTA结构体的指针。
BOOL WINAPI ChooseFont(
_Inout_ LPCHOOSEFONT lpcf
);
使用方法如下:
CHOOSEFONT cf{};
static LOGFONT lf{}; // 逻辑字体结构
static DWORD rgbCurrent = 0; // 当前字体颜色
HFONT hfont;
cf.lStructSize = sizeof(cf);
cf.hwndOwner = NULL;
cf.lpLogFont = &lf; //指向一个逻辑 字体
cf.rgbColors = rgbCurrent;
cf.Flags = CF_SCREENFONTS | CF_EFFECTS; //设置字体对话框选项
if (ChooseFont(&cf) == TRUE)
{
hfont = CreateFontIndirect(cf.lpLogFont); //创建逻辑字体
rgbCurrent = cf.rgbColors; //保存字体颜色
}
颜色选择对话框
颜色选择对话框主要用到ChooseColor函数,参数为指向CHOOSECOLOR 结构体的指针。
BOOL WINAPI ChooseColor(
_Inout_ LPCHOOSECOLOR lpcc
);
#include <windows.h>
#include<iostream>
int main()
{
CHOOSECOLOR cc{};
static COLORREF acrCustClr[16]; //颜色对话框下面的16个自定义颜色存储空间
HBRUSH hbrush;
static COLORREF rgbCurrent = 0;
cc.lStructSize = sizeof(cc);
cc.hwndOwner = NULL;
cc.lpCustColors = (LPDWORD)acrCustClr;
cc.rgbResult = rgbCurrent;
cc.Flags = CC_FULLOPEN | CC_RGBINIT;
if (ChooseColor(&cc) == TRUE)
{
hbrush = CreateSolidBrush(cc.rgbResult);
rgbCurrent = cc.rgbResult;
}
}
打印对话框
打印对话框主要用到PrintDlg函数,参数为指向PRINTDLG结构体的指针。
BOOL WINAPI PrintDlg(
_Inout_ LPPRINTDLG lppd
);
PRINTDLG pd{};
pd.lStructSize = sizeof(pd);
pd.hwndOwner = NULL;
pd.hDevMode = NULL;
pd.hDevNames = NULL;
pd.Flags = PD_USEDEVMODECOPIESANDCOLLATE || PD_RETURNDC;
pd.nCopies = 1; //设置打印份数
pd.nFromPage = 0xFFFF; //设置打印起始页号
pd.nToPage = 0xFFFF; //设置打印结束页号
pd.nMinPage = 1;
pd.nMaxPage = 0xFFFF;
if (PrintDlg(&pd) == TRUE)
{
//打印操作
//释放dc
DeleteDC(pd.hDC);
}
主要用到PrintDlgEx函数,参数为指向PRINTDLGEX结构体的指针。
HRESULT WINAPI PrintDlgEx(
_Inout_ LPPRINTDLGEX lppd
);
#include <windows.h>
#include<iostream>
int main()
{
HRESULT hResult;
PRINTDLGEX pdx = { 0 };
LPPRINTPAGERANGE pPageRanges = NULL;
//分配PRINTPAGERANGE结构体数组内存
pPageRanges = (LPPRINTPAGERANGE)GlobalAlloc(GPTR, 10 * sizeof(PRINTPAGERANGE));
if (!pPageRanges)
return 0;
// 初始化PRINTDLGEX结构体
pdx.lStructSize = sizeof(PRINTDLGEX);
pdx.hwndOwner = GetConsoleWindow(); //拥有者窗体句柄 不能为NULL (这里使用控制台程序测试,所以传入控制台窗体句柄)
pdx.hDevMode = NULL;
pdx.hDevNames = NULL;
pdx.hDC = NULL; //设备上下文句柄
pdx.Flags = PD_RETURNDC | PD_COLLATE;
pdx.Flags2 = 0;
pdx.ExclusionFlags = 0;
pdx.nPageRanges = 0;
pdx.nMaxPageRanges = 10;
pdx.lpPageRanges = pPageRanges;
pdx.nMinPage = 1;
pdx.nMaxPage = 1000;
pdx.nCopies = 1;
pdx.hInstance = 0;
pdx.lpPrintTemplateName = NULL;
pdx.lpCallback = NULL;
pdx.nPropertyPages = 0;
pdx.lphPropertyPages = NULL;
pdx.nStartPage = START_PAGE_GENERAL;
pdx.dwResultAction = 0;
hResult = PrintDlgEx(&pdx);
if ((hResult == S_OK) && pdx.dwResultAction == PD_RESULT_PRINT)
{
//打印操作
}
//资源释放
if (pdx.hDevMode != NULL)
GlobalFree(pdx.hDevMode);
if (pdx.hDevNames != NULL)
GlobalFree(pdx.hDevNames);
if (pdx.lpPageRanges != NULL)
GlobalFree(pPageRanges);
//删除dc
if (pdx.hDC != NULL)
DeleteDC(pdx.hDC);
return 0;
}
页面设置对话框
页面设置对话框主要用到PageSetupDlg函数,参数为指向PAGESETUPDLG结构体的指针。
BOOL WINAPI PageSetupDlg(
_Inout_ LPPAGESETUPDLG lppsd
);
这里在进行页面预览时,需要设置一个钩子函数,用于对页面进行绘制。如下:
UINT_PTR CALLBACK PaintHook(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LPRECT lprc;
COLORREF crMargRect;
HDC hdc, hdcOld;
switch (uMsg)
{
case WM_PSD_MARGINRECT:
hdc = (HDC)wParam;
lprc = (LPRECT)lParam;
// 获取系统High light颜色
crMargRect = GetSysColor(COLOR_HIGHLIGHT);
//创建系统突出显示颜色的点划线笔,然后将其选择到示例页面的DC中。
hdcOld = (HDC)SelectObject(hdc, CreatePen(PS_DASHDOT, 1, crMargRect));
//绘制Rectangle
Rectangle(hdc, lprc->left, lprc->top, lprc->right, lprc->bottom);
//还原dc
SelectObject(hdc, hdcOld);
return TRUE;
default:
return FALSE;
}
return TRUE;
}
PAGESETUPDLG psd{};
psd.lStructSize = sizeof(psd);
psd.hwndOwner = GetConsoleWindow(); // 演示使用控制台窗体
psd.hDevMode = NULL;
psd.hDevNames = NULL;
psd.Flags = PSD_INTHOUSANDTHSOFINCHES | PSD_MARGINS |
PSD_ENABLEPAGEPAINTHOOK;
psd.rtMargin.top = 1000;
psd.rtMargin.left = 1250;
psd.rtMargin.right = 1250;
psd.rtMargin.bottom = 1000;
psd.lpfnPagePaintHook = PaintHook;
if (PageSetupDlg(&psd) == TRUE)
{
//获取纸张尺寸和边距值。
}
有趣的是,按照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)