码迷,mamicode.com
首页 > 其他好文 > 详细

定制文件夹选择对话框的样式和大小实现方法

时间:2015-04-03 01:30:11      阅读:184      评论:0      收藏:0      [点我收藏+]

标签:

前面讲过了两种个性的文件夹挑选对话框的完成办法,见文章《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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!