|
Post by anixx on Mar 18, 2023 5:39:27 GMT -8
// ==WindhawkMod== // @id classic-file-picker // @name Classic File Picker // @description Redirect the Windows Vista+ file picker to the Windows XP one // @version 0.1 // @author Cynosphere // @include * // @compilerOptions -lole32 -lcomdlg32 // ==/WindhawkMod==
// ==WindhawkModReadme== /* # Classic File Picker */ // ==/WindhawkModReadme==
template<class S> CLSID CreateGUID(const S& hexString) { CLSID clsid; CLSIDFromString(hexString, &clsid);
return clsid; }
const CLSID CLSID_FileOpenDialog = CreateGUID(L"{DC1C5A9C-E88A-4dde-A5A1-60F82A20AEF7}"); const CLSID CLSID_FileOpenDialogLegacy = CreateGUID(L"{725F645B-EAED-4fc5-B1C5-D9AD0ACCBA5E}"); const CLSID CLSID_FileSaveDialog = CreateGUID(L"{c0b4e2f3-ba21-4773-8dba-335ec946eb8b}"); const CLSID CLSID_FileSaveDialogLegacy = CreateGUID(L"{AF02484C-A0A9-4669-9051-058AB12B9195}");
using CoCreateInstance_t = decltype(&CoCreateInstance); CoCreateInstance_t CoCreateInstance_Original; HRESULT WINAPI CoCreateInstance_Hook(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID riid, LPVOID *ppv) { if (rclsid == CLSID_FileOpenDialog) { return CoCreateInstance_Original(CLSID_FileOpenDialogLegacy, pUnkOuter, dwClsContext, riid, ppv); } else if (rclsid == CLSID_FileSaveDialog) { return CoCreateInstance_Original(CLSID_FileSaveDialogLegacy, pUnkOuter, dwClsContext, riid, ppv); }
return CoCreateInstance_Original(rclsid, pUnkOuter, dwClsContext, riid, ppv); }
BOOL Wh_ModInit() { Wh_SetFunctionHook((void*)CoCreateInstance, (void*)CoCreateInstance_Hook, (void**)&CoCreateInstance_Original);
return TRUE; }
void Wh_ModUninit() {}
This does require classic theme though to work properly, Windows will upgrade to the normal dialog no matter what but this solves my gripe with the Windhawk classic theme method. Is itpossible to add ClientEdge to the icon list area?
|
|
|
Post by anixx on Mar 22, 2023 4:37:27 GMT -8
Hello, guys! I found a way to force classic file picker and classic theme without the use of BasicThemer! What one should do: - Enable the Cynosphere open/save dialogs WindHawk mod - Enable the Classic theme using the usual method, such as ClassicThemeTray (or SimpleClassicTheme or similar) - Enable the Classic Theme WindHawk mod by Travis, but modify it by changing "SetThemeAppProperties(0);" to "SetThemeAppProperties(STAP_ALLOW_NONCLIENT);". Also, add a line "// @exclude ApplicationFrameHost.exe" next to "// @include *"
This way you will have the classic theme as with ClassicThemeTray, but also have the classic (XP-style) file picker!
There would be no BasicThemer-related glitches, such as delays and dialogs with wrong window decorations.
|
|
|
Post by anixx on Mar 22, 2023 4:44:21 GMT -8
Ah you've made me very happy. It works well, only issue I have it will not work unless I use Travis' classic theme script, which forces the title bar to not use the classic theme for me. I'm using 6sicsix's hybrid classic theme batch script, and even uninstalling 6sicsix's script, Travis's mod still produces the same results. Not sure if it's an issue with build 1607.  Thank you so much for making this a reality. I've wanted this for ages, thank you!  I use BasicThemer2(-detours) to fix the titlebars See my post above. You can get rid of BasicThemer.
|
|
|
Post by anixx on Mar 22, 2023 5:34:17 GMT -8
A mod that fuses the functionality of the mod by Cynosphere and Travis, also fixing the window captions that allows to get rid of BasicThemer and does not require the Travis mod: // ==WindhawkMod== // @id classic-file-picker // @name Classic File Picker // @description Redirect the Windows Vista+ file picker to the Windows XP one // @version 0.1 // @author Anixx // @include * // @exclude ApplicationFrameHost.exe // @exclude msedge.exe // @compilerOptions -lole32 -lcomdlg32 -luxtheme // ==/WindhawkMod==
// ==WindhawkModReadme== /* # Classic File Picker */ // ==/WindhawkModReadme==
#include <uxtheme.h>
template<class S> CLSID CreateGUID(const S& hexString) { CLSID clsid; CLSIDFromString(hexString, &clsid);
return clsid; }
const CLSID CLSID_FileOpenDialog = CreateGUID(L"{DC1C5A9C-E88A-4dde-A5A1-60F82A20AEF7}"); const CLSID CLSID_FileOpenDialogLegacy = CreateGUID(L"{725F645B-EAED-4fc5-B1C5-D9AD0ACCBA5E}"); const CLSID CLSID_FileSaveDialog = CreateGUID(L"{c0b4e2f3-ba21-4773-8dba-335ec946eb8b}"); const CLSID CLSID_FileSaveDialogLegacy = CreateGUID(L"{AF02484C-A0A9-4669-9051-058AB12B9195}");
using CoCreateInstance_t = decltype(&CoCreateInstance); CoCreateInstance_t CoCreateInstance_Original; HRESULT WINAPI CoCreateInstance_Hook(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID riid, LPVOID *ppv) { if (rclsid == CLSID_FileOpenDialog) { return CoCreateInstance_Original(CLSID_FileOpenDialogLegacy, pUnkOuter, dwClsContext, riid, ppv); } else if (rclsid == CLSID_FileSaveDialog) { return CoCreateInstance_Original(CLSID_FileSaveDialogLegacy, pUnkOuter, dwClsContext, riid, ppv); }
return CoCreateInstance_Original(rclsid, pUnkOuter, dwClsContext, riid, ppv); }
BOOL Wh_ModInit() { SetThemeAppProperties(STAP_ALLOW_NONCLIENT); Wh_SetFunctionHook((void*)CoCreateInstance, (void*)CoCreateInstance_Hook, (void**)&CoCreateInstance_Original); return TRUE; }
|
|
AnyKey
Sophomore Member

