
Introduction
When I need a user to select a file or folder, I would have to create two controls, an edit control for entering the text, and a browse button that would bring up a dialog for actually choosing the file or folder. So I thought, why not combine the two controls into one. The CFileEditCtrl class is the result. The class definition and implementation are in the files FileEditCtrl.h and FileEditCtrl.cpp which are included in the demo project.
Testing
This code has not been tested for UNICODE builds. If any bugs are found and fixed, please drop me a note.
Acknowledgements
Michael Dunn for his article Introduction to COM - What It Is and How to Use It, for showing me how to handle shortcut (*.lnk and *.pif) files.
Me for my articles CPJAImage - Yet another image drawing class and Multiple Selection in a File Dialog.
Using an image on the button
If you want to place an image (HICON or HBITMAP), instead of the ellipses, on the button, you have to add the PJAImage.h and PJAImage.cpp files to your project. If you do not want to use an image, you do not have to add these files to your project, but you have to ensure that the PJAImage.h file is not included in the FileEditCtrl.h file, by commenting out the #include "PJAImage.h" (line 41) line in FileEditCtrl.h.
top
Features
- The control is derived from
CEdit. All CEdit member functions are CFileEditCtrl member functions. It can be created with any of the ES_* edit control styles. It will respond just like any other edit control to any EM_* commands, and sends all EN_* notification messages.
- The ellipses button is drawn in the controls non-client area. It is a part of the control, not a separate button that has to be added onto the dialog template, or otherwise created or setup. It can be placed on either the left or the right side of the control.
- The control has its own
DDX_FileEditCtrl and DDV_FileEditCtrl dialog data exchange functions. Setting up the control for use is very easy.
- Using the
Create() member function, the control can be created in any window, not just dialogs or forms.
- The control can be used to browse for files or folders. And it has a member function that can be used to switch between the two. When the
CFileDialog or SHBrowseForFolder dialogs are opened, they will be set to the directory currently entered in the control.
- The control accepts relative paths. Users can enter
..\..\anyfolder and the control will return the absolute path relative to the current working directory. Entering '.' will return the current working directory. If the FEC_MULTIPLE flag is set, the first file entered will be relative to the current directory, and all subsequent files will be relative to the first file, unless the absolute path is entered.
- The control accepts wildcards ( '*' and/or '?' ) in the file name. Just set the
FEC_WILDCARDS flag.
- The control will automatically dereference shortcut (*.lnk) files. To disable this feature, just set the
FEC_NODEREFERENCELINKS flag.
- The control accepts Drag and Drop files and folders. Just create it with the
WS_EX_ACCEPTFILES extended Windows style. When a drop action occurs, the control sends a WM_NOTIFY message to its parent window.
- Member functions give access to the internal
BROWSEINFO and OPENFILENAME structures, so if the default settings are not satisfactory, there is complete control over how the CFileDialog and SHBrowseForFolder dialogs are implemented.
- The control is resizable. The button keeps its proportionate size relative to the height of the control. As the control gets taller, the button gets bigger, and so does the dots on the button.
- The
CFileDialog has the text on its default button changed from 'Open' to 'OK'.
- When the ellipses button is clicked, the control sends a
WM_NOTIFY message to its parent window, giving the parent window a chance to stop the SHBrowseForFolder or CFileDialog from popping up. The <Ctrl><.> keystroke has the same action as a click on the button.
- The button can have an icon or bitmap displayed on it instead of the ellipses.
- The control can be drawn as a flat, hot to mouse control.
top
Using the Control
To use this control in your application, Add the FileEditCtrl.h and FileEditCtrl.cpp files to your project. Then it is recommended to add the text strings defined at the top of the FileEditCtrl.cpp file to your string table resource, using the FEC_IDS_* identifiers defined there.
#if !defined FEC_IDS_ALLFILES
#define FEC_NORESOURCESTRINGS so this class knows how to handle these strings
#define FEC_IDS_ALLFILES _T("All Files (*.*)|*.*||")
#define FEC_IDS_BUTTONTIP _T("Browse")
#define FEC_IDS_FILEDIALOGTITLE _T("Browse for File")
#define FEC_IDS_SEPERATOR _T(";")
#define FEC_IDS_NOFILE _T("Enter an existing file.")
#define FEC_IDS_NOTEXIST _T("%s does not exist.")
#define FEC_IDS_NOTFILE _T("%s is not a file.")
#define FEC_IDS_NOTFOLDER _T("%s is not a folder.")
#define FEC_IDS_OKBUTTON _T("OK")
#endif
To use the control on a dialog, using all the default settings, add an edit control to the dialog template, add a CString member variable to the dialog class, and in DoDataExchange() add the DDX_FileEditCtrl() and DDV_FileEditCtrl() functions. The default settings for the SHBrowseForFolder dialog has the BIF_RETURNONLYFSDIRS flag set. And the default settings for the CFileDialog dialog has the OFN_HIDEREADONLY, OFN_FILEMUSTEXIST and OFN_NOCHANGEDIR flags set, the file filter is set to the FEC_IDS_ALLFILES resource string, and the dialog caption is set to the FEC_IDS_FILEDIALOGTITLE resource string. If you want the control to be used for folders, set the flag in last parameter in DDX_FileEditCtrl() to FEC_FOLDER, and for files set it to FEC_FILEOPEN to use the File Open dialog, and FEC_FILESAVEAS to use the File Save As dialog.
If you want more control over the dialogs, such as choosing multiple files, then you have to add a CFileEditCtrl variable to your dialog class. In DoDataExchange(), add the second version of DDX_FileEditCtrl(). And then get a pointer to the OPENFILENAME or BROWSEINFO structures, using the GetOpenFileName() or GetBrowseInfo() functions, and set them accordingly. In the demo app, I have an edit control with an ID of IDC_EDIT1 and a CFileEditCtrl variable m_FileEditCtrl.
void CFileEditDemoDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
...
DDX_FileEditCtrl(pDX, IDC_EDIT1, m_FileEditCtrl, FEC_FILEOPEN);
...
}
Because these functions are not supported by Class Wizard, they have to be placed outside the AFX_DATA_MAP code block. If you would like to add Class Wizard support, see MFC Technical Note 26 DDX and DDV routines and look under ClassWizard.
To retrieve the file names from the control, use the GetStartPosition() and GetNextPathName() member functions. In the demo app, I did this in the CDumpDialog::OnInitDialog() function, in order to fill the list box with the files entered by the user.
BOOL CDumpDialog::OnInitDialog()
{
CDialog::OnInitDialog();
CFileEditDemoDlg *pDemo = (CFileEditDemoDlg *)GetParent();
int width = 0;
CString str;
CDC *pDC = m_List.GetDC();
int saved = pDC->SaveDC();
pDC->SelectObject(GetFont());
POSITION pos = pDemo->m_fileeditctrl.GetStartPosition();
while (pos)
{
str = pDemo->m_fileeditctrl.GetNextPathName(pos);
m_List.AddString(str);
CSize size(0, 0);
size = pDC->GetTextExtent(str);
width = width > size.cx ? width : size.cx;
}
pDC->RestoreDC(saved);
ReleaseDC(pDC);
m_List.SetHorizontalExtent(width + 5);
return TRUE;
}top
FEC_NOTIFY structure
typedef struct tagFEC_NOTIFY {
NMHDR hdr;
CFileEditCtrl* pFEC;
CString *pNewText;
tagFEC_NOTIFY (CFileEditCtrl *FEC, UINT code);
} FEC_NOTIFY;
#define FEC_NM_PREBROWSE 1
#define FEC_NM_POSTBROWSE 2
#define FEC_NM_DROP 3
When a user clicks on the browse button, the control will send a WM_NOTIFY message with a FEC_NM_PREBROWSE notification code to its parent window before it brings up the SHBrowseForFolder or CFileDialog dialogs. The NMHDR* pointer will point to a FEC_NOTIFY structure. The pFEC member will point to the CFileEditCtrl that sent the message. You can use this pointer to modify the OPENFILENAME or BROWSEINFO structures. If you set the LRESULT parameter of the OnNotify handler to a nonzero value, you will stop the dialogs from executing.
If you want to use the browse button to start a dialog, or other functions, other than the CFileDialog or SHBrowseForFolder, simply call and handle your dialog in the FEC_NM_PREBROWSE handler. Be sure to set the LRESULT parameter to nonzero.
The control will send another WM_NOTIFY message with a FEC_NM_POSTBROWSE notification code after the browse dialog is closed but before the control's window text has been updated. The NMHDR* pointer will once again point to a FEC_NOTIFY structure. If the pNewText parameter is NULL, the dialog was cancelled. If it is not NULL, it will be a pointer to a CString containing the new text. If you set the LRESULT parameter of the OnNotify handler to a nonzero value, you will stop the control from updating.

