在CFileDialog对话框中添加控件

摘要:
根据其思想,一个新的类CFileDialogEX是从CFileDialog派生出来的。将以下代码#defineWM添加到class_ CHECKZOOMINWM_ USER+1856public://OFN_EXPLORER|OFN_ENABLEHOOK m_ OFN.lpstrTitle=_T(“高级保存对话框”);

关键字:CFileDialog扩展类 ,OFNHookProc

需求描述 : 昨天遇到一个用户需求,在CFileDialog对话框(SAVE)中加入一个Check , 一个Edit, 一个Spin控件,dlg.Domodal()==IDOK返回时要同时获得Edit控件中的数据.

实现方法: 如果只需要控制控件,用方法一即可,但如果需要获取数据,则只能用方法二。我最终用的就是方法二.

方法一: 首先查找MSDN关于CFileDialog扩展的实现描述,上网查到实现预览图片式的CFILEDIALOG的例子。按照其思路从CFileDialog派生了一个新的类CFileDialogEX.

在类中添加以下代码

#define WM_CHECKZOOMIN WM_USER+1856

public:
    BOOL bZoomIn;
    UINT nMul; //[1~100]

//前置声明---------------
BOOL NEAR CALLBACK HandleNotify(HWND hDlg, LPOFNOTIFY pofn);
UINT_PTR CALLBACK OFNHookProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);

// CFileDialogEx

IMPLEMENT_DYNAMIC(CFileDialogEx, CFileDialog)

CFileDialogEx::CFileDialogEx(BOOL bOpenFileDialog, LPCTSTR lpszDefExt, LPCTSTR lpszFileName,
        DWORD dwFlags, LPCTSTR lpszFilter, 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;   
}

 

//Hook function for the Comm Dlg
//在这里处理我们感兴趣的消息,想要哪个,截哪个!
UINT_PTR CALLBACK OFNHookProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_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;

    case WM_DESTROY:    //消毁对话框
        {
            LPOPENFILENAME lpOFN = (LPOPENFILENAME)GetWindowLong(hDlg, DWL_USER);

        }
        break;

    case WM_COMMAND:   //这里处理,IDC_CHECK_ZOOMIN命令
        {   
        if ((HIWORD(wParam) == BN_CLICKED) && (LOWORD(wParam) == IDC_CHECK_ZOOMIN))
        {
            BOOL bZoomIn = 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);
            }
            HWND hParent = GetParent(hDlg);        // 注意hDlg是新加的模板对话框句柄,它是CFileDialog对话框的子部分,要获取CFileDialog对话框的句柄需要用GetParent函数 
            PostMessage(hParent,WM_CHECKZOOMIN,(WPARAM)bZoomIn,(LPARAM)0);
            bZoomIn = FALSE;
        }

        break;
    case WM_NOTIFY:
        HandleNotify(hDlg, (LPOFNOTIFY)lParam);
        break;
    }
    return 0;
}

//这里处理notify 消息
BOOL NEAR CALLBACK HandleNotify(HWND hDlg, LPOFNOTIFY pofn)
{
    CFileDialogEx dlg(TRUE);
    switch (pofn->hdr.code)
    {
    case CDN_SELCHANGE:
        {
            //char szFile[MAX_PATH];
            //// Get the path of the selected file.
            //if (CommDlg_OpenSave_GetFilePath(GetParent(hDlg), szFile, sizeof(szFile)) <= sizeof(szFile))
            //{

            //    if(GetFileAttributes(szFile) !=  FILE_ATTRIBUTE_DIRECTORY)
            //    {           
            //        //Should we load the Pic
            //        if(SendDlgItemMessage(hDlg, IDC_CHECK1, BM_GETCHECK,0,0) == BST_UNCHECKED)
            //            dlg.ShowImagepreview(hDlg, szFile);   
            //    }
            //}
        }
        break;

    case CDN_FILEOK:
        {           
            int num;
            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;

            return FALSE;
        }
        break;

    }

    return(TRUE);
}

原计划从回调函数得到触发消息,然后用PostMessage的方式将自定义的WM_CHECKZOOMIN消息发给主窗口,在主窗口中更新我新加的变量bZoomIn和

nMul的值。

