Also, made a funny function to use native TD when visual themes are turned off in the application or in Windows. By default windows only exposes CommCtl 5.8 then and your "normal" code does not find the implementation (that IS present in process memory)
Here is a code sample using two small pieces from JCL that make native implementation found and used even when UI theming tries ot prevent it. If anyone would care implanting it into the "mainline" STD should be straight-forward (back port to stock TStringList and copy/redo the function listing the loaded DLLs into TStrings).
uses JclSysInfo, JclStringLists, StrUtils;
{$EXTERNALSYM GetModuleHandleEx}
{$EXTERNALSYM GET_MODULE_HANDLE_EX_FLAG_PIN}
{$EXTERNALSYM GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT}
{$EXTERNALSYM GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS}
function GetModuleHandleEx(dwFlags: DWORD; lpModuleName: LPCTSTR; var phModule: HMODULE): BOOL; stdcall;
external kernel32 name 'GetModuleHandleExA';
const
GET_MODULE_HANDLE_EX_FLAG_PIN = $00000001;
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT = $00000002;
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS = $00000004;
procedure SynTaskDlgFindGhostComCtl6;
var
libs: iJclStringList;
i: integer;
h: HMODULE;
f: TFileName;
begin
// <legacy app name> only works with XP Themes off, otherwise it crashes
// This makes Delphi stock TaskDialog be turned off
// This also makes GetModuleHandle(comctl32) return DLL v. 5.80 that has no TaskDlg API
// However the close look at the process memory shows there are TWO DLLs loaded at time!!!
if Assigned(SynTaskDialog.TaskDialogIndirect) then
Exit; // Themes were enabled and we're already provided with ComCtl 6.x
libs := JclStringList(); // Jedi CodeLib
LoadedModulesList(libs.GetStringsRef, GetCurrentProcessId); // Jedi CodeLib
// observed in Win10 that comctl 6.1 is loaded later than conctl 5.8, getting
// a higher base address, hence we're scanning memory backwards
i := libs.Count - 1;
while i >= 0 do begin
if Assigned(SynTaskDialog.TaskDialogIndirect) then
Exit;
f := libs[i];
if EndsText(comctl32, f) then begin
h := NativeUInt(Pointer(libs.Objects[i]));
SynTaskDialog.TaskDialogIndirect := GetProcAddress(h,'TaskDialogIndirect');
// now we should create a warranty this DLL never gets unloaded
if Assigned(SynTaskDialog.TaskDialogIndirect) then
Win32Check( GetModuleHandleEx(
GET_MODULE_HANDLE_EX_FLAG_PIN or GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
pointer(h), h));
// LoadLibrary(f); pre-XP way, https://stackoverflow.com/questions/14302483/winapi-getmodulehandle-and-increment-refcount
end;
Dec(i);
end;
end;
made a "quick dirty change" to add native (not emulation) support for hyperlink and help events
works fine in delphi 2007 / windows 10 and i think should work with other Delphi verions too, the changes are simple
SynTaskDialog-2f92598c.zip
Also, made a funny function to use native TD when visual themes are turned off in the application or in Windows. By default windows only exposes
CommCtl 5.8
then and your "normal" code does not find the implementation (that IS present in process memory)Here is a code sample using two small pieces from JCL that make native implementation found and used even when UI theming tries ot prevent it. If anyone would care implanting it into the "mainline" STD should be straight-forward (back port to stock
TStringList
and copy/redo the function listing the loaded DLLs intoTStrings
).