更新时间:2015-06-26 21:42:07浏览次数:1+次
前面讲过了两种风格的文件夹选择对话框的实现方法,见文章《Win7界面的和API实现的老界面文件夹选择对话框代码实现详细讲解》。而老界面的文件夹选择对话框很小,也导致选择很不方便,所以很多人就不喜欢这种对话框了。但是今天讲的定制这种文件夹选择对话框的样式和大小,或许可以大大提升用户体验吧。嘿嘿。
首先来看看实现截图吧,看图说话,有图有真相!
第一张图是横向的,第二张图是纵向的,第三张图是横向纵向都扩大了。对话框中,还增加了编辑框,可以直接输入文件夹路径。选择了文件夹后,会自动更新选中的文件夹路径到编辑框中。看看,效果还不错,下面来看看如何定制,摆脱原始的小小的选择框吧。
实现的原理,其实很简单,就是提供了一个回调函数来进行定制。为什么回调函数容易实现定制,请看文章《函数调用与回调函数的设计原理的深入对比分析》的详细分析。这里就不对回调函数机制详细讨论了。使用回调函数,就是给你有机会定制界面,所以回调函数是一个非常不错的东西哦。而在回调函数中,是对消息BFFM_INITIALIZED进行响应,然后对文件夹选择对话框中的所有子控件进行遍历,然后调整大小和位置,进而实现定制。
下面看看实现的代码:
要使用回调函数定制,那么就要提供回调函数,在文件夹选择对话框的结构体中的成员lpfn传递回调函数地址即可。启动文件夹选择对话框的代码如下:
const TCHAR* lpPath=_T("C:\\Program Files\\");
TCHAR lpTemp[MAX_PATH]={0};// - 存储选中的文件夹路径
BROWSEINFO bi;
memset(&bi, 0, sizeof(bi));
LPITEMIDLIST pItemList;
bi.hwndOwner = m_hWnd;// - 设置拥有者窗口句柄,如果为NULL,相当于非模态窗口
bi.lpszTitle = _T("★C++技术网 提醒★ ?请选择文件夹?");// - 选择文件夹中的提示文字
bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_EDITBOX;
bi.lpfn = BrowseCallbackProc;// - 回调函数,用于定制文件夹选择对话框
bi.lParam=(LPARAM)lpPath;// - 传入默认选中的文件夹
pItemList = SHBrowseForFolder(&bi);
if (pItemList!=NULL)
{
SHGetPathFromIDList(pItemList,lpTemp);// - 得到选中的文件夹路径
}
static int __stdcall BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData);
必须是类静态的,所以要加上static 关键字。其他的格式,都是API规定的格式。在实现回调函数之前,我自定义了一个结构体,用来存储子控件的样式的,存储左右上下边距,宽度和高度。用结构体形式整体存储这些信息,可以简化代码,让逻辑更加清楚。并使用typedef重定义了结构体类型,让使用更加方便。typedef struct ControlLayout
{
int iWidth; // - 宽度
int iHeight; // - 高度
int iMargin_Left; // - 左边距
int iMargin_Right; // - 右边距
int iMargin_Top; // - 上边距
int iMargin_Bottom;// - 下边距
}CTRLLAYOUT;
回调函数的代码实现如下:
int CALLBACK CfolderDlg::BrowseCallbackProc(HWND hwnd,UINT uMsg,LPARAM lParam,LPARAM lpData)
{
CWnd* pMainWnd;
CRect OrgMainClientRect;// - 调整前文件夹对话框客户区矩形
CRect NewMainWndRect;// - 调整后文件夹对话框整个窗口矩形
CWnd* pChildWnd;// - 子窗口指针
TCHAR szClassName[MAX_PATH];// - 控件Windows窗口类类名
CRect TreeRect; // -树控件矩形区域
CRect ButtonRect;// - 按钮控件矩形区域
CTRLLAYOUT TreeLayout={0};// - 树控件样式
CTRLLAYOUT ButtonLayout[2]={0};// - 树控件样式
int iIndex = 0;// - 对按钮数组计数
switch (uMsg)
{
case BFFM_INITIALIZED:
pMainWnd = CWnd::FromHandle(hwnd);// - 根据窗口句柄,获取文件夹选择对话框指针
pMainWnd->GetClientRect(OrgMainClientRect);// - 获取主窗口客户区的大小,即控件放置的区域
pChildWnd = pMainWnd->GetWindow(GW_CHILD); // - 获取子窗口的指针
/* - 循环便利文件夹选择对话框的控件,并存储控件的位置信息 - */
while (pChildWnd != NULL)
{
GetClassName(pChildWnd->m_hWnd, szClassName, MAX_PATH);
if (_tcscmp(_T("SysTreeView32"), szClassName) == 0)
{
/* - 存储树控件样式 - */
pChildWnd->GetWindowRect(TreeRect);
pMainWnd->ScreenToClient(TreeRect);
TreeLayout.iMargin_Left = TreeRect.left;
TreeLayout.iMargin_Top = TreeRect.top;
TreeLayout.iMargin_Right = OrgMainClientRect.right - TreeRect.right;
TreeLayout.iMargin_Bottom = OrgMainClientRect.bottom - TreeRect.bottom;
}
if (_tcscmp(_T("Button"), szClassName) == 0)
{
/* - 存储按钮控件样式 - */
pChildWnd->GetWindowRect(ButtonRect);
pMainWnd->ScreenToClient(ButtonRect);
ButtonLayout[iIndex].iWidth = ButtonRect.Width();
ButtonLayout[iIndex].iHeight = ButtonRect.Height();
ButtonLayout[iIndex].iMargin_Right = OrgMainClientRect.right - ButtonRect.right;
ButtonLayout[iIndex].iMargin_Bottom = OrgMainClientRect.bottom - ButtonRect.bottom;
iIndex++;
}
pChildWnd = pChildWnd->GetNextWindow();
}
/* - 增大文件夹对话框和对话框中的客户区 - */
pMainWnd->GetWindowRect(NewMainWndRect);
OrgMainClientRect.InflateRect(0, 0, 240, 300);
NewMainWndRect.InflateRect(0, 0, 240, 300);
pMainWnd->MoveWindow(NewMainWndRect);
/* - 修改控件大小和位置 - */
iIndex = 0;
pChildWnd = pMainWnd->GetWindow(GW_CHILD);// - 移动主窗口后获取子窗口指针
while (pChildWnd != NULL)
{
GetClassName(pChildWnd->m_hWnd, szClassName, MAX_PATH);
if (_tcscmp(_T("SysTreeView32"), szClassName) == 0)
{
TreeRect.left = TreeLayout.iMargin_Left;
TreeRect.top = TreeLayout.iMargin_Top;
TreeRect.right = OrgMainClientRect.right - TreeLayout.iMargin_Right;
TreeRect.bottom = OrgMainClientRect.bottom - TreeLayout.iMargin_Bottom;
pChildWnd->MoveWindow(TreeRect);
}
if (_tcscmp(_T("Button"), szClassName) == 0)
{
ButtonRect.right = OrgMainClientRect.right - ButtonLayout[iIndex].iMargin_Right;
ButtonRect.bottom = OrgMainClientRect.bottom - ButtonLayout[iIndex].iMargin_Bottom;
ButtonRect.left = ButtonRect.right - ButtonLayout[iIndex].iWidth;
ButtonRect.top = ButtonRect.bottom - ButtonLayout[iIndex].iHeight;
pChildWnd->MoveWindow(ButtonRect);
iIndex++;
}
pChildWnd = pChildWnd->GetNextWindow();
}
pMainWnd->SendMessage(BFFM_SETSELECTION, TRUE, lpData);// - 设置默认选中的文件夹
break;
default:
break;
}
return 0;
}
相关资讯