123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- #include "main.h"
- #include "./folderbrowseex.h"
- #include "../nu/CGlobalAtom.h"
- #include <shobjidl.h>
- #include "../replicant/nu/AutoWide.h"
- static CGlobalAtom CLSPROP(L"FBEXDLG");
- #ifdef _WIN64
- #define LONGPTR_CAST LONG_PTR
- #else
- #define LONGPTR_CAST LONG
- #endif
- #define PATHTYPE_PIDL FALSE
- #define PATHTYPE_STRING TRUE
- BOOL CALLBACK browseEnumProc(HWND hwnd, LPARAM lParam)
- {
- wchar_t cl[32] = {0};
- GetClassName(hwnd, cl, ARRAYSIZE(cl));
- if (!lstrcmpi(cl, WC_TREEVIEW))
- {
- PostMessage(hwnd, TVM_ENSUREVISIBLE, 0, (LPARAM)TreeView_GetSelection(hwnd));
- return FALSE;
- }
- return TRUE;
- }
- static int WINAPI BrowseCallback_Helper(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
- {
- FolderBrowseEx *lpfbex = reinterpret_cast<FolderBrowseEx*>(lpData);
- if (!lpfbex) return 0;
- switch (uMsg)
- {
- case BFFM_INITIALIZED:
- lpfbex->hwnd = hwnd;
- if(SetPropW(hwnd, CLSPROP, (void*)lpData))
- {
- lpfbex->oldProc = (LONG_PTR) ((IsWindowUnicode(hwnd)) ? SetWindowLongPtrW(hwnd, DWLP_DLGPROC, (LONGPTR_CAST)WindowProc_Helper) : SetWindowLongPtrA(hwnd, DWLP_DLGPROC, (LONGPTR_CAST)WindowProc_Helper));
- if (NULL == lpfbex->oldProc) RemovePropW(hwnd, CLSPROP);
- }
- // this is not nice but it fixes the selection not working correctly on all OSes
- EnumChildWindows(hwnd, browseEnumProc, 0);
- break;
- }
- return lpfbex->BrowseCallback(uMsg, lParam);
- }
- static LRESULT WINAPI WindowProc_Helper(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- FolderBrowseEx *lpfbex = static_cast<FolderBrowseEx*>(GetPropW(hwnd, CLSPROP));
- if (!lpfbex) return 0;
- switch(uMsg)
- {
- case WM_NCDESTROY:
- lpfbex->DialogProc(uMsg, wParam, lParam);
- if (IsWindowUnicode(hwnd)) SetWindowLongPtrW(hwnd, DWLP_DLGPROC, (LONGPTR_CAST)lpfbex->oldProc);
- else SetWindowLongPtrA(hwnd, DWLP_DLGPROC, (LONGPTR_CAST)lpfbex->oldProc);
- RemovePropW(hwnd, CLSPROP);
- lpfbex->oldProc = NULL;
- lpfbex->hwnd = NULL;
- return 0;
- }
- return lpfbex->DialogProc(uMsg, wParam, lParam);
- }
- static void Initialize(FolderBrowseEx *lpfbx, LPCITEMIDLIST pidlRoot, UINT ulFlags, LPCWSTR lpszCaption, LPCWSTR lpszTitle)
- {
- lpfbx->pidlRoot = pidlRoot;
- lpfbx->ulFlags = ulFlags;
- lpfbx->lpszCaption = NULL;
- lpfbx->lpszTitle = NULL;
- lpfbx->image = -1;
- lpfbx->pidl = NULL;
- lpfbx->hwnd = NULL;
- lpfbx->oldProc = NULL;
- CoInitialize(NULL);
- lpfbx->pathExpanded.empty = TRUE;
- lpfbx->pathSelection.empty = TRUE;
- if (lpszCaption) lpfbx->SetCaption(lpszCaption);
- if (lpszTitle) lpfbx->SetTitle(lpszTitle);
- }
- FolderBrowseEx::FolderBrowseEx(LPCITEMIDLIST pidlRoot, UINT ulFlags, LPCWSTR lpszCaption, LPCWSTR lpszTitle)
- {
- Initialize(this, pidlRoot, ulFlags, lpszCaption, lpszTitle);
- }
- FolderBrowseEx::FolderBrowseEx(UINT ulFlags, LPCWSTR lpszCaption, LPCWSTR lpszTitle)
- {
- Initialize(this, NULL, ulFlags, lpszCaption, lpszTitle);
- }
- FolderBrowseEx::FolderBrowseEx(UINT ulFlags, LPCWSTR lpszTitle)
- {
- Initialize(this, NULL, ulFlags, L"", lpszTitle);
- }
- FolderBrowseEx::FolderBrowseEx(void)
- {
- Initialize(this, NULL, 0, L"", L"");
- }
- FolderBrowseEx::~FolderBrowseEx(void)
- {
- if (pidl) CoTaskMemFree(pidl);
- if (lpszTitle) free(lpszTitle);
- if (lpszCaption) free(lpszCaption);
- CoUninitialize();
- }
- HRESULT FolderBrowseEx::ParseDisplayName(LPCWSTR lpszPath, IBindCtx *pbc, LPITEMIDLIST *ppidl, SFGAOF sfgaoIn, SFGAOF *psfgaoOut)
- {
- IShellFolder *isf = NULL;
- HRESULT result;
- SFGAOF attrib;
- if (NOERROR != (result = SHGetDesktopFolder(&isf))) return result;
- attrib = sfgaoIn;
- result = isf->ParseDisplayName(NULL, pbc, (LPWSTR)lpszPath, NULL, ppidl, &attrib);
- isf->Release();
- if (S_OK != result) *ppidl = NULL;
- else if (psfgaoOut) *psfgaoOut = attrib;
- return result;
- }
- void FolderBrowseEx::SetExpanded(LPCITEMIDLIST pidlExpand)
- {
- pathExpanded.empty = FALSE;
- pathExpanded.type = PATHTYPE_PIDL;
- pathExpanded.value = (void*)pidlExpand;
- if (hwnd) SendMessage(BFFM_SETEXPANDED, pathExpanded.type, (LPARAM)pathExpanded.value);
- }
- void FolderBrowseEx::SetExpanded(LPCWSTR lpszExpand)
- {
- pathExpanded.empty = FALSE;
- pathExpanded.type = PATHTYPE_STRING;
- pathExpanded.value = (void*)lpszExpand;
- if (hwnd) SendMessage(BFFM_SETEXPANDED, pathExpanded.type, (LPARAM)pathExpanded.value);
- }
- void FolderBrowseEx::SetSelection(LPCITEMIDLIST pidlSelect)
- {
- pathSelection.empty = FALSE;
- pathSelection.type = PATHTYPE_PIDL;
- pathSelection.value = (void*)pidlSelect;
- if (hwnd) SendMessage(BFFM_SETSELECTIONW, pathSelection.type, (LPARAM)pathSelection.value);
- }
- void FolderBrowseEx::SetSelection(LPCWSTR lpszSelect)
- {
- pathSelection.empty = FALSE;
- pathSelection.type = PATHTYPE_STRING;
- pathSelection.value = (void*)lpszSelect;
- if (hwnd) SendMessage(BFFM_SETSELECTIONW, pathSelection.type, (LPARAM)pathSelection.value);
- }
- void FolderBrowseEx::SetCaption(LPCWSTR lpszCaption)
- {
- if (this->lpszCaption) free(this->lpszCaption);
- this->lpszCaption = _wcsdup((lpszCaption) ? lpszCaption : L"");
- if (hwnd) SetWindowText(lpszCaption);
- }
- void FolderBrowseEx::SetTitle(LPCWSTR lpszTitle)
- {
- if (this->lpszTitle) free(this->lpszTitle);
- this->lpszTitle = _wcsdup((lpszTitle) ? lpszTitle : L"");
- }
- LPITEMIDLIST FolderBrowseEx::Browse(HWND hwndOwner)
- {
- BROWSEINFOW bi = {0};
- bi.hwndOwner = hwndOwner;
- bi.pidlRoot = pidlRoot;
- bi.pszDisplayName = pszDisplayName;
- bi.lpszTitle = lpszTitle;
- bi.ulFlags = ulFlags;
- bi.lpfn = BrowseCallback_Helper;
- bi.lParam = (LPARAM)this;
- pidl = SHBrowseForFolderW(&bi);
- if (pidl) OnSelectionDone(pidl);
- image = (pidl) ? bi.iImage : -1;
- return pidl;
- }
- INT FolderBrowseEx::BrowseCallback(UINT uMsg, LPARAM lParam)
- {
- switch(uMsg)
- {
- case BFFM_INITIALIZED: OnInitialized(); break;
- case BFFM_IUNKNOWN: OnIUnknown((IUnknown*)lParam); break;
- case BFFM_SELCHANGED: OnSelectionChanged((LPCITEMIDLIST)lParam); break;
- case BFFM_VALIDATEFAILEDA: return OnValidateFailed(AutoWide((LPCSTR)lParam));
- case BFFM_VALIDATEFAILEDW: return OnValidateFailed((LPCWSTR)lParam);
- }
- return 0;
- }
- void FolderBrowseEx::OnInitialized(void)
- {
- if (!pathSelection.empty) SendMessage(BFFM_SETSELECTIONW, pathSelection.type, (LPARAM)pathSelection.value);
- if (!pathExpanded.empty) SendMessage(BFFM_SETEXPANDED, pathExpanded.type, (LPARAM)pathExpanded.value);
- SetWindowText(lpszCaption);
- }
- void FolderBrowseEx::OnSelectionChanged(LPCITEMIDLIST pidl)
- {
- }
- INT_PTR FolderBrowseEx::DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- return CallWindowProc(uMsg, wParam, lParam);
- }
- INT_PTR FolderBrowseEx::CallWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- return (IsWindowUnicode(hwnd)) ? ::CallWindowProcW((WNDPROC)oldProc, hwnd, uMsg, wParam, lParam)
- : ::CallWindowProcA((WNDPROC)oldProc, hwnd, uMsg, wParam, lParam);
- }
- void FolderBrowseEx::SetDialogResult(LRESULT result)
- {
- SetWindowLongPtr(hwnd, DWLP_MSGRESULT, (LONG)(LONG_PTR)result);
- }
|