The control also sends a WM_NOTIFY message with the FEC_NM_DROP notification code after the user drags and drops a file or folder onto the control, but before the control updates its text. Once again, setting the LRESULT parameter of the OnNotify handler to a nonzero value will stop the control from updating.
top
User Functions
These are the public member functions that are used to control the CFileEditCtrl class.
CFileEditCtrl::CFileEditCtrl(BOOL bAutoDelete )
CFileEditCtrl constructor
Initializes all the internal variables.
Parameters:
bAutoDelete [in] - Auto delete flag
Returns:
Nothing.
Note:
If bAutoDelete is TRUE, this class object will be deleted when its window is destroyed (in CFileEditCtrl::PostNCDestroy). The only time this should be used is when the control is created dynamically in the DDX_FileEditCtrl(CDataExchange*,int,CString&,DWORD) function.
User Functions
CFileEditCtrl::~CFileEditCtrl()
CFileEditCtrl destructor
Cleans up internal data variables.
Parameters:
None
Returns:
Nothing.
User Functions
BOOL CFileEditCtrl::Create(DWORD dwFlags,
DWORD dwExStyle,
LPCTSTR lpszWindowName,
DWORD dwStyle,
const RECT& rect,
CWnd* pParentWnd,
UINT nID)
CFileEditCtrl::Create
Creates the CFileEditCtrl in any window.
Parameters:
dwFlags | [in] | - CFileEditCtrl flags (FEC_*) |
dwExStyle | [in] | - Windows extended styles (WS_EX_*) |
lpszWindowName | [in] | - The initial text in the control |
dwStyle | [in] | - Windows and Edit control styles (WS_* and ES_*) |
rect | [in] | - The position and size of the control |
pParentWnd | [in] | - Pointer to the control's parent window |
nID | [in] | - The control's ID |
Returns:
TRUE if the control was successfully created. FALSE if not.
Note:
See SetFlags() below for descriptions of the flags used.
User Functions
DWORD CFileEditCtrl::GetFlags()
CFileEditCtrl::GetFlags
Retrieves the current flags.
Parameters:
None.
Returns:
The current flags.
Note:
See SetFlags() below for descriptions of the flags used. Because some flags can be changed via GetOpenFileName(), always use this function to get the current state of the flags.
User Functions
BOOL CFileEditCtrl::ModifyFlags(DWORD remove,
DWORD add)
CFileEditCtrl::ModifyFlags
Modifies the control flags.
Parameters:
remove | [in] | - The flags to remove |
add | [in] | - The flags to add |
Returns:
TRUE if the flags are successfully modified. FALSE if not.
Note:
See SetFlags() below for descriptions of the flags used.
User Functions
BOOL CFileEditCtrl::SetFlags(DWORD dwFlags)
CFileEditCtrl::SetFlags
- Sets all the internal flags.
- Initializes and sets up the
OPENFILENAME or BROWSEINFO structures.
- Forces the control to be redrawn if the button position changes.
Parameters:
dwFlags [in] - The flags to set.
Returns:
TRUE if successful. FALSE if not.
Note:
The following table describes the flags used in the dwFlags parameter.
|
dwFlags |
Purpose |
FEC_FILEOPEN | The control is set to accept files. When the ellipses button is clicked, the control starts the Windows Common File Open dialog. This flag cannot be used with the FEC_FOLDER nor FEC_FILESAVEAS flags. |
FEC_FILESAVEAS | The control is set to accept files. When the ellipses button is clicked, the control starts the Windows Common File Save As dialog. This flag cannot be used with the FEC_FOLDER nor FEC_FILEOPEN flags. |
FEC_MULTIPLE | Used with FEC_FILEOPEN. The control will accept multiple files. Has the same effect as the OFN_ALLOWMULTISELECT flag. |
FEC_MULTIPLEFILES | Combination of FEC_FILEOPEN and FEC_MULTIPLE |
FEC_WILDCARDS | Used with FEC_FILEOPEN. The control will accept and resolve any wildcards ('*' and/or '?') in the file name. If the FEC_MULTIPLE flag is set, GetNextPathName() will return all the files that match. If FEC_MULTIPLE is not set, GetNextPathName() will return only the first match. |
FEC_NODEREFERENCELINKS | Used with FEC_FILEOPEN. GetNextPathName() will return the path name of any shortcut (*.lnk) files entered. If this flag is not set, GetNextPathName() will return the path name of the file the shortcut points to. Has the same effect as the OFN_NODEREFERENCELINKS flag. |
FEC_FOLDER | The control is set to accept folders. When the ellipses button is clicked, the control starts the SHBrowseForFolder dialog. This flag cannot be used with the FEC_FILEOPEN nor FEC_FILESAVEAS flag. |
FEC_TRAILINGSLASH | Used with FEC_FOLDER. The folder path entered in the control will have a trailing slash. |
FEC_BUTTONLEFT | The ellipses button will be placed on the left side of the control. |
FEC_BUTTONTIP | Enables the browse button tooltip. The tooltip text is set with the FEC_IDS_BUTTONTIP resource string. |
FEC_CLIENTTIP | Enables the client area tooltip. The tooltip text is set with the SetClientTipText() member function. |
FEC_FLAT | Sets the control to be drawn as a flat, hot to mouse control. |
FEC_GRAYSCALE | Used with FEC_FLAT. The dots or image on the button will be drawn in grayscale when the control is flat. They are drawn in color when the control is active/hot. |
User Functions
void CFileEditCtrl::SetClientTipText(CString text)
CFileEditCtrl::SetClientTipText
Sets the text to be used by the client area tooltip.
Parameters:
text [in] - The text to set
Returns:
Nothing.
User Functions
BROWSEINFO* CFileEditCtrl::GetBrowseInfo() const
CFileEditCtrl::GetBrowseInfo
Retrieve a pointer to the BROWSEINFO structure.
Parameters:
None.
Returns:
A pointer to the BROWSEINFO structure if the FEC_FOLDER flag was set. NULL otherwise.
Note:
If the default SHBrowseForFolder settings do not fit your use, use the pointer returned by this function to set up the SHBrowseForFolder using your own settings.
User Functions
OPENFILENAME* CFileEditCtrl::GetOpenFileName() const
CFileEditCtrl::GetOpenFileName
Retrieves a pointer to the OPENFILENAME structure.
Parameters:
None.
Returns:
A pointer to the OPENFILENAME structure if the FEC_FILE flag was set. NULL otherwise.
Note:
If the default CFileDialog settings do not fit your use, use the pointer returned by this function to set up the CFileDialog using your own settings.
User Functions
POSITION CFileEditCtrl::GetStartPosition()
CFileEditCtrl::GetStartPosition
Gets the starting position for the GetNextPathName() function.
Parameters:
None.
Returns:
A MFC POSITION structure that points to the first file in the control.
User Functions
CString CFileEditCtrl::GetNextPathName(POSITION &pos)
CFileEditCtrl::GetNextPathName
Returns the file name at the specified position in the buffer.
Parameters:
pos | [in] | - The position of the file name to retrieve |
| | [out] | - The position of the next file name |
Returns:
The complete path name of the file or folder.
Note:
The starting position is retrieved using the GetStartPosition() function. pos will be set to NULL when there are no more files.
User Functions
int CFileEditCtrl::SetButtonWidth(int width)
CFileEditCtrl::SetButtonWidth
Sets the width, in pixels, of the browse button.
Parameters:
width [in] - The new width of the button
Returns:
The previous width of the button.
Note:
Setting the width to -1 causes the control to use the default width which is calculated to be 80% of its height.
User Functions
int CFileEditCtrl::GetButtonWidth()
CFileEditCtrl::GetButtonWidth
Retrieves the width, in pixels, of the browse button.
Parameters:
None.
Returns:
The width of the browse button.
User Functions
void CFileEditCtrl::SetButtonImage(HANDLE hImage,
DWORD PJAIFlags,
COLORREF Transparent)
CFileEditCtrl::SetButtonImage
Sets the image to be used on the browse button.
Parameters:
hImage | [in] | - Handle of the image (can be a HBITMAP or HICON) |
PJAIFlags | [in] | - The image flags (see the note below) |
Transparent | [in] | - The transparent color on the bitmap. If CLR_DEFAULT is used, the color of the top left pixel is used as the transparent color. |
Returns:
TRUE if a new image is set. FALSE if not.
Note:
The PJAImage.h file must be included (see lines 37 to 41 of FileEditCtrl.h) in order for this function to work.
Flags used in the PJAIFlags parameter:
PJAI_BITMAP | The given handle is an HBITMAP |
PJAI_ICON | The given handle is an HICON |
PJAI_AUTODELETE | The given handle will be deleted and the memory freed when a new image is set or the CFileEditCtrl object is deleted. If this flag is not set, the user of this class is responsible for freeing the image handle when it is no longer needed |
PJAI_STRETCHED | Draws the image so that it fills the button. |
PJAI_TRANSPARENT | Draws the bitmap image transparently. This flag has no effect if the image is an icon, as icons are transparent by default. |
User Functions
Data Exchange Functions
void DDV_FileEditCtrl (CDataExchange *pDX,
int nIDC)
DDV_FileEditCtrl
Verifies that the files or folders entered actually exist.
Parameters:
pDX | [in] | - Pointer to the CDataExchange object |
nIDC | [in] | - The control's resource ID |
Returns:
Nothing.
Note:
If the file or folder is invalid, pops up a message box informing the user, then sets the focus to the offending CFileEditCtrl.
User Functions
void DDX_FileEditCtrl (CDataExchange *pDX,
int nIDC,
CFileEditCtrl &rCFEC,
DWORD dwFlags)
DDX_FileEditCtrl
Subclasses the control with the given ID. Transfers the data between the window text and the supplied CFileEditCtrl.
Parameters:
pDX | [in] | - Pointer to the CDataExchange object |
nIDC | [in] | - The control's resource ID |
rCFEC | [in] | - The CFileEditCtrl object that is to control this window |
dwFlags | [in] | - The flags used to setup this control |
Returns:
Nothing.
Note:
See SetFlags() above for descriptions of the flags used.
User Functions top
The Button
In order to get the button to work, I first had to override the OnNcCalcSize() function. This is the function that is used to calculate the size and position of a Windows client area. In my override, I called CEdit::OnNcCalcSize() to get the default size and position of the client area, then I adjusted the size of the client area and calculated the size and position of the button. The CRect m_rcButtonRect member variable is used to store this information.
void CFileEditCtrl::OnNcCalcSize(BOOL bCalcValidRects,
NCCALCSIZE_PARAMS FAR* lpncsp)
{
CEdit::OnNcCalcSize(bCalcValidRects, lpncsp);
m_rcButtonRect = lpncsp->rgrc[0];
if (m_bButtonLeft)
{
lpncsp->rgrc[0].left +=
(lpncsp->rgrc[0].bottom - lpncsp->rgrc[0].top) * 8/10;
m_rcButtonRect.right = lpncsp->rgrc[0].left;
}
else
{
lpncsp->rgrc[0].right -=
(lpncsp->rgrc[0].bottom - lpncsp->rgrc[0].top) * 8/10;
m_rcButtonRect.left = lpncsp->rgrc[0].right;
}
if (bCalcValidRects)
m_rcButtonRect.OffsetRect(-lpncsp->rgrc[1].left,
-lpncsp->rgrc[1].top);
m_rcButtonRect.NormalizeRect();
}
The only time OnNcCalcSize() is called is when the windows frame has changed, so to force a call to OnNcCalcSize(), I had to call SetWindowPos() from SetFlags(), using the SWP_FRAMECHANGED flag.
BOOL FileEditCtrl::SetFlags(DWORD dwFlags)
{
...
SetWindowPos(NULL,0,0,0,0,
SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOSIZE|
SWP_NOZORDER|SWP_NOACTIVATE);
...
}
I then needed to paint the button on the control, so I wrote the DrawButton() function. Because the button is not in the client area of the window, DrawButton() has to be called from OnNcPaint().
void CFileEditCtrl::OnNcPaint()
{
CEdit::OnNcPaint();
DrawButton (m_nButtonState);
}
The next thing was to get mouse messages for the button. Because the button is not in the client area, it would not get client area mouse messages, and because it is not a border, it would not get non-client mouse messages. To solve this problem, I had to override OnNcHitTest() and get it to return HT_BORDER when the mouse cursor was over the button.
UINT CFileEditCtrl::OnNcHitTest(CPoint point)
{
...
UINT where = CEdit::OnNcHitTest(point);
if (where == HTNOWHERE && ScreenPointInButtonRect(point))
where = HTBORDER;
return where;
}
Now a mouse press on the button would generate a WM_NCLBUTTONDOWN message, so I had to override OnNcLButtonDown(). In OnNcLButtonDown(), I would capture the mouse using SetCapture() and call DrawButton() to draw the button as down. Because once the mouse is captured, it no longer generates non-client mouse messages, I would have to respond to WM_LBUTTONUP and WM_MOUSEMOVE messages in order to keep track of the mouse. Because CEdit::OnLButtonDown also captures the mouse, I could not use GetCapture to see if the button had captured the mouse, so I added the BOOL m_bMouseCaptured variable to keep track of it.
void CFileEditCtrl::OnNcLButtonDown(UINT nHitTest, CPoint point)
{
CEdit::OnNcLButtonDown(nHitTest, point);
...
if (ScreenPointInButtonRect(point))
{
SetCapture();
m_bMouseCaptured = TRUE;
SetFocus();
DrawButton(BTN_DOWN);
}
}
By overriding OnMouseMove(), I could keep track of the captured mouse, and draw the button as down if the mouse cursor was over the button, or as up if it was not.
void CFileEditCtrl::OnMouseMove(UINT nFlags, CPoint point)
{
CEdit::OnMouseMove(nFlags, point);
...
if (m_bMouseCaptured)
{
ClientToScreen(point);
if (ScreenPointInButtonRect(point))
{
if (m_nButtonState != BTN_DOWN)
DrawButton (BTN_DOWN);
}
else if (m_nButtonState != BTN_UP)
DrawButton (BTN_UP);
}
}
In the override of OnLButtonUp, the mouse capture is released, the m_bMouseCaptured flag is cleared, and if the mouse cursor is over the button, the ButtonClicked() function is called. The ButtonClicked() function opens the appropriate dialog and sends a WM_NOTIFY notification message to the control's parent window.
void CFileEditCtrl::OnLButtonUp(UINT nFlags, CPoint point)
{
CEdit::OnLButtonUp(nFlags, point);
...
if (m_bMouseCaptured)
{
ReleaseCapture();
m_bMouseCaptured = FALSE;
if (m_nButtonState != BTN_UP)
DrawButton(BTN_UP);
ClientToScreen(point);
if (ScreenPointInButtonRect(point))
ButtonClicked();
}
}top
Revision History
- Created October 2000
- November 11, 2000 - allowed the control to work with dialog templates
- November 22, 2000 - registers the control's window class, can now be added to dialog as custom control
- January 4, 2001
- near total rewrite of the control, now derived from
CEdit
- control can now be added to dialog template using an edit control
- browse button now drawn in non-client area of the control
- January 5, 2001 - removed
OnKillFocus(), replaced with OnDestroy()
- January 15, 2001
- added
DDX_ and DDV_ support
- modified
GetStartPosition() and GetNextPathName()
- modified how
FECOpenFile() updates the control text when multiple files are selected
- added
FillBuffers()
- added support for relative paths
- added
OnChange handler
- added drag and drop support
- January 26, 2001 - fixed bug where
SHBrowseForFolder does not like trailing slash
- January 27, 2001 - fixed bug where if control is initialized with text,
FillBuffers was not called.
- January 28, 2001
- removed
GetFindFolder() and SetFindFolder(); replaced with GetFlags() and SetFlags()
- modified the
DDX_ and DDV_ functions to accept these flags
- modified the
Create() function to accept these flags
- allowed option for returned folder to contain trailing slash
- allowed browse button to be on the left side of the control
- added
ScreenPointInButtonRect() to better tell if mouse cursor is over the button
- modified how
OnDropFiles() updates the control text when multiple files are dropped
- February 25, 2001 - fixed
EN_CHANGE notification bug. Now parent window receives this notification message, used ON_CONTROL_REFLECT_EX macro instead of ON_CONTROL_REFLECT
- April 12, 2001 - added
OnSize handler, fixed button drawing problem when control size changed
- April 21, 2001 - added a tooltip for the browse button
- May 12, 2001
- removed
OnDestroy, replaced with PostNCDestroy
- added tooltip support to client area
- modified the
FECBrowseForFolder and FECFolderProc functions
- added a one pixel neutral area between the client area and browse button when the button is on the right hand side of the control. (looks better IMO)
- May 29, 2001
- PL -- removed the filename from the
m_pCFileDialog->m_ofn.lpstrInitialDir variable, so when browsing back for file, we open the correct folder.
- used smaller (exact size) arrays for file, extension and path components.
- some cosmetic changes.
- May 29, 2001 -
FECFolderProc now checks for UNC path. SHBrowseForFolder cannot be initialized with UNC
- June 2, 2001 - modified
ButtonClicked function. Now sends a WM_NOTIFY message to parent window before showing dialog, allows parent window to cancel action by setting result to nonzero. Also sends WM_NOTIFY message to parent window after dialog closes with successful return
- June 9, 2001 - added
OnNcLButtonDblClk handler. Double click on button now treated as two single clicks
- June 23, 2001
- placed a declaration for the
FECFolderProc global callback function into the header file
- fixed bug that occurred when removing the filename from the
m_pCFileDialog->m_ofn.lpstrInitialDir variable when there was no file to remove.
- August 2, 2001 - replaced
SetWindowText() with OnSetText() message handler. Now correctly handles WM_SETTEXT messages
- August 12, 2001
- added
GetValidFolder() function and modified FECOpenFile() function. We now start browsing in the correct folder -- it finally works!!! {:o)
- modified
SetFlags() so the button could be moved by setting the FEC_BUTTONLEFT flag
- removed the
m_bCreatingControl variable
- removed the call to
SetWindowPos() from the Create() and DDX_FileEditCtrl() functions. Now done in SetFlags() function
- August 14, 2001 - modified
FECOpenFile(). Now sets the file name in CFileDialog to first file name in FileEditCtrl
- August 18, 2001 - Set the tooltip font to the same font used in the
CFileEditCtrl
- September 2, 2001
- added the
ModifyFlags() function and changed how the flags are handled
- modified the
GetFlags() function
- added the
FEC_MULTIPLE and FEC_MULTIPLEFILES flags
- added support for wildcards ( '*' and '?') in filenames
Involved:
- modifying the
GetStartPosition(), GetNextPathName(), SetFlags(), and FillBuffers() functions
- adding the
ExpandWildCards() function
- replacing the
m_lpstrFiles variable with the m_Files array
- adding the
FEC_WILDCARDS flag.
- September 3, 2001
- added ability to dereference shortcut files (*.lnk)
- added the
FEC_NODEREFERENCELINKS flag.
- added the
DereferenceLink() function.
- September 5, 2001 - fixed the
Create() function - now destroys the control if the SetFlags() function fails
- September 8, 2001
- added the
AddFiles() function to be better able to handle shortcut (*.lnk) files
- modified the
OnDropFiles() function to be better able to handle shortcut (*.lnk) files
- September 12, 2001
- PR -- added
#include <shlobj.h> to the FileEditCtrl.h header file
- UNICODE fixes, added
_T() macro in Create() function and in TRACE() calls.
- PR states that the code now works perfectly with UNICODE builds and UNC paths. {:o) {:o) {:o) {:o) {:o) {:o)
- September 18, 2001 - added ability to use icons or bitmaps on the browse button
Involved:
- adding
SetButtonImage() function.
- modifying the
DrawButton() function
- adding the
FECButtonImage class.
- September 20, 2001
- fixed resource leak in
FECButtonImage class
- cleaned up the
FECButtonImage class code
- added ability to resize the browse button
Involved:
- adding
m_nButtonWidth variable
- adding
SetButtonWidth() and GetButtonWidth() functions
- modifying
OnNcCalcSize() and DrawButton() functions
- September 24, 2001 - fixed bug in
GetNextPathName() and ExpandWildCards() where multiple files could not start from the current drive. i.e. \folder\file.ext as second file would give an error
- September 26, 2001 - fixed bug in
GetNextPathName() to allow incomplete relative paths (i.e. ..\..\) when browsing for files.
- October 5, 2001 - PR -- Added
#include <afxcmn.h> to the CFileEditCtrl.h header file
- October 14, 2001
- rewrote the
FECButtonImage::DrawImage() function, it now handles disabled transparent bitmaps better (the transparent color can be any color, no longer just light colors), and now also handles pattern and bitmap background brushes
- various other touch ups (comments mostly)
- November 20, 2001 - added ability to dereference *.pif (shortcut to MS-DOS) files
- November 26, 2001 - added ability to be flat, hot to mouse (
FEC_FLAT flag)
Involved:
- adding
OnKillFocus(), OnLButtonDown() and OnNCMouseMove() message handlers
- adding
Redraw() and SetReadOnly() member functions
- modifying
OnEnable(), OnMouseMove(), OnNCPaint() and OnSetFocus() message handlers
- modifying
DrawButton() and SetFlags() member functions
- modifying the
CFECButtonImage::DrawImage() function
- December 1, 2001 - clean up code from November 26, 2001
- December 5, 2001 - added the
FEC_GRAYSCALE flag. Flat buttons can be drawn in full color or grayscale.
- December 8, 2001 - greatly improved the button drawing code.
- December 18, 2001
- removed the
CFECButtonImage class, replaced with the CPJAImage class.
- rewrote the
SetButtonImage() function.
- rewrote the
DrawButton() function.
- January 7, 2002 - Remon -- added the
FEC_NM_DROP notification. The control now sends a WM_NOTIFY message to its parent window after a file or folder has been dropped onto it.
- January 14, 2002 - fixed a bug that prevented the tooltips from displaying properly.
- February 18, 2002 - replaced
SetReadOnly() with OnSetReadOnly(), the control now properly handles the EM_SETREADONLY message.
- March 27, 2002 - fixed border drawing when control is drawn flat. Now the control does not appear to change size when it switches from edit mode to readonly or disabled.
- March 28, 2002
- moved the
FEC_NM_POSTBROWSE notification. Now it is sent after the dialog closes, but before the edit control's text is updated. The parent window can now return a nonzero value to stop the edit control from updating.
Involved:
- modifying the
ButtonClicked(), FECBrowseForFolder() and FECOpenFile() functions
- adding the
pNewText pointer to the FEC_NOTIFY structure
- modified
FEC_NM_DROP notification. The parent window can now return a nonzero value to stop the edit control from updating.
- April 1, 2002 - Removed the
CStringArray used to store file names, now using a linked list (CStringList)
Involved:
- modifying the
AddFile(), GetStartPosition(), GetNextPathName and FillBuffers() functions
- April 2, 2002 - Added the ability for the
CFECFileDialog to dynamically manage the memory needed by the lpstrFile member of the OPENFILENAME structure. (Thanks to Philippe Lhoste)
Involved:
- adding the
DoModal(), OnFileNameChange() and Reset() functions to the CFECFileDialog class
- modifying the
FECOpenFile() function.
- November 23, 2002 - The April 2, 2002 changes did not work with WinNT and above. No idea why not. I fixed it by adding the
GetStartPosition() and GetNextPathName() functions and a destructor to the CFECFileDialog class. I also removed the Reset() function, and modified the DoModal() and FECOpenFile() functions.
- December 4, 2002
- Added the
FEC_FILEOPEN and FEC_FILESAVEAS flags. FEC_FILEOPEN replaces the FEC_FILE flag. The FEC_FILESAVEAS flag causes the browse button to open the 'File Save As' dialog.
- Improved the drawing code for flat control
top
Be sure to check here for the latest updates.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.