]>
git.saurik.com Git - wxWidgets.git/blob - src/msw/dirdlg.cpp
   1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     wxDirDialog 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) Julian Smart 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  21     #pragma implementation "dirdlg.h" 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  33 #if defined(__WIN95__) && !defined(__GNUWIN32_OLD__) && wxUSE_OLE 
  37     #include "wx/dialog.h" 
  38     #include "wx/dirdlg.h" 
  40     #include "wx/app.h"     // for GetComCtl32Version() 
  43 #include "wx/msw/private.h" 
  50 #include <shlobj.h> // Win95 shell 
  52 // ---------------------------------------------------------------------------- 
  54 // ---------------------------------------------------------------------------- 
  57     #define MAX_PATH 4096      // be generous 
  60 #ifndef BIF_NEWDIALOGSTYLE 
  61     #define BIF_NEWDIALOGSTYLE 0x0040 
  64 #ifndef BIF_NONEWFOLDERBUTTON 
  65     #define BIF_NONEWFOLDERBUTTON  0x0200 
  69     #define BIF_EDITBOX 16 
  72 // ---------------------------------------------------------------------------- 
  74 // ---------------------------------------------------------------------------- 
  76 IMPLEMENT_CLASS(wxDirDialog
, wxDialog
) 
  78 // ---------------------------------------------------------------------------- 
  79 // private functions prototypes 
  80 // ---------------------------------------------------------------------------- 
  83 static void ItemListFree(LPITEMIDLIST pidl
); 
  85 // the callback proc for the dir dlg 
  86 static int CALLBACK 
BrowseCallbackProc(HWND hwnd
, UINT uMsg
, LPARAM lp
, 
  90 // ============================================================================ 
  92 // ============================================================================ 
  94 // ---------------------------------------------------------------------------- 
  96 // ---------------------------------------------------------------------------- 
  98 wxDirDialog::wxDirDialog(wxWindow 
*parent
, 
  99                          const wxString
& message
, 
 100                          const wxString
& defaultPath
, 
 102                          const wxPoint
& WXUNUSED(pos
), 
 103                          const wxSize
& WXUNUSED(size
), 
 104                          const wxString
& WXUNUSED(name
)) 
 110     SetPath(defaultPath
); 
 113 void wxDirDialog::SetPath(const wxString
& path
) 
 117     // SHBrowseForFolder doesn't like '/'s nor the trailing backslashes 
 118     m_path
.Replace(_T("/"), _T("\\")); 
 119     if ( !m_path
.empty() ) 
 121         while ( *(m_path
.end() - 1) == _T('\\') ) 
 123             m_path
.erase(m_path
.length() - 1); 
 126         // but the root drive should have a trailing slash (again, this is just 
 127         // the way the native dialog works) 
 128         if ( *(m_path
.end() - 1) == _T(':') ) 
 135 int wxDirDialog::ShowModal() 
 137     wxWindow 
*parent 
= GetParent(); 
 140     bi
.hwndOwner      
= parent 
? GetHwndOf(parent
) : NULL
; 
 142     bi
.pszDisplayName 
= NULL
; 
 144     bi
.lpszTitle      
= m_message
.mb_str(); 
 146     bi
.lpszTitle      
= m_message
.c_str(); 
 148     bi
.ulFlags        
= BIF_RETURNONLYFSDIRS 
| BIF_STATUSTEXT
; 
 149     bi
.lpfn           
= BrowseCallbackProc
; 
 150     bi
.lParam         
= (LPARAM
)m_path
.c_str();    // param for the callback 
 152     static const int verComCtl32 
= wxApp::GetComCtl32Version(); 
 154     // we always add the edit box (it doesn't hurt anybody, does it?) if it is 
 155     // supported by the system 
 156     if ( verComCtl32 
>= 471 ) 
 158         bi
.ulFlags 
|= BIF_EDITBOX
; 
 161     // to have the "New Folder" button we must use the "new" dialog style which 
 162     // is also the only way to have a resizable dialog 
 164     // "new" style is only available in the version 5.0+ of comctl32.dll 
 165     const bool needNewDir 
= HasFlag(wxDD_NEW_DIR_BUTTON
); 
 166     if ( (needNewDir 
|| HasFlag(wxRESIZE_BORDER
)) && (verComCtl32 
>= 500) ) 
 170             bi
.ulFlags 
|= BIF_NEWDIALOGSTYLE
; 
 174             // Versions < 600 doesn't support BIF_NONEWFOLDERBUTTON 
 175             // The only way to get rid of the Make New Folder button is use 
 176             // the old dialog style which doesn't have the button thus we 
 177             // simply don't set the New Dialog Style for such comctl versions. 
 178             if (verComCtl32 
>= 600) 
 180                 bi
.ulFlags 
|= BIF_NEWDIALOGSTYLE
; 
 181                 bi
.ulFlags 
|= BIF_NONEWFOLDERBUTTON
; 
 186     // do show the dialog 
 187     LPITEMIDLIST pidl 
= SHBrowseForFolder(&bi
); 
 191         ItemListFree((LPITEMIDLIST
)bi
.pidlRoot
); 
 196         // Cancel button pressed 
 200     BOOL ok 
= SHGetPathFromIDList(pidl
, wxStringBuffer(m_path
, MAX_PATH
)); 
 206         wxLogLastError(wxT("SHGetPathFromIDList")); 
 214 // ---------------------------------------------------------------------------- 
 216 // ---------------------------------------------------------------------------- 
 219 BrowseCallbackProc(HWND hwnd
, UINT uMsg
, LPARAM lp
, LPARAM pData
) 
 223         case BFFM_INITIALIZED
: 
 224             // sent immediately after initialisation and so we may set the 
 225             // initial selection here 
 227             // wParam = TRUE => lParam is a string and not a PIDL 
 229             SendMessage(hwnd
, BFFM_SETSELECTION
, TRUE
, pData
); 
 233         case BFFM_SELCHANGED
: 
 234             // note that this doesn't work with the new style UI (MSDN doesn't 
 235             // say anything about it, but the comments in shlobj.h do!) but we 
 236             // still execute this code in case it starts working again with the 
 237             // "new new UI" (or would it be "NewUIEx" according to tradition?) 
 239                 // Set the status window to the currently selected path. 
 241                 if ( SHGetPathFromIDList((LPITEMIDLIST
)lp
, 
 242                                          wxStringBuffer(strDir
, MAX_PATH
)) ) 
 244                     // NB: this shouldn't be necessary with the new style box 
 245                     //     (which is resizable), but as for now it doesn't work 
 246                     //     anyhow (see the comment above) no harm in doing it 
 248                     // need to truncate or it displays incorrectly 
 249                     static const size_t maxChars 
= 37; 
 250                     if ( strDir
.length() > maxChars 
) 
 252                         strDir 
= strDir
.Right(maxChars
); 
 253                         strDir 
= wxString(wxT("...")) + strDir
; 
 256                     SendMessage(hwnd
, BFFM_SETSTATUSTEXT
, 
 257                                 0, (LPARAM
)strDir
.c_str()); 
 262         //case BFFM_VALIDATEFAILED: -- might be used to provide custom message 
 263         //                             if the user types in invalid dir name 
 270 static void ItemListFree(LPITEMIDLIST pidl
) 
 275         SHGetMalloc(&pMalloc
); 
 283             wxLogLastError(wxT("SHGetMalloc")); 
 289     #include "../generic/dirdlgg.cpp" 
 290 #endif // compiler/platform on which the code here compiles 
 292 #endif // wxUSE_DIRDLG