标签:
前面讲过了两种个性的文件夹挑选对话框的完成办法,见文章《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);// - 得到选中的文件夹途径
}
代码阐明:
代码中的注释已经写的很明白了,每一步根本都标明白了,所以不多解说了。要说一下的即是BROWSEINFO
构造体。此构造体用于对文件夹挑选对话框传递各种参数,包含定制界面的回调函数。构造体的成员ulFlags
能够运用多个标识组合起来运用,完成对界面的定制。BIF_EDITBOX即是多出来的编辑框。BIF_RETURNONLYFSDIRS表明只返回文件
夹。这些标识有很多,详细的就要自个查MSDN了,里边说的很明白,我就不重复解说,仅仅通知你办法,你要自个动手去查去学习。
SHBrowseForFolder即是发动文件夹挑选对话框的Shell函数。履行完后,然后判断是不是成功,然后调用
SHGetPathFromIDList得到文件夹列表中挑选的文件夹,存入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;
}
代码阐明:
每一句代码的注释根本很明白。这儿说一下全部的流程思路原理。回调函数只对BFFM_INITIALIZED音讯进行呼应,也即是只在初始化文件夹挑选对话框时对对话框进行定制即可,别的音讯就不用管了。
运用TreeLayout存储文件夹树巨细和规划(相对方位),运用ButtonLayout数组存储两个按钮的巨细和规划。运用传进来的文件夹挑选对话框句柄得到主窗口指针,然后获取子窗口和客户区。文件夹挑选对话框的构造是这样的:全部窗口作为父窗口,窗口中的每一个控件作为子窗口。要对这些子窗口进行修正,则要对子窗口进行遍历,
调用GetWindow(GW_CHILD)获取榜首个子窗口,然后调用GetNextWindow()获取后边的子窗口,直到
GetNextWindow()获取的子窗口指针为NULL停止。依据对应的控件类,存储对应的规划。再遍历一次,对控件进行调整,当然,如果要图省事,
也能够一次性修正好,也是能够的。这儿仅仅给出参阅代码,能够在此基础上优化。InflateRect()函数是对矩形进行拓展,参数为正,则拓展矩形,为负数则减小矩形。详细的请检查MSDN的解说。最终发送一个音讯设置默许选中的文件夹。深圳丝足
标签:
原文地址:http://www.cnblogs.com/bmxuhang/p/4388901.html