使用GetOpenFileName 選擇檔案夾

來源:互聯網
上載者:User
關鍵字: GetOpenFileName CFileDialog SDK Folder我一直不喜歡預設的檔案夾選擇. 相反地,我喜歡MFC中的CFileDialog這種對話方塊.如何使用SDK,實現CFileDialog對話方塊選擇檔案夾, 是我要解釋和舉例的.1. CFileDialog 的實現. CFileDialog 是MFC的類,實現了定製Open, Save, 這些Common Dialog 的定製. 其內部一般是使GetOpenFileName實現的.  CFileDialog 中有一個 m_ofn 結構, 是 OPENFILENAME 類型. 他的詳細實現在 dlgfile.cpp 中.  有趣的是,在我的 vc9 中, CFileDialog 對Vista有特殊處置, 如果系統是Vista,而且設定了VistaStyle, 則CFileDialog使用 IFileDialog 介面而不是 GetOpenFileName,這個和我們關係不大,而且我也不打算把簡單問題複雜化. 一般而言, MFC 設定 m_ofn 的 flag 中包括了 OFN_ENABLEHOOK | OFN_EXPLORER, 這樣可以指定HookProc函數指標, 他可以接受各種訊息.MFC的是這樣寫的:m_ofn.lpfnHook = (COMMDLGPROC)_AfxCommDlgProc; 這是預設的Common Dialog 處理函數.2. 我們的實現. 前面說到這裡,我們基本上已經知道如何?選擇對話方塊的要求了. (1).首先設定 m_ofn.lpstrFile      WCHAR wcsFolderPath[MAX_PATH] = {0};      ::wcscpy( wcsFolderPath, L"*..*" );      m_ofn.lpstrFile  = wcsFolderPath;m_ofn.nMaxFile = sizeof( wcsFolderPath ) /sizeof(WCHAR);         "*..*" 將實現屏蔽所有檔案,只顯示對話方塊的效果(2).設定 m_ofn.hInstance = (HMODULE)GetCurrentProcess();//不要使用NULL,可能造成無法定製的問題(3).設定HookProc: m_ofn.lpfnHook = (COMMDLGPROC)MyFolderProc; 做完這些事,然後你在MyFolderProc中嘗試截獲 WM_COMMAND IDOK, IDCANCEL 這些訊息,結果是: 你什麼都截獲不到.很遺憾,HookProc處理的是一個類似"偽"對話方塊的一個控制代碼, 使用spy++, 你會發現,真正處理訊息的是HookProc中對話方塊控制代碼的父控制代碼.所以我們應該這麼做:
  1. LONG g_lOriWndProc = NULL;
  2. BOOL g_bReplaced = FALSE;
  3. UINT_PTR static __stdcall  MyFolderProc(  HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam )
  4. {
  5.         if( hdlg != NULL &&  g_bReplaced  == FALSE )
  6.         {
  7.             WCHAR wcsClassName1[MAX_PATH];
  8.             WCHAR wcsClassName2[MAX_PATH];
  9.             HWND hParent = ::GetParent( hdlg );
  10.             ::GetClassNameW( hParent, wcsClassName1 , sizeofWCAR(wcsClassName1) );
  11.             ::GetClassNameW( hdlg     , wcsClassName2 , sizeofWCAR(wcsClassName2) );
  12.             if( 0== ::wcscmp( wcsClassName1, wcsClassName2 ) )
  13.             {
  14.                 g_bReplaced  = TRUE;
  15.                  g_lOriWndProc  = ::SetWindowLongW( ::GetParent( hdlg ), GWL_WNDPROC , (LONG)_WndProc );
  16.             }
  17.         }
  18.         if( uiMsg == WM_NOTIFY )
  19.         {
  20.             LPOFNOTIFY lpOfNotify = (LPOFNOTIFY)lParam;
  21.             if( lpOfNotify->hdr.code == CDN_FOLDERCHANGE )
  22.             {
  23.                                   // your codes here
  24.             }
  25.         }
  26.     }
  27.     return FALSE;
  28. }
  29. LRESULT static __stdcall  _WndProc ( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam  )
  30. {
  31.     if( uMsg == WM_COMMAND )
  32.     {
  33.         if( wParam == IDOK )
  34.         {
  35.             //Your codes
  36.         }
  37.     }
  38.     return CallWndProc( (WNDPROC) g_lOriWndProc , hwnd, uMsg, wParam ,lParam );
  39. }

上面這段代碼揭示了如何定製Common Dialog 中的FileDialog. 你可以截獲IDOK.

但是有一個問題,你選擇一個檔案夾,然後點擊按鈕"開啟", 你會發現他預設開啟這個對話方塊,而不會關閉對話方塊,返回對話方塊所選擇的檔案夾路徑. 如何解決這個問題? 很容易, 我們在截獲IDOK時, 發送訊息 CDM_GETFOLDERPATH , 擷取檔案夾路徑,寫入目標緩衝, 然後發送訊息 IDCANCEL,對話方塊就會關閉了.我就是如此實現的. 我把GetOpenFileName封裝成了一個簡單的類,設定一個_bOK, 來標識究竟是單擊了ok,還是真的單擊了cancel (因為我最後發送了IDCANCEL訊息,如果不設定_bOK,無法辨別到底是OK,還是cancel ).網上有CFolderDialog這個簡單的類,但是是MFC的,對我來說還是如鯁在喉, 所以在這裡用SDK的方法實現之.希望大家對Windows 有更深的理解.

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.