在CFileDialog对话框中添加控件.docx
《在CFileDialog对话框中添加控件.docx》由会员分享,可在线阅读,更多相关《在CFileDialog对话框中添加控件.docx(11页珍藏版)》请在冰豆网上搜索。
在CFileDialog对话框中添加控件
在CFileDialog对话框中添加控件
关键字:
CFileDialog扩展类,OFNHookProc
需求描述:
昨天遇到一个用户需求,在CFileDialog对话框(SAVE)中加入一个Check,一个Edit,一个Spin控件,dlg.Domodal()==IDOK返回时要同时获得Edit控件中的数据.
实现方法:
如果只需要控制控件,用方法一即可,但如果需要获取数据,则只能用方法二。
我最终用的就是方法二.
方法一:
首先查找MSDN关于CFileDialog扩展的实现描述,上网查到实现预览图片式的CFILEDIALOG的例子。
按照其思路从CFileDialog派生了一个新的类CFileDialogEX.
在类中添加以下代码
#defineWM_CHECKZOOMINWM_USER+1856
public:
BOOLbZoomIn;
UINTnMul;//[1~100]
//前置声明---------------
BOOLNEARCALLBACKHandleNotify(HWNDhDlg,LPOFNOTIFYpofn);
UINT_PTRCALLBACKOFNHookProc(HWNDhDlg,UINTuMsg,WPARAMwParam,LPARAMlParam);
//CFileDialogEx
IMPLEMENT_DYNAMIC(CFileDialogEx,CFileDialog)
CFileDialogEx:
:
CFileDialogEx(BOOLbOpenFileDialog,LPCTSTRlpszDefExt,LPCTSTRlpszFileName,
DWORDdwFlags,LPCTSTRlpszFilter,CWnd*pParentWnd):
CFileDialog(bOpenFileDialog,lpszDefExt,lpszFileName,dwFlags,lpszFilter,pParentWnd)
{
//这个四个常用标识位
m_ofn.Flags|= OFN_ENABLETEMPLATE|OFN_HIDEREADONLY|OFN_EXPLORER; //OFN_EXPLORER|OFN_ENABLEHOOK
m_ofn.lpstrTitle = _T("高级保存对话框");
m_ofn.hInstance=AfxGetInstanceHandle();
m_ofn.lpstrFilter = _T("*.bmp\0*.BMP\0所有文件\0*.*\0");
m_ofn.lpTemplateName=MAKEINTRESOURCE(IDD_FILEDIALOG_EX);
m_ofn.lpfnHook= (LPOFNHOOKPROC)OFNHookProc;
}
//HookfunctionfortheCommDlg
//在这里处理我们感兴趣的消息,想要哪个,截哪个!
UINT_PTRCALLBACKOFNHookProc(HWNDhDlg,UINTuMsg,WPARAMwParam,LPARAMlParam)
{
switch(uMsg)
{
caseWM_INITDIALOG:
//初始化对话框上的控件
if(SendDlgItemMessage(hDlg,IDC_CHECK_ZOOMIN,BM_GETCHECK,0,0)==BST_UNCHECKED)
{
:
:
EnableWindow(GetDlgItem(hDlg,IDC_EDIT_ZOOMNUM),FALSE);
:
:
EnableWindow(GetDlgItem(hDlg,IDC_SPIN_ZOOMNUM),FALSE);
:
:
SetWindowText(GetDlgItem(hDlg,IDC_EDIT_ZOOMNUM),_T("1"));
//ShowWindow(button,SW_HIDE);
}
break;
caseWM_DESTROY:
//消毁对话框
{
LPOPENFILENAMElpOFN=(LPOPENFILENAME)GetWindowLong(hDlg,DWL_USER);
}
break;
caseWM_COMMAND:
//这里处理,IDC_CHECK_ZOOMIN命令
{
if((HIWORD(wParam)==BN_CLICKED)&&(LOWORD(wParam)==IDC_CHECK_ZOOMIN))
{
BOOLbZoomIn=TRUE;
if(SendDlgItemMessage(hDlg,IDC_CHECK_ZOOMIN,BM_GETCHECK,0,0)==BST_CHECKED)
{
bZoomIn=TRUE;
:
:
EnableWindow(GetDlgItem(hDlg,IDC_EDIT_ZOOMNUM),TRUE);
:
:
EnableWindow(GetDlgItem(hDlg,IDC_SPIN_ZOOMNUM),TRUE);
}
else
{
bZoomIn=FALSE;
//:
:
SetWindowText(GetDlgItem(hDlg,IDC_EDIT_ZOOMNUM),"");
:
:
EnableWindow(GetDlgItem(hDlg,IDC_EDIT_ZOOMNUM),FALSE);
:
:
EnableWindow(GetDlgItem(hDlg,IDC_SPIN_ZOOMNUM),FALSE);
}
HWNDhParent=GetParent(hDlg); //注意hDlg是新加的模板对话框句柄,它是CFileDialog对话框的子部分,要获取CFileDialog对话框的句柄需要用GetParent函数
PostMessage(hParent,WM_CHECKZOOMIN,(WPARAM)bZoomIn,(LPARAM)0);
bZoomIn=FALSE;
}
break;
caseWM_NOTIFY:
HandleNotify(hDlg,(LPOFNOTIFY)lParam);
break;
}
return0;
}
//这里处理notify消息
BOOLNEARCALLBACKHandleNotify(HWNDhDlg,LPOFNOTIFYpofn)
{
CFileDialogExdlg(TRUE);
switch(pofn->hdr.code)
{
caseCDN_SELCHANGE:
{
//charszFile[MAX_PATH];
////Getthepathoftheselectedfile.
//if(CommDlg_OpenSave_GetFilePath(GetParent(hDlg),szFile,sizeof(szFile))<=sizeof(szFile))
//{
// if(GetFileAttributes(szFile)!
= FILE_ATTRIBUTE_DIRECTORY)
// {
// //ShouldweloadthePic
// if(SendDlgItemMessage(hDlg,IDC_CHECK1,BM_GETCHECK,0,0)==BST_UNCHECKED)
// dlg.ShowImagepreview(hDlg,szFile);
// }
//}
}
break;
caseCDN_FILEOK:
{
intnum;
GetDlgItemInt(hDlg,IDC_EDIT_ZOOMNUM,&num,FALSE);
if(SendDlgItemMessage(hDlg,IDC_CHECK_ZOOMIN,BM_GETCHECK,0,0)==BST_CHECKED)
{
dlg.bZoomIn=TRUE;
}
else
dlg.bZoomIn=FALSE;
returnFALSE;
}
break;
}
return(TRUE);
}
原计划从回调函数得到触发消息,然后用PostMessage的方式将自定义的WM_CHECKZOOMIN消息发给主窗口,在主窗口中更新我新加的变量bZoomIn和
nMul的值。
但调试发现我新定义的CFileDialogEX类中的WM_CHECKZOOMIN的消息响应函数总是无法进入。
进一步调式确定消息确实是发送成功了,而且窗口句柄也没有错,但就是进入不了我定义的响应函数。
经过资料查询和思索初步推理:
CFileDialog的消息处理是封闭的,自动的,在没有用钩子的情况下我们是无法将自己的消息函数插入其中并能自己处理的。
从MSDN给的说明也可以看出,它推荐PostMessage传输的也只是系统定义消息如WM_COMMAND,也就是说你可以控制它的控件做某项动作或显示隐藏控件,移动控件的位置。
一切回到了原点,此路不通,继续寻找新的方法!
!
!
!
!
!
方法二:
看到一篇文章.softist./programemo/cfiledialog/cfiledialog.htm,给我指了一条明路
CFileDialog的个性化(VC++)
本文是为标准的文件选择对话框添加控件以扩展它的功能。
为了做到这点,要把CFileDialog类派生,还要准备粘贴控件用的对话框模板,把控件的消息响应入口追加到MESSAGE-MAP中。
例程。
文件选择对话框在选择文本文件时,可以预览这个文件的容。
1.生成对话框模板。
作一个对话框的资源,比如ID为IDD_DIALOG1。
其属性如下设定。
IDD_DIALOG1DIALOGDISCARDABLE0,0,187,128
STYLEWS_CHILD|WS_CLIPSIBLINGS|WS_CLIPCHILDREN
FONT9,"MSSansSerif"
BEGIN
LTEXT"Static",stc32,7,7,173,114
EDITTEXTIDC_EDIT_PREVIEW,7,18,102,30,ES_MULTILINE|
ES_AUTOHSCROLL|ES_WANTRETURN
PUSHBUTTON"Button1",IDC_BUTTON_PREVIEW,143,36,37,23
END
2.追加控件。
首先追加一个ID为stc32的大一点的静态文字控件(Static)。
然后在它的下面,追加预览用的多行编辑框(ID=IDC_EDIT_PREVIEW)和起动预览用的按钮(ID=IDC_BUTTON_PREVIEW)。
3.生成CFileDialog的派生类,比如叫CFileDlg。
为了指定资源ID,追加如下的代码到CFileDlg里。
这个追加还有一个意义,那就是可以用MFC的类精灵工具(MFCClassWizard)来作相应的处理。
//DialogData
//{{AFX_DATA(CFileDlg)
enum{IDD=IDD_DIALOG1};
//}}AFX_DATA
4.把上面生成的对话框模板,安装到CFileDlg的类创建函数里,代码如下。
CFileDlg:
:
CFileDlg(BOOLbOpenFileDialog,...):
CFileDialog(bOpenFileDialog,...)
{
m_ofn.Flags|=dwFlags;
m_ofn.Flags|=OFN_EXPLORER;
m_ofn.Flags|=OFN_ENABLETEMPLATE;
SetTemplate(0,IDD_DIALOG1);
}
5.填写按钮(ID=IDC_BUTTON_PREVIEW)的响应函数。
从CFileDlg类的实体对话框取得文件的全路径,打开文件,把其容显示在编辑框(ID=IDC_EDIT_PREVIEW)上。
voidCFileDlg:
:
OnPreview()
{
CStringstrPathName=GetPathName();
if(strPathName!
="")
{
CFilefile;
file.Open(strPathName,CFile:
:
modeRead);
charbuff[1024];
memset(buff,0,1024);
file.Read(buff,1024);
GetDlgItem(IDC_EDIT_PREVIEW)->SetWindowText(buff);
file.Close();
}
}
6.结果测试。
CFileDlgdlg(TRUE);
dlg.DoModal();
通过指定资源ID,可以使用Wizard添加处理消息,OK这正是我想要的,按照它的方法,很快就实现了需求,调用如下
//.h
//DialogData
//{{AFX_DATA(CFileDlg)
enum{IDD=IDD_FILEDIALOG_EX};
//}}AFX_DATA
public:
BOOLbZoomIn;
UINTnMul;//[1~100]
afx_msgvoidOnBnClickedCheckZoomin();
afx_msgvoidOnDeltaposSpinZoomnum(NMHDR*pNMHDR,LRESULT*pResult);
virtualBOOLOnInitDialog();
afx_msgvoidOnEnChangeEditZoomnum();
afx_msgvoidOnEnKillfocusEditZoomnum();
//.cpp
CFileDialogEx:
:
CFileDialogEx(BOOLbOpenFileDialog,LPCTSTRlpszDefExt,LPCTSTRlpszFileName,
DWORDdwFlags,LPCTSTRlpszFilter,CWnd*pParentWnd):
CFileDialog(bOpenFileDialog,lpszDefExt,lpszFileName,dwFlags,lpszFilter,pParentWnd)
{
//这个四个常用标识位
m_ofn.Flags|= OFN_ENABLETEMPLATE|OFN_HIDEREADONLY|OFN_EXPLORER; //OFN_EXPLORER|OFN_ENABLEHOOK
m_ofn.lpstrTitle = _T("高级保存对话框");
m_ofn.hInstance=AfxGetInstanceHandle();
m_ofn.lpstrFilter = _T("*.bmp\0*.BMP\0所有文件\0*.*\0");
SetTemplate(0,IDD_FILEDIALOG_EX);
}
BEGIN_MESSAGE_MAP(CFileDialogEx,CFileDialog)
//ON_COMMAND()
ON_BN_CLICKED(IDC_CHECK_ZOOMIN,&CFileDialogEx:
:
OnBnClickedCheckZoomin)
ON_NOTIFY(UDN_DELTAPOS,IDC_SPIN_ZOOMNUM,&CFileDialogEx:
:
OnDeltaposSpinZoomnum)
ON_EN_CHANGE(IDC_EDIT_ZOOMNUM,&CFileDialogEx:
:
OnEnChangeEditZoomnum)
ON_EN_KILLFOCUS(IDC_EDIT_ZOOMNUM,&CFileDialogEx:
:
OnEnKillfocusEditZoomnum)
END_MESSAGE_MAP()
voidCFileDialogEx:
:
OnBnClickedCheckZoomin()
{
//TODO:
在此添加控件通知处理程序代码
bZoomIn=!
bZoomIn;
GetDlgItem(IDC_EDIT_ZOOMNUM)->EnableWindow(bZoomIn);
GetDlgItem(IDC_SPIN_ZOOMNUM)->EnableWindow(bZoomIn);
}
voidCFileDialogEx:
:
OnDeltaposSpinZoomnum(NMHDR*pNMHDR,LRESULT*pResult)
{
LPNMUPDOWNpNMUpDown=reinterpret_cast(pNMHDR);
//TODO:
在此添加控件通知处理程序代码
if(pNMUpDown->iDelta>0)
{
if(nMul>1)
nMul--;
}
else
{
if(nMul<=100)
nMul++;
}
wchar_tbuff[10];
_itow(nMul,buff,10);
LPCTSTRlpstr=(LPCTSTR)buff;
GetDlgItem(IDC_EDIT_ZOOMNUM)->SetWindowText(lpstr);
*pResult=0;
}
BOOLCFileDialogEx:
:
OnInitDialog()
{
CFileDialog:
:
OnInitDialog();
//TODO:
在此添加额外的初始化
GetDlgItem(IDC_EDIT_ZOOMNUM)->EnableWindow(FALSE);
GetDlgItem(IDC_SPIN_ZOOMNUM)->EnableWindow(FALSE);
GetDlgItem(IDC_EDIT_ZOOMNUM)->SetWindowText(_T("1"));
bZoomIn=FALSE;
nMul=1;
returnTRUE; //returnTRUEunlessyousetthefocustoacontrol
//异常:
OCX属性页应返回FALSE
}
voidCFileDialogEx:
:
OnEnChangeEditZoomnum()
{
//TODO:
如果该控件是RICHEDIT控件,它将不
//发送此通知,除非重写CFileDialog:
:
OnInitDialog()
//函数并调用CRichEditCtrl().SetEventMask(),
//同时将ENM_CHANGE标志“或”运算到掩码中。
//TODO:
在此添加控件通知处理程序代码
CStringstrText;
GetDlgItem(IDC_EDIT_ZOOMNUM)->GetWindowText(strText);
nMul=_wtoi(strText);
if((nMul<1)||(nMul>100))
{
if(nMul<1)nMul=1;
if(nMul>100)nMul=100;
wchar_tbuff[10];
_itow(nMul,buff,10);
LPCTSTRlpstr=(LPCTSTR)buff;
GetDlgItem(IDC_EDIT_ZOOMNUM)->SetWindowText(lpstr);
}
}
voidCFileDialogEx:
:
OnEnKillfocusEditZoomnum()
{
//TODO:
在此添加控件通知处理程序代码
CStringstrText;
GetDlgItem(I