home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 217 / DPCS0306DVD.ISO / Toolkit / Internet / FileZilla / Server / FileZilla_Server-0.9.11.exe / source / interface / misc / BrowseForFolder.cpp next >
Encoding:
C/C++ Source or Header  |  2004-12-01  |  8.8 KB  |  340 lines

  1. //////////////////////////////////////////////////////////////////////
  2. //
  3. // ShellBrowser.cpp: implementation of the CShellBrowser class.
  4. //
  5.  
  6. #include "stdafx.h"
  7. #include "BrowseForFolder.h"
  8.  
  9. #if defined(_DEBUG) && !defined(MMGR)
  10. #undef THIS_FILE
  11. static char THIS_FILE[]=__FILE__;
  12. #define new DEBUG_NEW
  13. #endif
  14.  
  15. //////////////////////////////////////////////////////////////////////
  16. //
  17. // Construction/Destruction
  18. //
  19.  
  20. CBrowseForFolder::CBrowseForFolder(const HWND hParent /*= NULL*/, const LPITEMIDLIST pidl /*= NULL*/, const int nTitleID /*= 0*/)
  21. {
  22.     m_hwnd = NULL;
  23.     SetOwner(hParent);
  24.     SetRoot(pidl);
  25.     SetTitle(nTitleID);
  26.     m_bi.lpfn = BrowseCallbackProc;
  27.     m_bi.lParam = reinterpret_cast<long>(this);
  28.     m_bi.pszDisplayName = m_szSelected;
  29. }
  30.  
  31. CBrowseForFolder::CBrowseForFolder(const HWND hParent, const LPITEMIDLIST pidl, const CString& strTitle)
  32. {
  33.     m_hwnd = NULL;
  34.     SetOwner(hParent);
  35.     SetRoot(pidl);
  36.     SetTitle(strTitle);
  37.     m_bi.lpfn = BrowseCallbackProc;
  38.     m_bi.lParam = reinterpret_cast<long>(this);
  39.     m_bi.pszDisplayName = m_szSelected;
  40. }
  41.  
  42. CBrowseForFolder::~CBrowseForFolder()
  43. {
  44.  
  45. }
  46.  
  47. //////////////////////////////////////////////////////////////////////
  48. //
  49. // Implementation
  50. //
  51.  
  52. void CBrowseForFolder::SetOwner(const HWND hwndOwner)
  53. {
  54.     if (m_hwnd != NULL)
  55.         return;
  56.  
  57.     m_bi.hwndOwner = hwndOwner;
  58. }
  59.  
  60. void CBrowseForFolder::SetRoot(const LPITEMIDLIST pidl)
  61. {
  62.     if (m_hwnd != NULL)
  63.         return;
  64.  
  65.     m_bi.pidlRoot = pidl;
  66. }
  67.  
  68. CString CBrowseForFolder::GetTitle() const
  69. {
  70.     return m_bi.lpszTitle;
  71. }
  72.  
  73. void CBrowseForFolder::SetTitle(const CString& strTitle)
  74. {
  75.     if (m_hwnd != NULL)
  76.         return;
  77.  
  78.     m_pchTitle=strTitle;
  79.     m_bi.lpszTitle = m_pchTitle;
  80. }
  81.  
  82. bool CBrowseForFolder::SetTitle(const int nTitle)
  83. {
  84.     if (nTitle <= 0)
  85.         return false;
  86.  
  87.     CString strTitle;
  88.     if(!strTitle.LoadString(static_cast<size_t>(nTitle)))
  89.     {
  90.         return false;
  91.     }
  92.     SetTitle(strTitle);
  93.     return true;
  94. }
  95.  
  96. void CBrowseForFolder::SetFlags(const UINT ulFlags)
  97. {
  98.     if (m_hwnd != NULL)
  99.         return;
  100.  
  101.     m_bi.ulFlags = ulFlags;
  102. }
  103.  
  104. CString CBrowseForFolder::GetSelectedFolder() const
  105. {
  106.     return m_szSelected;
  107. }
  108.  
  109. bool CBrowseForFolder::SelectFolder()
  110. {
  111.     bool bRet = false;
  112.  
  113.     LPITEMIDLIST pidl;
  114.     if ((pidl = ::SHBrowseForFolder(&m_bi)) != NULL)
  115.     {
  116.         m_strPath.Empty();
  117.         if (SUCCEEDED(::SHGetPathFromIDList(pidl, m_szSelected)))
  118.         {
  119.             bRet = true;
  120.             m_strPath = m_szSelected;
  121.         }
  122.  
  123.         LPMALLOC pMalloc;
  124.         //Retrieve a pointer to the shell's IMalloc interface
  125.         if (SUCCEEDED(SHGetMalloc(&pMalloc)))
  126.         {
  127.             // free the PIDL that SHBrowseForFolder returned to us.
  128.             pMalloc->Free(pidl);
  129.             // release the shell's IMalloc interface
  130.             (void)pMalloc->Release();
  131.         }
  132.     }
  133.     m_hwnd = NULL;
  134.  
  135.     return bRet;
  136. }
  137.  
  138. void CBrowseForFolder::OnInit() const
  139. {
  140.  
  141. }
  142.  
  143. void CBrowseForFolder::OnSelChanged(const LPITEMIDLIST pidl) const
  144. {
  145.     (void)pidl;
  146. }
  147.  
  148. void CBrowseForFolder::EnableOK(const bool bEnable) const
  149. {
  150.     if (m_hwnd == NULL)
  151.         return;
  152.  
  153.     (void)SendMessage(m_hwnd, BFFM_ENABLEOK, NULL, static_cast<WPARAM>(bEnable));
  154. }
  155.  
  156. void CBrowseForFolder::SetSelection(const LPITEMIDLIST pidl) const
  157. {
  158.     if (m_hwnd == NULL)
  159.         return;
  160.  
  161.     (void)SendMessage(m_hwnd, BFFM_SETSELECTION, FALSE, reinterpret_cast<long>(pidl));
  162. }
  163.  
  164. void CBrowseForFolder::SetSelection(const CString& strPath) const
  165. {
  166.     if (m_hwnd == NULL)
  167.         return;
  168.  
  169.     (void)SendMessage(m_hwnd, BFFM_SETSELECTION, TRUE, reinterpret_cast<long>(LPCTSTR(strPath)));
  170. }
  171.  
  172. void CBrowseForFolder::SetStatusText(const CString& strText) const
  173. {
  174.     if (m_hwnd == NULL)
  175.         return;
  176.  
  177.     CString oPathString = FormatLongPath(strText);
  178.  
  179.     (void)SendMessage(m_hwnd, BFFM_SETSTATUSTEXT, NULL,
  180.         reinterpret_cast<long>(LPCTSTR(oPathString/*strText*/)));
  181. }
  182.  
  183. int __stdcall CBrowseForFolder::BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
  184. {
  185.     CBrowseForFolder* pbff = reinterpret_cast<CBrowseForFolder*>(lpData);
  186.     pbff->m_hwnd = hwnd;
  187.     if (uMsg == BFFM_INITIALIZED)
  188.         pbff->OnInit();
  189.     else if (uMsg == BFFM_SELCHANGED)
  190.         pbff->OnSelChanged(reinterpret_cast<LPITEMIDLIST>(lParam));
  191.     
  192.     return 0;
  193. }
  194.  
  195. /*************************
  196. 3. Finally, the body of FormatLongPath looks like that:
  197. **************************/
  198.  
  199. CString CBrowseForFolder::FormatLongPath(CString oLongPath) const
  200. {
  201.     //will be passed instead of original
  202.     CString oModifString( oLongPath );
  203.  
  204.     //will be used to get measurements
  205.     CWnd oWnd;
  206.  
  207.     if( !oModifString.IsEmpty() && IsWindow(m_hwnd) && oWnd.Attach(m_hwnd) )
  208.     {
  209.         //margins must be considered
  210.         RECT Rect = { 0, 0, 7, 0 };    //my lucky guess the margin would be seven units. It used to be 7 in resource editor, so why not here?
  211.         int nMargin = MapDialogRect( m_hwnd, &Rect ) ? Rect.right : 20;    //convert into pixels then
  212.         
  213.         //measure the width first
  214.         CRect oClientRect;
  215.         oWnd.GetClientRect( &oClientRect );
  216.         oClientRect.NormalizeRect();
  217.         int nMaxTextWidth = oClientRect.Width() - nMargin*2;
  218.         
  219.         CClientDC oClientDC(&oWnd);
  220.  
  221.         //trying to determine the system metrix to create apropriate fonts for measurement
  222.         NONCLIENTMETRICS NonClientMetrics;
  223.         
  224.         NonClientMetrics.cbSize = sizeof(NONCLIENTMETRICS);
  225.         
  226.         BOOL bSystemMetrics = SystemParametersInfo( SPI_GETNONCLIENTMETRICS, 
  227.             NonClientMetrics.cbSize, 
  228.             &NonClientMetrics,
  229.             0 );
  230.  
  231.         if( bSystemMetrics )
  232.         {
  233.             CFont oMessageFont;//lets create the fonts same as the selected Message Font on the Display/Appearance tab
  234.  
  235.             if( oMessageFont.CreateFontIndirect(&NonClientMetrics.lfMessageFont) )
  236.             {
  237.                 oClientDC.SelectObject( &oMessageFont );
  238.             }
  239.         }
  240.         else
  241.         {
  242.             oClientDC.SelectStockObject( SYSTEM_FONT );    //it MUST NOT happen, but in case...
  243.         }
  244.         
  245.         //measure the actual text width
  246.         int nTextWidth = oClientDC.GetTextExtent( oModifString ).cx;
  247.  
  248.         //to check whether it's correct uncoment below and change directory few times...
  249.         //oClientDC.SelectStockObject( BLACK_PEN );
  250.         //oClientDC.Rectangle( 0, 0, nMargin, nMargin*5 );
  251.         //oClientDC.Rectangle( nMaxTextWidth+nMargin, 0, oClientRect.Width(), nMargin*5 );
  252.         //oClientDC.Rectangle( nMargin, 0, nMaxTextWidth+nMargin, nMargin );
  253.         //oClientDC.TextOut( nMargin, 0, oModifString );
  254.         
  255.         //after all this measurements time to do the real job
  256.         if( nTextWidth > nMaxTextWidth )
  257.         {
  258.             int nRootDirIndex, nLastDirIndex;
  259.  
  260.             //this is the testing line:
  261.             //oModifString = "\\\\computer_name\\dir1\\subdir1" + oModifString.Right(oModifString.GetLength() - 2 );
  262.  
  263.             nRootDirIndex = oModifString.Find( '\\' );
  264.             nLastDirIndex = oModifString.ReverseFind( '\\' );
  265.  
  266.             if( nRootDirIndex == 0 )    //we have to deal with the network 'drive', which would look like that: \\computer_name\dir1\subdir1
  267.             {
  268.                 nRootDirIndex = oModifString.Find( '\\', nRootDirIndex+1 );
  269.                 if( nRootDirIndex != -1 )
  270.                 {
  271.                     nRootDirIndex = oModifString.Find( '\\', nRootDirIndex+1 );
  272.                 }
  273.             }
  274.  
  275.             if( nRootDirIndex != -1 && nLastDirIndex != -1 )
  276.             {
  277.                 nRootDirIndex += 1;    //increase for the tactical reasons
  278.  
  279.                 CString oDottedText( "..." );//this three dots will be used to indicate the cut part of the path
  280.  
  281.                 CString oRootDirectory;     //this can be cut as the last one
  282.                 CString oMidDirectoryPart;    //we will try to shorten this part first
  283.                 CString oLastDirectory;     //and then, if still too long we'll cut this one
  284.                 
  285.                 oRootDirectory =    oModifString.Left( nRootDirIndex );
  286.                 oMidDirectoryPart =    oModifString.Mid( nRootDirIndex, nLastDirIndex - nRootDirIndex );
  287.                 oLastDirectory =    oModifString.Mid( nLastDirIndex );
  288.                 
  289.                 while( nTextWidth > nMaxTextWidth )
  290.                 {
  291.                     int nMidPartLenght = oMidDirectoryPart.GetLength();
  292.  
  293.                     oModifString = oRootDirectory + oMidDirectoryPart + oDottedText + oLastDirectory;
  294.  
  295.                     //measure the actual text width again
  296.                     nTextWidth = oClientDC.GetTextExtent( oModifString ).cx;
  297.                     
  298.                     if( nMidPartLenght > 0 )
  299.                     {
  300.                         //prepare for the next loop (if any)
  301.                         oMidDirectoryPart = oMidDirectoryPart.Left(oMidDirectoryPart.GetLength() - 1 );
  302.                     }
  303.                     else
  304.                     {
  305.                         int nLastDirectoryLenght = oLastDirectory.GetLength();
  306.                         
  307.                         if( nLastDirectoryLenght > 0 )
  308.                         {
  309.                             //prepare for the next loop (if any)
  310.                             oLastDirectory = oLastDirectory.Right(oLastDirectory.GetLength() - 1 );
  311.                         }
  312.                         else
  313.                         {
  314.                             //should not come here, what size of the fonts are you using?!
  315.                             //anyway, we will do different now, cutting from the end...
  316.                             int nRootDirectoryLenght = oRootDirectory.GetLength();
  317.  
  318.                             if( nRootDirectoryLenght > 0 )
  319.                             {
  320.                                 oRootDirectory = oRootDirectory.Left(oRootDirectory.GetLength() - 1 );
  321.                             }
  322.                             else
  323.                             {
  324.                                 TRACE0( "Mayday, Mayday!!!\n" );
  325.                                 oModifString = oLongPath;
  326.                                 //something wrong, give me a...
  327.                                 break;
  328.                             }
  329.                         }
  330.                     }
  331.                 }//end while
  332.             }
  333.         }
  334.  
  335.         oWnd.Detach();
  336.     }
  337.  
  338.     return oModifString;
  339. }
  340.