Clicking in an MFC edit box

c++, mfc, windows

Solution

Alright Mr. Lister I guess I'll add an answer.

First off I would preface this with I would probably simply add a button name "..." to launch the file dialog to the right of the edit box for opening the file dialog as that's the simplest solution and what most windows users will expect.

Another option however is to extend an MFC control. When deciding to extend a control you want to pick one that mostly has the desired behavior and that has a virtual destructor which lends itself to being a subclass. Since you want button like behavior `CButton` may be a good choice.

Your class interface might look something like this:

class CPathButton : public CButton
{
public:
    enum { ID /*= IDC_BUTTON1*/ };

    const CString GetPath() const;
    const CString GetFileName() const;
    const CString GetDirectory() const;
    const CString GetExtension() const;
    // other useful methods for setting file filters etc

protected:
    // add ON_CONTROL(BN_CLICKED, ID, &OnClick) or ON_BN_CLICKED(ID, &OnClick)
    DECLARE_MESSAGE_MAP()

    // CFileDialog fdlg.DoModal(), m_path = fdlg.GetPathName(), SetWindowText(fdlg.GetFileTitle()), etc
    afx_msg void OnClick();

    // additional message handlers etc

private:
    CString m_path; // save full path for after dialog is closed
};

You can add as much or as little customization as you want depending on if the control will be created dynamically, via the resource file, or whatever. The basic idea being that you display the currently selected file name on the button while storing the full path for other uses as a member so the user doesn't need to see the clutter of a long path with nested directories.

If you don't like the way it looks by default you can override `OnPaint` and handle `WM_PAINT` messages and use a custom font, size, or add ellipsis for a long file title. You could also handle re-sizing the button to fit the file title by using text metrics and `GetTextExtent` to ensure the name fits or simply display a `CToolTipCtrl` when they hover the mouse over the button so they can see the full name. The `CMFCButton` from the MFC feature pack in VS2008+ has tool tip functionality built in so if you inherit from that instead of `CButton` displaying a tool tip would be as simple as calling `SetTooltip(m_path)`

If you want to get really fancy you could use some of the uxtheme API or new windows animation API.

Problem

I've created a read-only edit box in an MFC dialog box. I'm trying to have it so a user clicks in the edit box, which is read-only, it opens a file dialog, and then puts this value into the text box using UpdateData. I'm catching the `ON_EN_SETFOCUS` message but pressing OK on the file dialog respawns it, so I get caught in an infinite loop. ``` UpdateData(TRUE); CFileDialog fileDialog(TRUE,NULL, NULL,OFN_HIDEREADONLY|OFN_FILEMUSTEXIST, _T("Text Files(*.txt)|*.txt||")); if( fileDialog.DoModal() == IDOK ) { configFile=fileDialog.GetPathName(); //Note to self, this includes filename, getPathName includes filename and path. } else { return; } UpdateData(FALSE); ``` If you've got any ideas on how this should be done, I would be very grateful.

Original source