Click here to Skip to main content
15,892,737 members
Articles / Desktop Programming / MFC

CBrowseCtrl - Adding File/Folder-Browse Features to Your Projects Easily

Rate me:
Please Sign up or sign in to vote.
4.93/5 (59 votes)
25 May 20045 min read 287.5K   7.8K   150  
A file/folder browsing control that integrates an editbox and a button with built-in images
///////////////////////////////////////////////////////////////////////////
//				BrowseCtrl.h
//
// CBrowseCtrl is a CButton derived control used to let the user browse for
// files or folders on their systems.
//
// CBrowseCtrl integrates an edit-box and a browse-button together so the
// develops only need to maintain one control in their projects instead of two.

// Moreover, CBrowseCtrl draws its own "build-in" images on the browse-button
// without requiring the developers to include any extra icon, bitmap or other
// image resources.
//
// Written by Abin (abinn32@yahoo.com)
//
// History:
// 
// Jan 08, 2004 - Initial public release.
// Jan 09, 2004 - 1, Improved drawing functions to properly handle the case in
//                   which the control client area is too small to be drawn.
//                   In debug mode it will provide a message box to inform the
//                   developer about that issue.
//                2, Improved the edit box so it acts better upon receiving and
//                   losing the input focus. 
// Jan 10, 2004 - 1, Fixed a problem where the edit bix is not properly redrawn
//                   in some mouse events. Thanks to JOHN11.
//                2, Added method "GetSelectedCount" which returns the number of
//                   items the user has selected in the most recent file/folder
//                   dialog that was terminated by IDOK.
//                3, Improved the mouse/focus events monitoring functions
//                4, Fixed a drawing glitch when the user clicks on the edges of
//                   the edit box.
//                5, Changed the drawing rects calculating methods for performance
//                   improvement.
// Jan 14, 2004 - 1, Updated "SetPathName" and "GetPathName" member functions.
//                2, Altered the message sending method so the lparam is now a
//                   pointer to this CBrowseCtrl object.
// Jan 22, 2004 - 1, Added methods to monitor whether the user has manually changed
//                   the contents of the edit box when BC_CTL_ALLOWEDIT is set. The
//                   return value of "GetPathName" will also be properly affected.
//                2, The window titles of file/folder dialogs can now be accessed
//                   by calling "SetDialogTitle" and "GetDialogTitle".
//                3, The banner text of folder dialogs can now be accessed by calling
//                   "SetDialogBanner" and "GetDialogBanner".
//                4, Added method "ModifyButtonStyle" to allow convenient style changing.
// Feb 07, 2004 - 1, Improved drawing functions so that images/text are partially drawn
//                   if there is not enough space.
//
// May 22, 2004 - 1, Updated drawing functions.
//                2, Added functions: GetDriveLetter, GetDirectory, GetFileName
//                   GetFileTitle, GetFileExt.
//
/////////////////////////////////////////////////////////////////////////// 

#ifndef __BROWSECTRL_H__
#define __BROWSECTRL_H__

/////////////////////////////////////////////////////////////////////
//		Browse Button Style Flags
/////////////////////////////////////////////////////////////////////
#define BC_BTN_LEFT			0x0001 // Display the browse button on the left-side of the editbox
#define BC_BTN_ICON			0x0002 // Use icon, no text will be displayed
#define BC_BTN_FLAT			0x0004 // Use flat button style
#define BC_ICO_ARROWFOLDER	0x0008 // The arrow-folder icon, must be combined with BC_BTN_ICON
#define BC_ICO_FOLDER		0x0010 // The folder icon, must be combined with BC_BTN_ICON
#define BC_ICO_EXPLORER		0x0020 // The Windows Explorer icon, must be combined with BC_BTN_ICON
#define BC_CTL_ALLOWEDIT	0x0040 // Allow user to type in the editbox
#define BC_CTL_FOLDERSONLY	0x0080 // Browse for folder

class CBrowseCtrl : public CButton
{
public:	

	/////////////////////////////////////////////////////////////////////
	//		Constructor & Destructor
	/////////////////////////////////////////////////////////////////////

	CBrowseCtrl();
	virtual ~CBrowseCtrl();

	/////////////////////////////////////////////////////////////////////
	//		Runtime Creation
	/////////////////////////////////////////////////////////////////////

	virtual BOOL Create(const RECT& rect, CWnd* pParentWnd, UINT nID, DWORD dwBtnStyles = BC_BTN_ICON | BC_ICO_ARROWFOLDER, UINT nNotifyMessageID = 0);