但调试发现我新定义的CFileDialogEX类中的WM_CHECKZOOMIN的消息响应函数总是无法进入。进一步调式确定消息确实是发送成功了,而且窗口句柄也没有错,但就是进入不了我定义的响应函数。  经过资料查询和思索初步推理: CFileDialog的消息处理是封闭的,自动的,在没有用钩子的情况下我们是无法将自己的消息函数插入其中并能自己处理的。 从MSDN给的说明也可以看出,它推荐PostMessage传输的也只是系统定义消息如WM_COMMAND,也就是说你可以控制它的控件做某项动作或显示隐藏控件,移动控件的位置。

一切回到了原点,此路不通,继续寻找新的方法!!!!!!

 

方法二:看到一篇文章http://www.softist.com/programemo/cfiledialog/cfiledialog.htm,给我指了一条明路

CFileDialog的个性化(VC++)

本文是为标准的文件选择对话框添加控件以扩展它的功能。为了做到这点,要把CFileDialog类派生,还要准备粘贴控件用的对话框模板,把控件的消息响应入口追加到MESSAGE-MAP中。

例程。文件选择对话框在选择文本文件时,可以预览这个文件的内容。

1.生成对话框模板。作一个对话框的资源,比如ID为IDD_DIALOG1。其属性如下设定。

IDD_DIALOG1 DIALOG DISCARDABLE  0, 0, 187, 128
STYLE WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN
FONT 9, "MS Sans Serif"
BEGIN
    LTEXT           "Static",stc32,7,7,173,114
    EDITTEXT        IDC_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的类精灵工具(MFC ClassWizard)来作相应的处理。

// Dialog Data
    //{{AFX_DATA(CFileDlg)
    enum { IDD = IDD_DIALOG1 };
    //}}AFX_DATA

4.把上面生成的对话框模板,安装到CFileDlg的类创建函数里,代码如下。

CFileDlg::CFileDlg(BOOL bOpenFileDialog, ...) : 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)上。

void CFileDlg::OnPreview()
{
    CString strPathName = GetPathName();
    if (strPathName != "")
    {
        CFile file;
        file.Open(strPathName, CFile::modeRead);
        char buff[1024];
        memset(buff, 0, 1024);
        file.Read(buff, 1024);
        GetDlgItem(IDC_EDIT_PREVIEW)->SetWindowText(buff);
        file.Close();
    }
}

6.结果测试。

CFileDlg dlg(TRUE);
dlg.DoModal();

 

通过指定资源ID , 可以使用Wizard添加处理消息, OK 这正是我想要的, 按照它的方法,很快就实现了需求,调用如下

//.h

// Dialog Data
//{{AFX_DATA(CFileDlg)
enum { IDD = IDD_FILEDIALOG_EX };
//}}AFX_DATA

public:
    BOOL bZoomIn;
    UINT nMul; //[1~100]

afx_msg void OnBnClickedCheckZoomin();
afx_msg void OnDeltaposSpinZoomnum(NMHDR *pNMHDR, LRESULT *pResult);
virtual BOOL OnInitDialog();
afx_msg void OnEnChangeEditZoomnum();
afx_msg void OnEnKillfocusEditZoomnum();

 

//.cpp

CFileDialogEx::CFileDialogEx(BOOL bOpenFileDialog, LPCTSTR lpszDefExt, LPCTSTR lpszFileName,
        DWORD dwFlags, LPCTSTR lpszFilter, 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()

void CFileDialogEx::OnBnClickedCheckZoomin()
{
    // TODO: 在此添加控件通知处理程序代码
    bZoomIn = !bZoomIn;
    GetDlgItem(IDC_EDIT_ZOOMNUM)->EnableWindow(bZoomIn);
    GetDlgItem(IDC_SPIN_ZOOMNUM)->EnableWindow(bZoomIn);
}

void CFileDialogEx::OnDeltaposSpinZoomnum(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
    // TODO: 在此添加控件通知处理程序代码
    if (pNMUpDown->iDelta > 0)
    {
        if (nMul > 1)
            nMul--;
    }
    else
    {
        if (nMul <= 100)
            nMul++;
    }

    wchar_t buff[10];       
    _itow( nMul, buff, 10 );
    LPCTSTR lpstr = (LPCTSTR)buff;

    GetDlgItem(IDC_EDIT_ZOOMNUM)->SetWindowText(lpstr);
    *pResult = 0;
}

BOOL CFileDialogEx::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;
    return TRUE;  // return TRUE unless you set the focus to a control
    // 异常: OCX 属性页应返回 FALSE
}

