windowsmfccommon-dialog

using CFileDialog::AddCheckButton fails


OK, I am trying to use CFileDialog::AddCheckButton. The function call succeeds and I'm able to see the new check box. I'm unable to see any events and while I can override OnInitDialog, overriding OnOK is ignored. I'm not sure what I'm doing wrong:

//header

class CTPSaveDialog : public CFileDialog
{
    DECLARE_DYNAMIC(CTPSaveDialog)
    static const CString CTPSaveDialog::m_cstrFilter;
public:
    BOOL m_bForce;
    CTPSaveDialog(
        LPCTSTR lpszDefExt = NULL,
        LPCTSTR lpszFileName = NULL,
        DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
        CWnd* pParentWnd = NULL,
        DWORD dwSize = 0);
    ~CTPSaveDialog();
    virtual BOOL OnInitDialog();
    DECLARE_MESSAGE_MAP()
    afx_msg void OnBnClickedCheckForce();
    virtual void OnOK();
};

// implementation

const CString CTPSaveDialog::m_cstrFilter = "JPEG images (*.jpg)|*.jpg|TIFF Format (*.tif)|*.tif|Windows Bitmap (*.bmp)|*.bmp|Portable Network Graphics (*.png)|*.png|GIF (*.gif)|*.gif||";

IMPLEMENT_DYNAMIC(CTPSaveDialog, CFileDialog)

CTPSaveDialog::CTPSaveDialog(LPCTSTR lpszDefExt, LPCTSTR lpszFileName, DWORD dwFlags, CWnd * pParentWnd, DWORD dwSize) :
    CFileDialog(FALSE, lpszDefExt, lpszFileName, dwFlags, m_cstrFilter, pParentWnd, dwSize, TRUE)
{
    AddCheckButton(IDC_CHK_FORCE, "Force", FALSE);
    m_bForce = FALSE;
    m_ofn.lpstrTitle = "Write Simulation To File";
}

CTPSaveDialog::~CTPSaveDialog()
{
}


BOOL CTPSaveDialog::OnInitDialog()
{
    CFileDialog::OnInitDialog();

    if (GetDlgItem(IDC_CHK_FORCE))
        SendDlgItemMessage(IDC_CHK_FORCE, BM_SETCHECK, m_bForce ? BST_CHECKED : BST_UNCHECKED);
    // TODO:  Add extra initialization here
    return TRUE;  // return TRUE unless you set the focus to a control
                  // EXCEPTION: OCX Property Pages should return FALSE
}

BEGIN_MESSAGE_MAP(CTPSaveDialog, CFileDialog)
    ON_BN_CLICKED(IDC_CHK_FORCE, &CTPSaveDialog::OnBnClickedCheckForce)
END_MESSAGE_MAP()

void CTPSaveDialog::CTPSaveDialog()
{
    m_bForce = !m_bForce;
}

void CTPSaveDialog::OnOK()
{
    // TODO: Add your specialized code here and/or call the base class

    CFileDialog::OnOK();
}

Solution

  • In CFileDialog with Vista style, windows messages are not handled in message map. Instead CFileDialog uses specific virtual functions. You only need to declare and define these functions.

    Use OnCheckButtonToggled to detect if check box is clicked.

    Use OnFileNameOK to detect when file is selected and Open/Save button is clicked.

    Use SetCheckButtonState to set/unset the check button (not SendDlgItemMessage)

    See CFileDialog for all available methods.

    As stated in documentation, OnInitDialog is not supported either:

    Some CFileDialog methods are not supported under Windows Vista or later. Check the individual method topic for information about whether the method is supported. In addition, the following inherited functions are not supported under Windows Vista or later:

    CDialog::OnInitDialog
    ...
    

    Just do the initialization in the constructor or before calling DoModal(), and override these functions:

    class CTPSaveDialog : public CFileDialog
    {
        ...
        virtual void OnCheckButtonToggled(DWORD dwIDCtl, BOOL bChecked);
        virtual BOOL OnFileNameOK();
    };
    
    void CTPSaveDialog::OnCheckButtonToggled(DWORD dwIDCtl, BOOL bChecked)
    {
        if (dwIDCtl == IDC_CHK_FORCE)
            TRACE("Is checked? %d\n", bChecked);
    }
    
    BOOL CTPSaveDialog::OnFileNameOK()
    {
        TRACE("Clicked Open/Save button\n");
    
        //return FALSE to close the dialog
        return FALSE;
    }