aboutsummaryrefslogtreecommitdiff
path: root/Src/Plugins/Library/ml_local/FolderBrowseEx.cpp
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Plugins/Library/ml_local/FolderBrowseEx.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/Plugins/Library/ml_local/FolderBrowseEx.cpp')
-rw-r--r--Src/Plugins/Library/ml_local/FolderBrowseEx.cpp239
1 files changed, 239 insertions, 0 deletions
diff --git a/Src/Plugins/Library/ml_local/FolderBrowseEx.cpp b/Src/Plugins/Library/ml_local/FolderBrowseEx.cpp
new file mode 100644
index 00000000..2c1b0de1
--- /dev/null
+++ b/Src/Plugins/Library/ml_local/FolderBrowseEx.cpp
@@ -0,0 +1,239 @@
+#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);
+} \ No newline at end of file