	/////////////////////////////////////////////////////////////////////
	//		Operations
	/////////////////////////////////////////////////////////////////////

	int DoModal(); // Popup the file/folder browse dialog

	/////////////////////////////////////////////////////////////////////
	//		General Control Settings
	/////////////////////////////////////////////////////////////////////
	
	void SetButtonStyle(DWORD dwStyles); // The browse-button styles.
	DWORD GetButtonStyle() const;
	void ModifyButtonStyle(DWORD dwRemove, DWORD dwAdd);
	void SetButtonText(LPCTSTR lpszText); // The button text
	CString GetButtonText() const;	
	void SetTooltipText(LPCTSTR lpszText); // Button tooltip text
	CString GetTooltipText() const;		
	void SetNotifyMessageID(UINT nNotifyMsgID); // Sent to the parent window when dialog closes
	UINT GetNotifyMessageID() const;	
	BOOL IsEditManuallyChanged() const; // Whether the user has manually changed the contents of the edit box

	/////////////////////////////////////////////////////////////////////
	//		Browse Dialog Settings
	/////////////////////////////////////////////////////////////////////

	// The string displays on the edit control, also will be the default selected
	// file/folder when the dialog pops up
	void SetPathName(LPCTSTR lpszPathName);
	
	void SetOpenSave(BOOL bOpen); // "Open" or "Save As", CFileDialog only
	BOOL GetOpenSave() const;
	void SetDefExt(LPCTSTR lpszDefExt); // Default file extension, CFileDialog only
	CString GetDefExt() const;
	void SetFilter(LPCTSTR lpszFilter); // File extension filters, CFileDialog only
	CString GetFilter() const;
	void SetFileFlags(DWORD dwFlags); // File dialog flags, CFileDialog only
	DWORD GetFileFlags() const;
	void SetFolderFlags(UINT nFlags); // Folder dialog flags, folder dialog only
	UINT GetFolderFlags() const;
	
	// The text appear on the file/folder dialog title bar, if lpTitle is NULL or an
	// empty string, the default title is used.
	void SetDialogTitle(LPCTSTR lpszTitle);
	CString GetDialogTitle() const;

	// The banner text on the folder dialog.
	void SetDialogBanner(LPCTSTR lpszBanner);
	CString GetDialogBanner() const;
	
	/////////////////////////////////////////////////////////////////////
	//		Browse Result Data Access
	/////////////////////////////////////////////////////////////////////
	int GetSelectedCount() const; // How many files did the user select?
	CString GetPathName() const; // The full path name	
	CString GetDriveLetter() const; // Drive letter, e.g. "C"
	CString GetDirectory() const; // Folder path, e.g. "C:\\My Document"
	CString GetFileName() const; // File name with extension, files only
	CString GetFileTitle() const; // File name without extension, files only
	CString GetFileExt() const; // File extension, files only
	POSITION GetStartPosition() const;	// The path-name start position, for multiple selection 
	CString GetNextPathName(POSITION& pos) const;	// Next path name
	BOOL GetReadOnlyPref() const; // The "Read-Only" checkbox on dialog, CFileDialog only

	/////////////////////////////////////////////////////////////////////
	//		Overloads
	/////////////////////////////////////////////////////////////////////
	void SetWindowText(LPCTSTR lpszString);
	void GetWindowText(CString& rString) const;
	int GetWindowText(LPTSTR lpszStringBuf, int nMaxCount) const;	

protected:

	/////////////////////////////////////////////////////////////////////
	//		Protected Methods
	/////////////////////////////////////////////////////////////////////
	BOOL CreateCtrl(); // Initialize the control
	
	// Button drawing
	void PrepareMemDC(CDC* pMemDC, CBitmap* pBmp, CDC* pSrcDC, const CRect& srcRect, COLORREF bkColor) const;
	void DrawButtonExplorer(CDC* pDC, COLORREF bkColor, const CRect& rect) const; // Draw the explorer icon on the button
	void DrawButtonFolder(CDC* pDC, COLORREF bkColor, const CRect& rect) const; // Draw the folder icon on the button
	void DrawButtonArrowFolder(CDC* pDC, COLORREF bkColor, const CRect& rect) const; // Draw the arrow-folder icon on the button
	void DrawButtonText(CDC* pDC, COLORREF bkColor, const CRect& rect) const; // Draw text on the button
	void DrawButtonFrame(CDC* pDC, COLORREF bkColor) const; // Draw the button frame and background