void CFileDialogEx::OnEnChangeEditZoomnum()
{
    // TODO:  如果该控件是 RICHEDIT 控件,它将不
    // 发送此通知,除非重写 CFileDialog::OnInitDialog()
    // 函数并调用 CRichEditCtrl().SetEventMask(),
    // 同时将 ENM_CHANGE 标志“或”运算到掩码中。

    // TODO:  在此添加控件通知处理程序代码
    CString strText;
    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_t buff[10];       
        _itow( nMul, buff, 10 );
        LPCTSTR lpstr = (LPCTSTR)buff;

        GetDlgItem(IDC_EDIT_ZOOMNUM)->SetWindowText(lpstr);
    }

}

void CFileDialogEx::OnEnKillfocusEditZoomnum()
{
    // TODO: 在此添加控件通知处理程序代码
    CString strText;
    GetDlgItem(IDC_EDIT_ZOOMNUM)->GetWindowText(strText);

    nMul = _wtoi(strText);   
}

// 调用实现代码

CString szFilter1 = _T("保存图象文件(*.bmp)|*.bmp;|所有文件(*.*)|*.*||");
CFileDialogEx dlg(FALSE, _T(".bmp"), NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,szFilter1);

if (dlg.DoModal()==IDOK)
        {
            CComBSTR str=dlg.GetPathName();
            if (!dlg.bZoomIn)
            {                            }
            else
            {   float Magnification = dlg.nMul;}

         }

免责声明:文章转载自《在CFileDialog对话框中添加控件》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Linux服务器丢包故障的解决python 读取串口数据常用函数及实例分析下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

wtl学习总结

在windows平台,相比MFC,我更喜欢WTL,因其简洁漂亮。所以陆续花了一年的时间学习之,这里总结一下(在学习Wtl/Atl之前,最好是对WinApi编程有一定的了解)。 安装         Wtl主页 http://sourceforge.net/projects/wtl/ ,整个库就是一堆.h文件,官方没有提供Installer,下载后解压到某...

全局消息钩子

钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的。当消息到达后,在目标窗口处理函数之前处理它。钩子机制允许应用程序截获处理window消息或特定事件。钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。每当特定的消息发出,在没有到达目的窗口前,钩子程...

使用事件和消息队列实现分布式事务(转+补充)

虽然本文并非笔者原创,但是我们在非强依赖的事务中原理上也是采用这种方式处理的,不过因为没有仔细去总结,最近在整理和总结时看到了,故转载并做部分根据我们实际情况的完善和补充。 不同于单一架构应用(Monolith), 分布式环境下, 进行事务操作将变得困难, 因为分布式环境通常会有多个数据源, 只用本地数据库事务难以保证多个数据源数据的一致性. 这种情况下,...

Android 对话框弹出位置和透明度的设置

在Android中 我们经常会用AlertDialog来显示对话框。通过这个对话框是显示在屏幕中心的。但在某些程序中,要求对话框可以显示在不同的位置。例如,屏幕的上 方或下方。要实现这种效果。就需要获得对话框的Window对象,获得这个Window对象有多种方法。最容易的就是直接通过AlertDialog类的 getWindow方法来获得Window对象。...

javascript console

javascript console console.log(object[, object, ...])在控制台输出一条消息。如果有多个参数,输出时会用空格隔开这些参数。 第一个参数可以是一个包含格式化占位符输出的字符串,例如: console.log("The %s jumped over %d tall buildings", animal, co...

PHP(Mysql/Redis)消息队列的介绍及应用场景案例

在进行网站设计的时候,有时候会遇到给用户大量发送短信,或者订单系统有大量的日志需要记录,还有做秒杀设计的时候,服务器无法承受这种瞬间的压力,无法正常处理,咱们怎么才能保证系统正常有效的运行呢?这时候我们就要引用消息队列来实现这类的需求,这时候就需要一个中间的系统进行分流和解压。消息队列就是一个中间件,需要配合其他合理使用。  消息队列的概念、原理和场景 本...