Posts: 134
OS: Windows 11 Pro 21H2
Theme: Classic Theme
CPU: AMD Ryzen 7 3700X
RAM: 16 GB
GPU: RTX 2070 S
|
Post by AnyKey on Mar 22, 2023 9:24:18 GMT -8
It works perfectly! Really nice.
Now all that's left is to work on ClientEdge. Is it possible to do by modifying the resource? Or AHK or code improvements required?
|
|
|
Post by anixx on Mar 22, 2023 9:24:53 GMT -8
Basically, the line SetThemeAppProperties(STAP_ALLOW_NONCLIENT); makes classic theme to be applied to the window contents, but does not touch the window border at all. So, the mod should not affect the window borders art all.
|
|
|
Post by anixx on Mar 22, 2023 9:35:37 GMT -8
Just noticed that under LibreOffice it uses a different set of icons. I wonder, why? 
|
|
|
Post by The Jackal on Mar 22, 2023 9:48:50 GMT -8
I have no such problems. Did you re-login after applying this? No. My bad. I've just logged out now and back in, and yeah, it's all working as it should. Classic title bars are applying everywhere as they should.
|
|
|
Post by The Jackal on Mar 22, 2023 10:01:15 GMT -8
Just noticed that under LibreOffice it uses a different set of icons. I wonder, why? View AttachmentThere's two versions of this dialog. It seems it's program dependent which version it calls up (the one introduced in XP, and other, the Windows 2000 one).
|
|
|
Post by anixx on Mar 22, 2023 10:01:49 GMT -8
If one wants to fix Edge appearance, one has to apply the Travis mode for edge only:
// ==WindhawkMod== // @id classic-theme-windows // @name Classic Theme Windows // @description Forces Classic Theme on all Windows // @version 0.1 // @author Travis // @include msedge.exe // @compilerOptions -luxtheme // ==/WindhawkMod==
// ==WindhawkModReadme== /* # Classic Theme Windows Forces Classic Theme on all Windows */ // ==/WindhawkModReadme==
#include <uxtheme.h>
BOOL Wh_ModInit() { Wh_Log(L"Init");
SetThemeAppProperties(0); return TRUE; } This way one can fix problems with any program which has glitches and problems with tranparency of the window border, this assigns them Aero Lite border.
|
|
|
Post by anixx on Mar 22, 2023 10:19:42 GMT -8
It works perfectly! Really nice.
Now all that's left is to work on ClientEdge. Is it possible to do by modifying the resource? Or AHK or code improvements required?
I think, this should be possible using WindHawk as well. In general, all options from ExplorerPatcher and 7+TT can be moved to WindHawk. For instance, there is no point now to use Explorer Patcher's "install as shell extension" mode any more, especially given it is not recommended. All the things (such as navbar and context menus in open-save dialogs) can be done with WindHawk now.
|
|
|
Post by The Jackal on Mar 22, 2023 10:56:50 GMT -8
I actually went back to check if these dialog had client edge on them on W2k/XP...they do. Is there a reason why MS would removed it from them? I mean, it seems a bit silly considering they up and replaced the dialogs themselves starting in Vista?
|
|
|
Post by OrthodoxWin32 on Mar 22, 2023 15:14:20 GMT -8
Superb discovery anixx, well done! I will try all of this as soon as I have time. Indeed, WindHawk can do everything that ExplorerPatcher or 7+TaskbarTweaker does. For my use, the ideal would be a mode that allows using the taskbar with the classic theme but without the labels (as in Windows 7).
|
|
|
Post by anixx on Mar 22, 2023 17:12:13 GMT -8
Just noticed that under LibreOffice it uses a different set of icons. I wonder, why? View AttachmentThere's two versions of this dialog. It seems it's program dependent which version it calls up (the one introduced in XP, and other, the Windows 2000 one). How to call the old one?
|
|
|
Post by The Jackal on Mar 23, 2023 1:38:52 GMT -8
There's two versions of this dialog. It seems it's program dependent which version it calls up (the one introduced in XP, and other, the Windows 2000 one). How to call the old one? I dont know how, just each program is different and calls up a different one. There's got to be a way to distinguish each one by internal name show-how and if we can work that out, maybe then we can isolate the type you want to show.
|
|
Cynosphere
New Member
Posts: 8
OS: Windows 10 Home 22H2
Theme: Amora Focus
CPU: AMD Ryzen 7 3700X
GPU: AMD Radeon RX 6700 XT
|
Post by Cynosphere on Apr 3, 2023 17:31:15 GMT -8
Using anixx 's snippet from here, I was able to add client edge to the ListView. BOOL CALLBACK SetClientEdge(HWND hWnd, LPARAM lParam) { DWORD dwProcessId = 0; DWORD dwThreadId = GetWindowThreadProcessId(hWnd, &dwProcessId); if (!dwThreadId || dwProcessId != GetCurrentProcessId()) { return TRUE; }
if (g_uiThreadId && g_uiThreadId != dwThreadId) { return TRUE; }
HWND cn = NULL; HWND p = hWnd; wchar_t bufr[256]; GetClassName(hWnd, bufr, 256);
// File picker if (lstrcmpW(bufr, L"#32770") == 0) { p = FindWindowEx(p, NULL, L"SHELLDLL_DefView", NULL); if(p != NULL) { p = FindWindowEx(p, NULL, L"SysListView32", NULL); if(p != NULL) { cn = p; } } }
if(cn != NULL) { SetWindowLongPtrW(cn, GWL_EXSTYLE, GetWindowLongPtrW(cn, GWL_EXSTYLE) | WS_EX_CLIENTEDGE); RECT rect; GetWindowRect(cn, &rect); SetWindowPos(cn, NULL, NULL, NULL, rect.right - rect.left + 1, rect.bottom - rect.top, SWP_NOMOVE | SWP_NOZORDER | SWP_DEFERERASE); SetWindowPos(cn, NULL, NULL, NULL, rect.right - rect.left, rect.bottom - rect.top, SWP_NOMOVE | SWP_NOZORDER | SWP_DEFERERASE); }
return TRUE; }
using CreateWindowExW_t = decltype(&CreateWindowExW); CreateWindowExW_t CreateWindowExW_Orig; HWND WINAPI CreateWindowExW_Hook(DWORD dwExStyle,LPCWSTR lpClassName,LPCWSTR lpWindowName,DWORD dwStyle,int X,int Y,int nWidth,int nHeight,HWND hWndParent,HMENU hMenu,HINSTANCE hInstance,LPVOID lpParam) { HWND hWnd = CreateWindowExW_Orig(dwExStyle,lpClassName,lpWindowName,dwStyle,X,Y,nWidth,nHeight,hWndParent,hMenu,hInstance,lpParam);
if (!hWnd) { return hWnd; }
if (g_uiThreadId && g_uiThreadId != GetCurrentThreadId()) { return hWnd; }
if (IsWindow(hWnd)) { if (!g_uiThreadId) { g_uiThreadId = GetCurrentThreadId(); }
EnumWindows(SetClientEdge, 0); }
return hWnd; }
// and then add this to Wh_ModInit Wh_SetFunctionHook((void*)CreateWindowExW, (void*)CreateWindowExW_Hook, (void**)&CreateWindowExW_Orig);
I've only had issues with this not applying to dialogs spawned from Electron programs (e.g. Discord, VSCode)
|
|
|
Post by anixx on Apr 3, 2023 19:16:51 GMT -8
I tried to add this to your Classic File Picker mod, it returns a lot of errors:
c:\ProgramData\Windhawk\EditorWorkspace\mod.wh.cpp:53:9: error: use of undeclared identifier 'g_uiThreadId' if (g_uiThreadId && g_uiThreadId != dwThreadId) { ^ c:\ProgramData\Windhawk\EditorWorkspace\mod.wh.cpp:53:25: error: use of undeclared identifier 'g_uiThreadId' if (g_uiThreadId && g_uiThreadId != dwThreadId) { ^ c:\ProgramData\Windhawk\EditorWorkspace\mod.wh.cpp:97:9: error: use of undeclared identifier 'g_uiThreadId'; did you mean 'GetThreadId'? if (g_uiThreadId && g_uiThreadId != GetCurrentThreadId()) { ^~~~~~~~~~~~ GetThreadId c:/Program Files/Windhawk/Compiler/include/processthreadsapi.h:40:27: note: 'GetThreadId' declared here WINBASEAPI DWORD WINAPI GetThreadId (HANDLE Thread); ^ c:\ProgramData\Windhawk\EditorWorkspace\mod.wh.cpp:97:25: error: use of undeclared identifier 'g_uiThreadId' if (g_uiThreadId && g_uiThreadId != GetCurrentThreadId()) { ^ c:\ProgramData\Windhawk\EditorWorkspace\mod.wh.cpp:102:14: error: use of undeclared identifier 'g_uiThreadId'; did you mean 'GetThreadId'? if (!g_uiThreadId) { ^~~~~~~~~~~~ GetThreadId c:/Program Files/Windhawk/Compiler/include/processthreadsapi.h:40:27: note: 'GetThreadId' declared here WINBASEAPI DWORD WINAPI GetThreadId (HANDLE Thread); ^ c:\ProgramData\Windhawk\EditorWorkspace\mod.wh.cpp:102:14: warning: address of function 'GetThreadId' will always evaluate to 'true' [-Wpointer-bool-conversion] if (!g_uiThreadId) { ~^~~~~~~~~~~~ c:\ProgramData\Windhawk\EditorWorkspace\mod.wh.cpp:102:14: note: prefix with the address-of operator to silence this warning if (!g_uiThreadId) { ^ & c:\ProgramData\Windhawk\EditorWorkspace\mod.wh.cpp:103:13: error: use of undeclared identifier 'g_uiThreadId' g_uiThreadId = GetCurrentThreadId(); ^ 1 warning and 6 errors generated.
|
|
|
Post by anixx on Apr 3, 2023 19:26:50 GMT -8
Well, added DWORD g_uiThreadId; to the top, now works.
I think, this is great!
P.S. Confirming: does not work in Electron apps.
|
|
|
Post by anixx on Apr 3, 2023 20:14:35 GMT -8
When changing the displayed folder in the dialog, for insctance, entering a folder, the ClientEdge disappears.
|
|
|
Post by anixx on Apr 4, 2023 0:42:18 GMT -8
By the way, the file picker dialog has a ListBox which by default has ClientEdge, but invisible, it occupies the same area as SysListView32. It retains clientedge when changing the folder. The problem is, it is empty.
|
|