	// File/Folder dialog popup
	int FileDoModal();
	int FolderDoModal();

	// Folder dialog call back function
	static int CALLBACK BrowseCallbackProc(HWND hwnd, UINT nMsg, LPARAM lParam, LPARAM lpData);
	
	// Edit control
	BOOL CreateEdit();
	
	// Mouse/input events
	void OnMouseEnter(); // The mouse cursor has entered the browse button area
	void OnMouseLeave(); // The mouse cursor has left the browse button area
	void OnSetEditFocus(); // The input focus has entered the edit control
	void OnKillEditFocus(); // The input focus has left the edit control

	void RecalculateRects(BOOL bMoveEdit = FALSE); // Recalculate drawing rects
	void OnButtonClicked();
	static BOOL SplitPath(LPCTSTR lpszPathName, CString* pStrDrvLetter, CString* pStrFolder, CString* pStrFileName, CString* pStrFileTitle, CString* pStrFileExt);

	/////////////////////////////////////////////////////////////////////
	//		Member Data
	/////////////////////////////////////////////////////////////////////

	// If greater than 0, this message is sent to the parent window when the
	// browse dialog is closed, wParam is either IDOK or IDCANCEL, lParam 
	// is a pointer to this CBrowseCtrl object.
	UINT m_nNotifyMsg; 

	CRect m_rcButton; // Rect of the browse button
	CRect m_rcContent; // Rect of the actual drawing area
	CRect m_rcEdit; // Rect of the edit box
	CEdit m_wndEdit; // The edit control which displays browse results
	BOOL m_bEditFocused; // The edit control is currently focused
	BOOL m_bOwnCreate; // Set to TRUE when the "Create" method has been called
	DWORD m_dwStyle; // The control styles
	BOOL m_bBtnPushed; // Set to TRUE if the button has been pused down, FALSE when released.
	BOOL m_bMouseIn; // Set to TRUE if the mouse cursor has entered the button area
	CToolTipCtrl m_wndTooltip; // The tooltip control for the button
	CString m_sTootipText; // Tooltip text, can be changed at fly
	CString m_sButtonText; // The button text, only displayed BC_BTN_ICON flag is not set

	// stuff for the file/folder dialog
	BOOL m_bDlgPopped; // The file/folder dialog has been popped up
	CString m_sDlgTitle; // To display on the file/folder dialog title bar
	CString m_sDlgBanner; //  To display a banner text on the folder dialog
	int m_nPathNamesLen; // Used when multiple files are selected, CFileDialog only
	BOOL m_bOpenFileDialog; // "Open" or "Save as", CFileDialog only
	DWORD m_dwFileFlags; // Dialog flags, CFileDialog only
	UINT m_nFolderFlags; // Dialog flags, folder dialog only
	BOOL m_bReadOnlyRef; // The "Open as Read Only" mark, CFileDialog only
	CString m_sDefExt; // Default file extension, CFileDialog only
	CString m_sFilter; // Default filters, CFileDialog only
	LPTSTR m_lpszPathNames; // Default path name, CFileDialog only
	int m_nSelCount;	// How many files did the user select?
	BOOL m_bEditChanged; // To monitor the changes made to the edit box by direct user input
	CString m_sEditText; // To record text changes in the edit box, needed if the control is destroyed before calling GetPathName

	/////////////////////////////////////////////////////////////////////
	//		Wizard Generated Stuff
	/////////////////////////////////////////////////////////////////////

	//{{AFX_VIRTUAL(CBrowseCtrl)
	public:
	virtual BOOL PreTranslateMessage(MSG* pMsg);
	protected:
	virtual void PreSubclassWindow();
	//}}AFX_VIRTUAL
	//{{AFX_MSG(CBrowseCtrl)
	afx_msg void OnPaint();
	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
	afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
	afx_msg void OnTimer(UINT nIDEvent);
	afx_msg void OnDestroy();
	afx_msg void OnMouseMove(UINT nFlags, CPoint point);
	afx_msg void OnSetFocus(CWnd* pOldWnd);
	afx_msg void OnMove(int x, int y);
	afx_msg void OnSize(UINT nType, int cx, int cy);
	afx_msg void OnEnable(BOOL bEnable);
	afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
	afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags);
	//}}AFX_MSG
	afx_msg void OnChangeEdit();
	DECLARE_MESSAGE_MAP()
};

#endif // #ifndef __BROWSECTRL_H__

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.


Written By
China China
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions