From 22ea0c8f932ccf6fce72622c18a5a434ac8d6d91 Mon Sep 17 00:00:00 2001 From: WeberAndre Date: Wed, 27 Nov 2024 15:24:34 +0100 Subject: [PATCH] Support DPI per Monitor V2 and Owner Draw of non VCL menus Use DPI from Windows Handle in a Per Monitor V2 DPI environment with different DPI values instead of MainForm. Allow Owner Draw of non VCL Items - needed for TOpenDialog / TSaveDialog with modern style. If not the last recently visited locations drop down will show nothing - just a empty rectangle. --- .gitignore | 2 ++ Common/Vcl.Styles.Utils.Menus.pas | 52 +++++++++++++++++++++++++++++-- 2 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5b9bd87 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ + +*.bak diff --git a/Common/Vcl.Styles.Utils.Menus.pas b/Common/Vcl.Styles.Utils.Menus.pas index 94ca4a8..bdffdd6 100644 --- a/Common/Vcl.Styles.Utils.Menus.pas +++ b/Common/Vcl.Styles.Utils.Menus.pas @@ -533,8 +533,14 @@ procedure TSysPopupStyleHook.DrawItem(Canvas: TCanvas; const Index: integer; con LParentMenu: TMenu; ItemRect2: TRect; - + LMenuItemInfo: TMenuItemInfo; + LGUIThreadinfo: TGUIThreadinfo; + DrawItemStruct: TDrawItemStruct; begin + //AW: 27.11.2024 - Use DPI from Window instead of MainForm + if CheckPerMonitorV2SupportForWindow(Handle) then + LPixelsPerInch := GetDPIForWindow(Handle) + else if Assigned(Application.Mainform) then LPixelsPerInch := Application.MainForm.Monitor.PixelsPerInch else @@ -547,6 +553,48 @@ procedure TSysPopupStyleHook.DrawItem(Canvas: TCanvas; const Index: integer; con { Fast access . } LSysPopupItem := Items[Index]; // Do not destroy !! DC := Canvas.Handle; + + if (Style <> isSep) and (LSysPopupItem.VCLMenuItems = nil) and + (ItemText = '') and LSysPopupItem.IsItemOwnerDraw then + begin + // redirect owner draw of non VCL MenuItems to Owner Window Handle + // assume they use themed methods to draw the MenuItem + // --> File Dialogs uses this + LGUIThreadinfo.cbSize := sizeof(TGUIThreadinfo); + if GetGUIThreadInfo(GetCurrentThreadID(), LGUIThreadinfo) then + begin + DrawItemStruct.CtlType := ODT_MENU; + DrawItemStruct.CtlID := 0; + DrawItemStruct.itemID := LSysPopupItem.GetItemID; + DrawItemStruct.itemAction := ODA_DRAWENTIRE; + DrawItemStruct.itemState := 0; + + if isDefault in State then + DrawItemStruct.itemState := DrawItemStruct.itemState or ODS_DEFAULT; + if isHot in State then + DrawItemStruct.itemState := DrawItemStruct.itemState or ODS_HOTLIGHT; // ODS_SELECTED; + if isDisabled in State then + DrawItemStruct.itemState := DrawItemStruct.itemState or ODS_DISABLED; + if isChecked in State then + DrawItemStruct.itemState := DrawItemStruct.itemState or ODS_CHECKED; + + DrawItemStruct.hwndItem := FMenu; + DrawItemStruct.hDC := DC; + DrawItemStruct.rcItem := ItemRect2; + + FillChar(LMenuItemInfo, sizeof(TMenuItemInfo), Char(0)); + LMenuItemInfo.cbSize := sizeof(TMenuItemInfo); + LMenuItemInfo.fMask := MIIM_DATA; + if GetMenuItemInfo(FMenu, LSysPopupItem.FIndex, True, LMenuItemInfo) then + DrawItemStruct.itemData := LMenuItemInfo.dwItemData + else + DrawItemStruct.itemData := 0; + + SendMessage( LGUIThreadinfo.hwndMenuOwner, WM_DRAWITEM, 0, NativeInt(@DrawItemStruct) ); + exit; + end; + end; + R := ItemRect2; LThemedMenu := tmPopupItemNormal; if isHot in State then @@ -870,7 +918,7 @@ procedure TSysPopupStyleHook.DrawItem(Canvas: TCanvas; const Index: integer; con DrawText(Canvas.Handle, LDetails, Copy(ItemText, 1, P), LTextRect, LTextFormat) end else - DrawText(Canvas.Handle, LDetails, ItemText, LTextRect, LTextFormat) + DrawText(Canvas.Handle, LDetails, ItemText, LTextRect, LTextFormat); end; {Draw vertical menu bar}