WildByDesign Posted February 23 Posted February 23 (edited) There seems to be a bug with the custom tab control drawing in _WinProc. It randomly erases whatever content is in the tab during the custom drawing. For example, in example script without any modifications, the label with the text Sample Tab gets erased on GUI startup approx. 20% of the time. Also, when switching back and forth from either tab Two or Three back to tab One, the label is also getting erased in that scenario as well approx. 20% of the time. I haven't been able to figure out the root cause but it seems mostly to be a timing issue. EDIT: I also tried modifying the code slightly by adding a simple checkbox in the tab and the checkbox randomly gets erased as well. At first I was thinking maybe the issue was related to the label coloring. But it definitely has to be the custom tab drawing causing the contents of the tab to be erased. Edited February 23 by WildByDesign
UEZ Posted February 23 Author Posted February 23 The problem was that the entired tab client area was overwritten in _WinProc -> WM_PAINT section by _WinAPI_BitBlt. I exluded that client area. I added also a repaint when minimized GUI was restored again and added a checkbox on 2nd tab. Should work now - please test (see 1st post). WildByDesign 1 Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ
WildByDesign Posted February 23 Posted February 23 3 hours ago, UEZ said: The problem was that the entired tab client area was overwritten in _WinProc -> WM_PAINT section by _WinAPI_BitBlt. I exluded that client area. I added also a repaint when minimized GUI was restored again and added a checkbox on 2nd tab. Should work now - please test (see 1st post). I got a chance to test the fix now and it works perfectly. Thank you.
UEZ Posted February 27 Author Posted February 27 I created a fake DateTimePicker control. Does anyone know in which DLL or other file the original icon is hidden? argumentum 1 Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ
WildByDesign Posted February 27 Posted February 27 Here is the closest that I could find. This is in shell32.dll.mun UEZ 1
WildByDesign Posted February 28 Posted February 28 I have a couple of suggestions if you are interested. I noticed that you implemented some of the newer Win11 DarkMode_DarkTheme stuff. They have a really nice dark mode progress theme now as well. Case "msctls_progress32" _WinAPI_SetWindowTheme($hCtrl, "DarkMode_CopyEngine", "Progress") I really like your idea for drawing the dark mode checkboxes for the TreeView control. Just some suggestions to match the regular checkbox control: The black showing on the outside of the checkbox rectangle should be transparent. The black is also covering up part of the TreeView item selection rectangle. Transparency on the outside of the checkbox rectangle would fix that also. The fill color on the inside of the unchecked checkbox is 0x242424 (on the regular dark mode checkbox) Keep up the fantastic work. I have learned so much from you.
WildByDesign Posted March 4 Posted March 4 I noticed a bug with _WM_INITMENUPOPUP last week but I forgot to mention. Basically, I don't think it is working at all and may not be necessary. System menu, top menus and context menu all trigger your _WM_INITMENUPOPUP which is good. However, I think that the problem is that _WinAPI_GetForegroundWindow is not capable of detecting #32768 and it never gets past there. The only way that I was able to successfully get these #32768 handles was with a WinEventHook. But _WinAPI_GetForegroundWindow does not seem to get them. With or without the sleep timer, it does not seem to matter. Here is your function with a few ConsoleWrites to see how far it makes it: expandcollapse popupFunc _WM_INITMENUPOPUP($hWnd, $iMsg, $wParam, $lParam) ; wParam = HMENU of the popup, lParam = position/index - not needed here ; A small delay sometimes helps to ensure the popup window exists ConsoleWrite("_WM_INITMENUPOPUP initial trigger." & @CRLF) Sleep(100) ; The foreground window is most likely the new menu popup Local $hPopup = _WinAPI_GetForegroundWindow() If Not $hPopup Then Return $GUI_RUNDEFMSG ConsoleWrite("_WM_INITMENUPOPUP after _WinAPI_GetForegroundWindow." & @CRLF) Local $sCls = StringLower(_WinAPI_GetClassName($hPopup)) If $sCls <> "#32768" And $sCls <> "popupmenu" Then ; if no menu popup is detected -> do nothing Return $GUI_RUNDEFMSG EndIf ; Set Theme + AllowDarkMode on the popup itself _WinAPI_SetWindowTheme($hPopup, "DarkMode_Explorer", "") _WinAPI_AllowDarkModeForWindow($hPopup, True) ConsoleWrite("_WM_INITMENUPOPUP coloring." & @CRLF) ; Also apply the theme to all child windows of the popup (e.g., scrollbars) Local $hChild = _WinAPI_GetWindow($hPopup, $GW_CHILD) While $hChild Local $sChildCls = StringLower(_WinAPI_GetClassName($hChild)) ; apply theme specifically for scrollbars, UpDown, etc. If $sChildCls = "scrollbar" Or $sChildCls = "msctls_updown32" Or $sChildCls = "traynotifywnd" Then _WinAPI_SetWindowTheme($hChild, "DarkMode_Explorer", "") _WinAPI_AllowDarkModeForWindow($hChild, True) Else ; try generically _WinAPI_SetWindowTheme($hChild, "DarkMode_Explorer", "") _WinAPI_AllowDarkModeForWindow($hChild, True) EndIf $hChild = _WinAPI_GetWindow($hChild, $GW_HWNDNEXT) WEnd ; Force refresh so the change is visible immediately _WinAPI_FlushMenuThemes() _WinAPI_RefreshImmersiveColorPolicyState() _WinAPI_RedrawWindow($hPopup, 0, 0, BitOR($RDW_INVALIDATE, $RDW_UPDATENOW)) Return $GUI_RUNDEFMSG EndFunc ;==>_WM_INITMENUPOPUP
UEZ Posted March 4 Author Posted March 4 _WM_INITMENUPOPUP() is useless and can be removed. WildByDesign 1 Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ
WildByDesign Posted Tuesday at 05:42 PM Posted Tuesday at 05:42 PM For applying dark mode to your tooltips, you can add this right before GUISetState: #include <WinAPIProc.au3> ;... Local $aData = _WinAPI_EnumProcessWindows(0, False) For $i = 1 To $aData[0][0] If $aData[$i][1] = "tooltips_class32" Then _WinAPI_SetWindowTheme($aData[$i][0], 'DarkMode_Explorer', 'ToolTip') Next ;... GUISetState(@SW_SHOW) UEZ 1
mLipok Posted Tuesday at 07:34 PM Posted Tuesday at 07:34 PM (edited) Just for references: https://www.autoitscript.com/trac/autoit/ticket/4013 Edited Tuesday at 07:34 PM by mLipok Signature beginning:* Please remember: "AutoIt"..... * Wondering who uses AutoIt and what it can be used for ? * Forum Rules ** ADO.au3 UDF * POP3.au3 UDF * XML.au3 UDF * IE on Windows 11 * How to ask ChatGPT for AutoIt Code * for other useful stuff click the following button: Spoiler Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind. My contribution (my own projects): * Debenu Quick PDF Library - UDF * Debenu PDF Viewer SDK - UDF * Acrobat Reader - ActiveX Viewer * UDF for PDFCreator v1.x.x * XZip - UDF * AppCompatFlags UDF * CrowdinAPI UDF * _WinMergeCompare2Files() * _JavaExceptionAdd() * _IsBeta() * Writing DPI Awareness App - workaround * _AutoIt_RequiredVersion() * Chilkatsoft.au3 UDF * TeamViewer.au3 UDF * JavaManagement UDF * VIES over SOAP * WinSCP UDF * GHAPI UDF - modest begining - comunication with GitHub REST API * ErrorLog.au3 UDF - A logging Library * Include Dependency Tree (Tool for analyzing script relations) * Show_Macro_Values.au3 * My contribution to others projects or UDF based on others projects: * _sql.au3 UDF * POP3.au3 UDF * RTF Printer - UDF * XML.au3 UDF * ADO.au3 UDF * SMTP Mailer UDF * Dual Monitor resolution detection * * 2GUI on Dual Monitor System * _SciLexer.au3 UDF * SciTE - Lexer for console pane * Useful links: * Forum Rules * Forum etiquette * Forum Information and FAQs * How to post code on the forum * AutoIt Online Documentation * AutoIt Online Beta Documentation * SciTE4AutoIt3 getting started * Convert text blocks to AutoIt code * Games made in Autoit * Programming related sites * Polish AutoIt Tutorial * DllCall Code Generator * Wiki: * Expand your knowledge - AutoIt Wiki * Collection of User Defined Functions * How to use HelpFile * Good coding practices in AutoIt * OpenOffice/LibreOffice/XLS Related: WriterDemo.au3 * XLS/MDB from scratch with ADOX IE Related: * How to use IE.au3 UDF with AutoIt v3.3.14.x * Why isn't Autoit able to click a Javascript Dialog? * Clicking javascript button with no ID * IE document >> save as MHT file * IETab Switcher (by LarsJ ) * HTML Entities * _IEquerySelectorAll() (by uncommon) * IE in TaskScheduler * IE Embedded Control Versioning (use IE9+ and HTML5 in a GUI) * PDF Related: * How to get reference to PDF object embeded in IE * IE on Windows 11 * I encourage you to read: * Global Vars * Best Coding Practices * Please explain code used in Help file for several File functions * OOP-like approach in AutoIt * UDF-Spec Questions * EXAMPLE: How To Catch ConsoleWrite() output to a file or to CMD *I also encourage you to check awesome @trancexx code: * Create COM objects from modules without any demand on user to register anything. * Another COM object registering stuff * OnHungApp handler * Avoid "AutoIt Error" message box in unknown errors * HTML editor * winhttp.au3 related : * https://www.autoitscript.com/forum/topic/206771-winhttpau3-download-problem-youre-speaking-plain-http-to-an-ssl-enabled-server-port/ "Homo sum; humani nil a me alienum puto" - Publius Terentius Afer"Program are meant to be read by humans and only incidentally for computers and execute" - Donald Knuth, "The Art of Computer Programming" , be and \\//_. Anticipating Errors : "Any program that accepts data from a user must include code to validate that data before sending it to the data store. You cannot rely on the data store, ...., or even your programming language to notify you of problems. You must check every byte entered by your users, making sure that data is the correct type for its field and that required fields are not empty." Signature last update: 2023-04-24
UEZ Posted 19 hours ago Author Posted 19 hours ago (edited) Can you please test if this is DPI aware? expandcollapse popup; Coded by UEZ build 2026-03-13 beta ; Should be DPI aware #include <Array.au3> #include <APIConstants.au3> #include <AVIConstants.au3> #include <GDIPlus.au3> #include <GUIConstantsEx.au3> #include <GuiDateTimePicker.au3> #include <GuiImageList.au3> #include <GuiMenu.au3> #include <GuiMonthCal.au3> #include <GuiScrollBars.au3> #include <GuiStatusBar.au3> #include <GuiTab.au3> #include <GuiTreeView.au3> #include <TreeViewConstants.au3> #include <ListViewConstants.au3> #include <WinAPIConstants.au3> #include <WinAPIGdi.au3> #include <WinAPIProc.au3> #include <WinAPIRes.au3> #include <WinAPIShellEx.au3> #include <WinAPISys.au3> #include <WinAPISysWin.au3> #include <WinAPITheme.au3> #include <WindowsConstants.au3> #Region DPI Constants ;https://learn.microsoft.com/en-us/windows/win32/api/windef/ne-windef-dpi_awareness Global Enum $DPI_AWARENESS_INVALID = -1, $DPI_AWARENESS_UNAWARE = 0, $DPI_AWARENESS_SYSTEM_AWARE = 1, $DPI_AWARENESS_PER_MONITOR_AWARE = 2 ;https://learn.microsoft.com/en-us/windows/win32/hidpi/dpi-awareness-context Global Const $DPI_AWARENESS_CONTEXT_UNAWARE = $DPI_AWARENESS_UNAWARE - 1 Global Const $DPI_AWARENESS_CONTEXT_SYSTEM_AWARE = $DPI_AWARENESS_UNAWARE - 2 Global Const $DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE = $DPI_AWARENESS_UNAWARE - 3 Global Const $DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 = $DPI_AWARENESS_UNAWARE - 4 Global Const $DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED = $DPI_AWARENESS_UNAWARE - 5 ;enum _MONITOR_DPI_TYPE Global Enum $MDT_EFFECTIVE_DPI = 0, $MDT_ANGULAR_DPI, $MDT_RAW_DPI Global Const $MDT_DEFAULT = $MDT_EFFECTIVE_DPI ;Windows Message Codes Global Const $WM_DPICHANGED = 0x02E0, $WM_DPICHANGED_BEFOREPARENT = 0x02E2, $WM_DPICHANGED_AFTERPARENT = 0x02E3, $WM_GETDPISCALEDSIZE = 0x02E4 ;DpiChangeBehavior Global Const $DDC_DEFAULT = 0 Global Const $DDC_DISABLE_ALL = 1 Global Const $DDC_DISABLE_RESIZE = 2 Global Const $DDC_DISABLE_CONTROL_RELAYOUT = 4 Global Const $DCDC_DEFAULT = 0 Global Const $DCDC_DISABLE_FONT_UPDATE = 1 Global Const $DCDC_DISABLE_RELAYOUT = 2 #EndRegion DPI Constants Enum $IHCM_USE_CACHED_VALUE, $IHCM_REFRESH Enum $APPMODE_DEFAULT = 0, $APPMODE_ALLOWDARK, $APPMODE_FORCEDARK, $APPMODE_FORCELIGHT, $APPMODE_MAX Const $PRF_CLIENT = 0x04 Const $ODS_HOTLIGHT = 0x0040 Const $TCM_SETBKCOLOR = 0x132D ; Dark Mode Colors (RGB) - used throughout WM_CTLCOLOR, custom draw, and GDI painting Global Const $COLOR_BG_DARK = 0x202020 ; main window background Global Const $COLOR_TEXT_LIGHT = 0xF0F0F0 ; default text color Global Const $COLOR_CONTROL_BG = 0x2B2B2B ; generic control background Global Const $COLOR_EDIT_BG = 0x1E1E1E ; edit/list background Global Const $COLOR_BUTTON_BG = 0x333333 ; button / selected tab background Global Const $COLOR_BORDER = 0x3F3F3F ; subtle border (edit, listbox, tab) Global Const $COLOR_BORDER2 = 0xA0A0A0 ; brighter border (checkbox outline) Global Const $COLOR_HOTTRACK_MENU = 0x3A3A3A ; menu item hover highlight Global Const $COLOR_BORDER_LIGHT = 0xD8D8D8 ; bright border on hover (date control) Global Const $COLOR_MENU_SELECT = 0x505050 ; color selecting menu ; Global variables for subclassing (MUST be declared before _Example()!) Global $g_hGUI = 0, $g_hTab, $g_ListView Global $g_aControls[150][3] = [[0, 0, 0]] ; [ControlID, hWnd, OldWndProc] Global $g_aCtrlDPI[150][7] = [[0, 0, 0, 0, 0, 0, ""]] ; [CtrlID, xpos, ypos, w, h, fontsize, fontname] Global $g_iControlCount = 0, $g_iCtrlCountDPI = 0 Global $g_pSubclassProc = 0 ; Global brushes for _WM_CTLCOLOR (avoids memory leaks) Global $g_hBrushEdit = 0 Global $g_hBrushButton = 0 Global $g_hBrushBg = 0 Global $g_hBrushGreen Global $g_hLabelGreen = 0, $g_idLabelGreen Global $g_idLabelPic, $g_hLabelPic Global $g_idInput, $g_idUpDown, $g_hUpDown Global $g_hMenu = 0, $g_hMenu1, $g_hMenu2, $g_hMenuFont = 0 Global $g_idDate = 0, $g_hDate = 0 ; Global variable for tab subclassing Global $g_hTab_CB, $g_pTab_CB, $g_hProc ; Global variable for SysDateTimePick32 subclassing Global $g_hDateProc_CB, $g_pDateProc_CB, $g_hDateOldProc ; Structure for NM_CUSTOMDRAW notification Global Const $tagNMCUSTOMDRAW = $tagNMHDR & ";" & _ ; Contains NM_CUSTOMDRAW / NMHDR header among other things "dword dwDrawStage;" & _ ; Current drawing stage (CDDS_*) "handle hdc;" & _ ; Device Context Handle "long left;long top;long right;long bottom;" & _ ; Drawing rectangle "dword_ptr dwItemSpec;" & _ ; Item index or other info (depending on the control) "uint uItemState;" & _ ; State Flags (CDIS_SELECTED, CDIS_FOCUS etc.) "lparam lItemlParam" ; lParam set by the item (e.g., via LVITEM.lParam) Global $g_aMenuText = [] ; top-level menu texts (populated by _MakeMenuOwnerDraw) Global $arMenuItems[1][8] ; owner-draw menu item data $arMenuItems[0][0] = 0 Global $arSideItems[1][10] ; side/context menu item data $arSideItems[0][0] = 0 Const $ODT_MENU = 1 Const $ODS_SELECTED = 0x0001 Const $ODS_DISABLED = 0x0004 Global Enum $idAbout = 5000 Global $g_hMenu_Sys, $g_idAboutMenu, $g_AboutDummy, $g_hStatusbar Global $g_bHover = False _GDIPlus_Startup() Global $AWARENESS ; Select DPI awareness level based on OS build: ; Win8.1-Win10 14393: PER_MONITOR_AWARE via Shcore.dll ; Win10 14393+: PER_MONITOR_AWARE_V2 (full non-client DPI scaling) ; older: SYSTEM_AWARE fallback Switch @OSBuild Case 9200 To 13999 $AWARENESS = $DPI_AWARENESS_PER_MONITOR_AWARE Case @OSBuild > 13999 $AWARENESS = $DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 Case Else $AWARENESS = $DPI_AWARENESS_SYSTEM_AWARE EndSwitch ; Set DPI awareness and retrieve current DPI (96 = 100%) Global $g_iDPI = _WinAPI_SetDPIAwareness($AWARENESS), $aPos Global $g_fScale = $g_iDPI / 96.0, $g_aStatusbarParts[4] = [75, 150, 300, 400], $g_hCtrlFont = 0, $g_aCustomFonts[0] _Example() _GDIPlus_Shutdown() Func _Example() ; Create global brushes $g_hBrushEdit = _WinAPI_CreateSolidBrush(_ColorToCOLORREF($COLOR_EDIT_BG)) $g_hBrushButton = _WinAPI_CreateSolidBrush(_ColorToCOLORREF($COLOR_BUTTON_BG)) $g_hBrushBg = _WinAPI_CreateSolidBrush(_ColorToCOLORREF($COLOR_BG_DARK)) Local $sAutoitExample = StringRegExpReplace(@AutoItExe, "\\[^\\]+$", "") & "\Examples\GUI" #Region GUI $g_hGUI = GUICreate("Sample GUI with Dark Mode", 400 * $g_fScale, 424 * $g_fScale) GUISetIcon(@SystemDir & "\mspaint.exe", 0) GUISetBkColor($COLOR_BG_DARK, $g_hGUI) $g_hMenu_Sys = _GUICtrlMenu_GetSystemMenu($g_hGUI) _GUICtrlMenu_AppendMenu($g_hMenu_Sys, $MF_SEPARATOR, 0, 0) _GUICtrlMenu_AppendMenu($g_hMenu_Sys, $MF_STRING, $idAbout, "About") ; Register GUI-level WM_CTLCOLOR messages GUIRegisterMsg($WM_CTLCOLOREDIT, "_WM_CTLCOLOR") GUIRegisterMsg($WM_CTLCOLORLISTBOX, "_WM_CTLCOLOR") GUIRegisterMsg($WM_CTLCOLORBTN, "_WM_CTLCOLOR") GUIRegisterMsg($WM_CTLCOLORSTATIC, "_WM_CTLCOLOR") GUIRegisterMsg($WM_MEASUREITEM, "_WM_MEASUREITEM") GUIRegisterMsg($WM_DRAWITEM, "_WM_DRAWITEM") GUIRegisterMsg($WM_NOTIFY, "_WM_NOTIFY") GUIRegisterMsg($WM_ACTIVATE, "_WM_ACTIVATE") GUIRegisterMsg($WM_WINDOWPOSCHANGED, "_WM_WINDOWPOSCHANGED") GUIRegisterMsg($WM_MENUCOMMAND, "_WM_MENUCOMMAND") GUIRegisterMsg($WM_SYSCOMMAND, "_WM_SYSCOMMAND") GUIRegisterMsg($WM_DPICHANGED, "_WM_DPICHANGED") #EndRegion GUI #Region MENU Global $g_aMenuText[4] $g_aMenuText[0] = "Menu &One" $g_aMenuText[1] = "Menu &Two" $g_aMenuText[2] = "Menu Th&ree" $g_aMenuText[3] = "Menu &Four" Local $idMenu1 = GUICtrlCreateMenu($g_aMenuText[0]) Local $idMenu2 = GUICtrlCreateMenu($g_aMenuText[1]) GUICtrlCreateMenu($g_aMenuText[2]) GUICtrlCreateMenu($g_aMenuText[3]) GUICtrlCreateMenuItem("SubMenu One &A", $idMenu1) GUICtrlCreateMenuItem("SubMenu One &B", $idMenu1) $g_idAboutMenu = GUICtrlCreateMenuItem("About", $idMenu1) $g_hMenu1 = GUICtrlGetHandle($idMenu1) $g_hMenu2 = GUICtrlGetHandle($idMenu2) ; Owner-draw Top-Level Menu creation _CreateMenuFont($g_fScale) _MakeMenuOwnerDraw($g_hGUI) _EnableMenuHotTrack($g_hMenu) #EndRegion MENU #Region CONTEXT MENU Local $idContextMenu = GUICtrlCreateContextMenu() GUICtrlCreateMenuItem("Context Menu", $idContextMenu) GUICtrlCreateMenuItem("", $idContextMenu) GUICtrlCreateMenuItem("&Properties", $idContextMenu) #EndRegion CONTEXT MENU #Region PIC Local $idPic = GUICtrlCreatePic("", 0, 2, 169, 68) GUICtrlSetImage($idPic, $sAutoitExample & "\logo4.gif") GUICtrlSetTip(-1, "#Region PIC") _AddControlForDPI($idPic, 0, 2, 169, 68, 0, "") $g_idLabelPic = GUICtrlCreateLabel("Sample Pic", 75, 1, 63, 15) $g_hLabelPic = GUICtrlGetHandle($g_idLabelPic) _AddControlForDPI($g_idLabelPic, 75, 1, 63, 15) #EndRegion PIC #Region AVI Local $idAvi = GUICtrlCreateAvi($sAutoitExample & "\SampleAVI.avi", 0, 184, 12, 32, 32, $ACS_AUTOPLAY) GUICtrlSetTip(-1, "#Region AVI") _AddControlForDPI($idAvi, 184, 12, 32, 32, 0, "") Local $idLabelAvi = GUICtrlCreateLabel("Sample avi", 175, 50) $aPos = ControlGetPos($g_hGUI, "", $idLabelAvi) _AddControlForDPI($idLabelAvi, 175, 50, $aPos[2], $aPos[3]) #EndRegion AVI #Region TAB Local $idTab = GUICtrlCreateTab(240, 2, 150, 70), $g_hTab = GUICtrlGetHandle($idTab) _AddControlForSubclass($idTab) _AddControlForDPI($idTab, 240, 2, 150, 70) GUICtrlCreateTabItem("One") GUICtrlSetTip(-1, "#Region TAB1") Local $idLabelTab = GUICtrlCreateLabel("Sample Tab with TabItems", 250, 40) $aPos = ControlGetPos($g_hGUI, "", $idLabelTab) _AddControlForDPI($idLabelTab, 250, 40, $aPos[2], $aPos[3]) GUICtrlCreateTabItem("Two") GUICtrlSetTip(-1, "#Region TAB2") Local $idCheckBoxTab2 = GUICtrlCreateCheckbox("Checkbox", 250, 30, 120, 20) GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT) _AddControlForDPI($idCheckBoxTab2, 250, 30, 120, 20) _WinAPI_SetWindowTheme(GUICtrlGetHandle($idCheckBoxTab2), "DarkMode_DarkTheme", 0) GUICtrlCreateTabItem("Three") GUICtrlSetTip(-1, "#Region TAB3") GUICtrlCreateTabItem("") #EndRegion TAB #Region COMBO Local $idCombo = GUICtrlCreateCombo("", 250, 80, 120, 100, $CBS_DROPDOWNLIST) GUICtrlSetData($idCombo, "Sample Combo|Item 2|Item 3", "Sample Combo") _AddControlForSubclass($idCombo) GUICtrlSetTip(-1, "#Region COMBO") _AddControlForDPI($idCombo, 250, 80, 120, 100) #EndRegion COMBO #Region PROGRESS Local $idProgress = GUICtrlCreateProgress(60, 80, 150, 20) ;_AddControlForSubclass($idProgress) GUICtrlSetTip(-1, "#Region PROGRESS") GUICtrlSetData(-1, 60) _AddControlForDPI($idProgress, 60, 80, 150, 20) Local $idLabelProgress = GUICtrlCreateLabel("Progress:", 5, 82) $aPos = ControlGetPos($g_hGUI, "", $idLabelProgress) _AddControlForDPI($idLabelProgress, 5, 82, $aPos[2], $aPos[3]) #EndRegion PROGRESS #Region EDIT Local $idEdit = GUICtrlCreateEdit(@CRLF & " Sample Edit Control", 10, 110, 150, 70), $hEditCtrl = GUICtrlGetHandle($idEdit) _WinAPI_SetWindowLong($hEditCtrl, $GWL_EXSTYLE, BitAND(_WinAPI_GetWindowLong($hEditCtrl, $GWL_EXSTYLE), BitNOT($WS_EX_CLIENTEDGE))) _AddControlForSubclass($idEdit) GUICtrlSetTip(-1, "#Region EDIT") _AddControlForDPI($idEdit, 10, 110, 150, 70) #EndRegion EDIT #Region LIST Local $idList = GUICtrlCreateList("", 5, 190, 100, 90), $hList = GUICtrlGetHandle($idList) _WinAPI_SetWindowLong($hList, $GWL_EXSTYLE, BitAND(_WinAPI_GetWindowLong($hList, $GWL_EXSTYLE), BitNOT($WS_EX_CLIENTEDGE))) _AddControlForSubclass($idList) GUICtrlSetTip(-1, "#Region LIST") GUICtrlSetData(-1, "A.Sample|B.List|C.Control|D.Here", "B.List") _AddControlForDPI($idList, 5, 190, 100, 90) #EndRegion LIST #Region ICON Local $idIcon = GUICtrlCreateIcon("explorer.exe", 0, 175, 120) GUICtrlSetTip(-1, "#Region ICON") _AddControlForDPI($idIcon, 175, 120, 32, 32, 0, "") Local $idLabelIcon = GUICtrlCreateLabel("Icon", 180, 160, 50, 20) _AddControlForDPI($idLabelIcon, 180, 160, 50, 20) #EndRegion ICON #Region LIST VIEW Local $idListView = GUICtrlCreateListView("Sample|ListView|", 110, 190, 110, 80, $LVS_REPORT) _AddControlForSubclass($idListView) GUICtrlSetBkColor($idListView, $COLOR_EDIT_BG) GUICtrlSetColor($idListView, $COLOR_TEXT_LIGHT) GUICtrlSetTip(-1, "#Region LIST VIEW") GUICtrlCreateListViewItem("A|One", $idListView) GUICtrlCreateListViewItem("B|Two", $idListView) GUICtrlCreateListViewItem("C|Three", $idListView) $g_ListView = GUICtrlGetHandle($idListView) _AddControlForDPI($idListView, 110, 190, 110, 80) #EndRegion LIST VIEW #Region GROUP WITH RADIO BUTTONS Local $idGroup = GUICtrlCreateGroup("Sample Group", 230, 120) GUICtrlSetColor($idGroup, $COLOR_TEXT_LIGHT) $aPos = ControlGetPos($g_hGUI, "", $idGroup) _AddControlForDPI($idGroup, 230, 120, $aPos[2], $aPos[3]) Local $idRadio1 = GUICtrlCreateRadio("Radio One", 250, 140, 80) GUICtrlSetTip($idRadio1, "#Region RADIO1") GUICtrlSetState($idRadio1, $GUI_CHECKED) $aPos = ControlGetPos($g_hGUI, "", $idRadio1) _AddControlForDPI($idRadio1, 250, 140, 80, $aPos[3]) Local $idRadio2 = GUICtrlCreateRadio("Radio Two", 250, 165, 80) GUICtrlSetTip($idRadio2, "#Region RADIO2") $aPos = ControlGetPos($g_hGUI, "", $idRadio2) _AddControlForDPI($idRadio2, 250, 165, 80, $aPos[3]) GUICtrlCreateGroup("", -99, -99, 1, 1) _WinAPI_SetWindowTheme(GUICtrlGetHandle($idRadio1), "DarkMode_DarkTheme", 0) _WinAPI_SetWindowTheme(GUICtrlGetHandle($idRadio2), "DarkMode_DarkTheme", 0) _WinAPI_SetWindowTheme(GUICtrlGetHandle($idGroup), "DarkMode_DarkTheme", 0) #EndRegion GROUP WITH RADIO BUTTONS #Region UPDOWN Local $idLabelUpDown = GUICtrlCreateLabel("UpDown", 350, 115) GUICtrlSetColor(-1, $COLOR_TEXT_LIGHT) $aPos = ControlGetPos($g_hGUI, "", $idLabelUpDown) _AddControlForDPI($idLabelUpDown, 350, 115, $aPos[2], $aPos[3]) $g_idInput = GUICtrlCreateInput("42", 350, 130, 40, 20) _AddControlForSubclass($g_idInput) _AddControlForDPI($g_idInput, 350, 130, 40, 20) $g_idUpDown = GUICtrlCreateUpdown(-1) _AddControlForSubclass($g_idUpDown) $aPos = ControlGetPos($g_hGUI, "", $g_idUpDown) _AddControlForDPI($g_idUpDown, $aPos[0], $aPos[1], $aPos[2], $aPos[3]) $g_hUpDown = GUICtrlGetHandle($g_idUpDown) #EndRegion UPDOWN #Region LABEL $g_idLabelGreen = GUICtrlCreateLabel("Green" & @CRLF & "Label", 350, 165, 40, 40) $g_hLabelGreen = GUICtrlGetHandle($g_idLabelGreen) GUICtrlSetTip($g_idLabelGreen, "#Region LABEL") $g_hBrushGreen = _WinAPI_CreateSolidBrush(_ColorToCOLORREF(0x00FF00)) ; green background _AddControlForDPI($g_idLabelGreen, 350, 165, 40, 40) #Region SLIDER Local $idLabelSlider = GUICtrlCreateLabel("Slider:", 235, 215) $aPos = ControlGetPos($g_hGUI, "", $idLabelSlider) _AddControlForDPI($idLabelSlider, 235, 215, $aPos[2], $aPos[3]) Local $idSlider = GUICtrlCreateSlider(270, 210, 120, 30) _AddControlForSubclass($idSlider) GUICtrlSetTip(-1, "#Region SLIDER") GUICtrlSetData(-1, 30) _AddControlForDPI($idSlider, 270, 210, 120, 30) #EndRegion SLIDER #Region INPUT Local $idInput2 = GUICtrlCreateInput("Sample Input Box", 235, 255, 130, 20) _AddControlForSubclass($idInput2) GUICtrlSetTip(-1, "#Region INPUT") _AddControlForDPI($idInput2, 235, 255, 130, 20) #EndRegion INPUT #Region DATE $g_idDate = GUICtrlCreateDate("", 5, 280, 200, 20) $g_hDate = GUICtrlGetHandle($g_idDate) _AddControlForSubclass($g_idDate) GUICtrlSetTip(-1, "#Region DATE") _AddControlForDPI($g_idDate, 5, 280, 200, 20) Local $idLabelDate = GUICtrlCreateLabel("(Date control expands into a calendar)", 10, 305, 200, 20) _AddControlForDPI($idLabelDate, 10, 305, 200, 20) #EndRegion DATE #Region BUTTON Local $idButton = GUICtrlCreateButton("Sample Button", 10, 330, 100, 30) _AddControlForSubclass($idButton) GUICtrlSetTip(-1, "#Region BUTTON") _AddControlForDPI($idButton, 10, 330, 100, 30) #EndRegion BUTTON #Region CHECKBOX Local $idCheckBox = GUICtrlCreateCheckbox("Checkbox", 130, 335, 80, 20) GUICtrlSetTip(-1, "#Region CHECKBOX") GUICtrlSetState(-1, $GUI_CHECKED) _WinAPI_SetWindowTheme(GUICtrlGetHandle($idCheckBox), "DarkMode_DarkTheme", 0) _AddControlForDPI($idCheckBox, 130, 335, 80, 20) #EndRegion CHECKBOX #Region TREEVIEW ONE Local $idTreeView1 = GUICtrlCreateTreeView(210, 290, 80, 80) _AddControlForSubclass($idTreeView1) GUICtrlSetBkColor($idTreeView1, $COLOR_EDIT_BG) GUICtrlSetColor($idTreeView1, $COLOR_TEXT_LIGHT) GUICtrlSetTip(-1, "#Region TREEVIEW ONE") _AddControlForDPI($idTreeView1, 210, 290, 80, 80) Local $idTreeViewItem = GUICtrlCreateTreeViewItem("TreeView", $idTreeView1) GUICtrlCreateTreeViewItem("Item1", $idTreeViewItem) GUICtrlCreateTreeViewItem("Item2", $idTreeViewItem) GUICtrlCreateTreeViewItem("Foo", -1) GUICtrlSetState($idTreeViewItem, $GUI_EXPAND) #EndRegion TREEVIEW ONE #Region TREEVIEW TWO Local $idTreeView2 = GUICtrlCreateTreeView(295, 290, 103, 80, $TVS_CHECKBOXES) _AddControlForSubclass($idTreeView2) _AddControlForDPI($idTreeView2, 295, 290, 103, 80) GUICtrlSetBkColor($idTreeView2, $COLOR_EDIT_BG) GUICtrlSetColor($idTreeView2, $COLOR_TEXT_LIGHT) GUICtrlSetTip(-1, "#Region TREEVIEW TWO") GUICtrlCreateTreeViewItem("TreeView", $idTreeView2) GUICtrlCreateTreeViewItem("With", $idTreeView2) GUICtrlCreateTreeViewItem("$TVS_CHECKBOXES", $idTreeView2) GUICtrlSetState(-1, $GUI_CHECKED) GUICtrlCreateTreeViewItem("Style", $idTreeView2) _SetDarkTreeViewCheckboxes(GUICtrlGetHandle($idTreeView2), 16, 16) #EndRegion TREEVIEW TWO #Region Statusbar $g_hStatusbar = _GUICtrlStatusBar_Create($g_hGUI) _AddControlHandleForSubclass($g_hStatusbar) _GUICtrlStatusBar_SetParts($g_hStatusbar, $g_aStatusbarParts) _GUICtrlStatusBar_SetText($g_hStatusbar, "Part 0", 0) _GUICtrlStatusBar_SetText($g_hStatusbar, "Part 1", 1) _GUICtrlStatusBar_SetText($g_hStatusbar, "Part 2", 2) _GUICtrlStatusBar_SetText($g_hStatusbar, "Part 3", 3) $aPos = ControlGetPos($g_hGUI, "", _WinAPI_GetDlgCtrlID($g_hStatusbar)) _AddControlForDPI(_WinAPI_GetDlgCtrlID($g_hStatusbar), $aPos[0], $aPos[1], $aPos[2], $aPos[3]) #EndRegion Statusbar ; Apply Dark Mode _ApplyDarkModeToAllControls() ; Handle scrollbars for windows that have them _EnableDarkScrollBars() ; Register a custom window procedure for the tab control for owner-drawing $g_hTab_CB = DllCallbackRegister("_WinProc", "ptr", "hwnd;uint;wparam;lparam") $g_pTab_CB = DllCallbackGetPtr($g_hTab_CB) $g_hProc = _WinAPI_SetWindowLong($g_hTab, $GWL_WNDPROC, $g_pTab_CB) ; Register a custom window procedure for the date control for owner-drawing $g_hDateProc_CB = DllCallbackRegister("_DateProc", "ptr", "hwnd;uint;wparam;lparam") $g_pDateProc_CB = DllCallbackGetPtr($g_hDateProc_CB) $g_hDateOldProc = _WinAPI_SetWindowLong($g_hDate, $GWL_WNDPROC, $g_pDateProc_CB) $g_AboutDummy = GUICtrlCreateDummy() _ApplyDPIScaling($g_fScale) ; Applying dark mode to Tooltips - thanks to WildByDesign ; Applying dark mode to Tooltips - thanks to WildByDesign Local $aData = _WinAPI_EnumProcessWindows(0, False) For $i = 1 To $aData[0][0] If $aData[$i][1] = "tooltips_class32" Then _WinAPI_SetWindowTheme($aData[$i][0], "DarkMode_Explorer", "ToolTip") Next GUISetState(@SW_SHOW) _OverpaintWhiteLine() While 1 Switch GUIGetMsg() Case $GUI_EVENT_RESTORE ;~ _WinAPI_RedrawWindow($g_hGUI, 0, 0, BitOR($RDW_INVALIDATE, $RDW_UPDATENOW)) _WinAPI_LockWindowUpdate($g_hGUI) _ApplyDPIScaling($g_fScale) _OverpaintWhiteLine() _WinAPI_LockWindowUpdate(0) Case $GUI_EVENT_CLOSE _CleanupSubclassing() _CleanupBrushes() ExitLoop Case $g_AboutDummy MsgBox($MB_SYSTEMMODAL, "About", "Example coded by UEZ :-)", 10, $g_hGUI) EndSwitch WEnd ; Restore the original window procedure for the tab control _WinAPI_SetWindowLong($g_hTab, $GWL_WNDPROC, $g_hProc) DllCallbackFree($g_hTab_CB) _WinAPI_SetWindowLong($g_hDate, $GWL_WNDPROC, $g_hDateOldProc) DllCallbackFree($g_hDateProc_CB) GUIDelete() EndFunc ;==>_Example Func _ApplyDPIScaling($fNewScale) ; Create new control font BEFORE applying - old font deleted AFTER all controls receive the new one. ; This avoids a brief moment where controls hold a deleted font handle (causes tiny/invisible text). ; _WinAPI_CreateFont with negative height = character height (matches GUICtrlSetFont point size behavior). Local $hOldFont = $g_hCtrlFont $g_hCtrlFont = _WinAPI_CreateFont(-Round(11.3 * $fNewScale), 0, 0, 0, $FW_NORMAL, False, False, False, _ $DEFAULT_CHARSET, $OUT_DEFAULT_PRECIS, $CLIP_DEFAULT_PRECIS, $PROOF_QUALITY, $DEFAULT_PITCH, "Arial") ; Cleanup previous custom fonts from last DPI pass For $j = 0 To UBound($g_aCustomFonts) - 1 If $g_aCustomFonts[$j] Then _WinAPI_DeleteObject($g_aCustomFonts[$j]) Next ReDim $g_aCustomFonts[0] _WinAPI_LockWindowUpdate($g_hGUI) ; suppress repaints during bulk repositioning Local $i, $hCtrl For $i = 0 To $g_iCtrlCountDPI - 1 ; Reposition using logical coordinates - GUICtrlSetPos handles DPI translation internally GUICtrlSetPos($g_aCtrlDPI[$i][0], $g_aCtrlDPI[$i][1] * $fNewScale, $g_aCtrlDPI[$i][2] * $fNewScale, _ $g_aCtrlDPI[$i][3] * $fNewScale, $g_aCtrlDPI[$i][4] * $fNewScale) ; Apply font via WM_SETFONT - bypasses AutoIt's cached DC which would ignore DPI changes If $g_aCtrlDPI[$i][5] > 0 Then $hCtrl = GUICtrlGetHandle($g_aCtrlDPI[$i][0]) If $hCtrl Then Local $hFont If $g_aCtrlDPI[$i][5] = 8.5 And ($g_aCtrlDPI[$i][6] = "" Or $g_aCtrlDPI[$i][6] = "Arial") Then ; standard font — use shared handle $hFont = $g_hCtrlFont Else ; custom size/face — create dedicated font scaled to current DPI Local $iH = -Round(_WinAPI_MulDiv($g_aCtrlDPI[$i][5], Round($fNewScale * 96), 72)) Local $sName = ($g_aCtrlDPI[$i][6] <> "" ? $g_aCtrlDPI[$i][6] : "Arial") $hFont = _WinAPI_CreateFont($iH, 0, 0, 0, $FW_NORMAL, False, False, False, _ $DEFAULT_CHARSET, $OUT_DEFAULT_PRECIS, $CLIP_DEFAULT_PRECIS, $PROOF_QUALITY, $DEFAULT_PITCH, $sName) ; track for cleanup on next DPI change ReDim $g_aCustomFonts[UBound($g_aCustomFonts) + 1] $g_aCustomFonts[UBound($g_aCustomFonts) - 1] = $hFont EndIf _SendMessage($hCtrl, $WM_SETFONT, $hFont, True) EndIf EndIf Next ; UpDown buddy positioning is controlled by Windows — override manually after scaling If $g_idInput And $g_idUpDown Then Local $tPos = ControlGetPos($g_hGUI, "", $g_idInput) If IsArray($tPos) Then ; Place UpDown directly to the right of the Input, same height Local $iUpDownW = _WinAPI_GetSystemMetricsForDpi($SM_CXVSCROLL, Round($g_fScale * 96)) _WinAPI_MoveWindow($g_hUpDown, $tPos[0] + $tPos[2], $tPos[1], $iUpDownW, $tPos[3], True) EndIf EndIf _WinAPI_LockWindowUpdate(0) _WinAPI_RedrawWindow($g_hGUI, 0, 0, BitOR($RDW_INVALIDATE, $RDW_UPDATENOW)) ; Safe to delete old font now - all controls already hold the new handle If $hOldFont Then _WinAPI_DeleteObject($hOldFont) EndFunc ;==>_ApplyDPIScaling Func _CreateMenuFont($fScale = 1.0, $sFontName = "Arial") ; Creates the owner-draw menu font at the correct pixel size for the current DPI. ; Uses MulDiv(8.5pt, DPI, 72) for accurate point-to-pixel conversion. ; Called once at startup; DPI changes recreate the font inline in _WM_DPICHANGED. If $g_hMenuFont Then _WinAPI_DeleteObject($g_hMenuFont) Local $iHeight = -Round(_WinAPI_MulDiv(8.5, $g_iDPI, 72)) $g_hMenuFont = _WinAPI_CreateFont($iHeight, 0, 0, 0, $FW_NORMAL, False, False, False, $DEFAULT_CHARSET, $OUT_DEFAULT_PRECIS, $CLIP_DEFAULT_PRECIS, $PROOF_QUALITY, $DEFAULT_PITCH, $sFontName) EndFunc ;==>_CreateMenuFont Func _GDIPlus_DrawRoundRect($hGfx, $iX, $iY, $iW, $iH, $iDiameter, $iBrushARGB, $iPenARGB, $fPenWidth = 1.0) Local Const $hPath = _GDIPlus_PathCreate() ; Top-left arc _GDIPlus_PathAddArc($hPath, $iX, $iY, $iDiameter, $iDiameter, 180, 90) ; Top-right arc _GDIPlus_PathAddArc($hPath, $iX + $iW - $iDiameter, $iY, $iDiameter, $iDiameter, 270, 90) ; Bottom-right arc _GDIPlus_PathAddArc($hPath, $iX + $iW - $iDiameter, $iY + $iH - $iDiameter, $iDiameter, $iDiameter, 0, 90) ; Bottom-left arc _GDIPlus_PathAddArc($hPath, $iX, $iY + $iH - $iDiameter, $iDiameter, $iDiameter, 90, 90) _GDIPlus_PathCloseFigure($hPath) If $iBrushARGB <> 0 Then Local Const $hBrush = _GDIPlus_BrushCreateSolid($iBrushARGB) _GDIPlus_GraphicsFillPath($hGfx, $hPath, $hBrush) _GDIPlus_BrushDispose($hBrush) EndIf If $iPenARGB <> 0 Then Local Const $hPen = _GDIPlus_PenCreate($iPenARGB, $fPenWidth) _GDIPlus_GraphicsDrawPath($hGfx, $hPath, $hPen) _GDIPlus_PenDispose($hPen) EndIf _GDIPlus_PathDispose($hPath) EndFunc ;==>_GDIPlus_DrawRoundRect Func _SetDarkTreeViewCheckboxesGDIp($hTreeView, $iW = 16, $iH = 16) Local $hImageList = _GUIImageList_Create($iW, $iH, 5, 3) Local $hBmp = _GDIPlus_BitmapCreateFromScan0($iW, $iH) Local $hGfx = _GDIPlus_ImageGetGraphicsContext($hBmp) _GDIPlus_GraphicsSetSmoothingMode($hGfx, $GDIP_SMOOTHINGMODE_HIGHQUALITY) ; --- Index 0: Unchecked --- _GDIPlus_GraphicsClear($hGfx, 0xFF000000 + $COLOR_EDIT_BG) _GDIPlus_DrawRoundRect($hGfx, 2 / 16 * $iW, 2 / 16 * $iH, 12 / 16 * $iW, 12 / 16 * $iH, 3, 0, 0xFF000000 + $COLOR_BORDER2, 1.5) Local $hBmp_GDI = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBmp, 0) _GUIImageList_Add($hImageList, $hBmp_GDI) _WinAPI_DeleteObject($hBmp_GDI) ; --- Index 1: Checked --- _GDIPlus_GraphicsClear($hGfx, 0xFF000000 + $COLOR_EDIT_BG) _GDIPlus_DrawRoundRect($hGfx, 2 / 16 * $iW, 2 / 16 * $iH, 12 / 16 * $iW, 12 / 16 * $iH, 3, 0xFF60CDFF, 0xFF60CDFF, 1.0) Local $hCheckPen = _GDIPlus_PenCreate(0xFF0F2028, 1.5) _GDIPlus_GraphicsDrawLine($hGfx, 5 / 16 * $iW, 8 / 16 * $iH, 7 / 16 * $iW, 10 / 16 * $iH, $hCheckPen) _GDIPlus_GraphicsDrawLine($hGfx, 7 / 16 * $iW, 10 / 16 * $iH, 11 / 16 * $iW, 6 / 16 * $iH, $hCheckPen) $hBmp_GDI = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBmp, 0) _GUIImageList_Add($hImageList, $hBmp_GDI) _WinAPI_DeleteObject($hBmp_GDI) ; --- Cleanup --- _GDIPlus_PenDispose($hCheckPen) _GDIPlus_GraphicsDispose($hGfx) _GDIPlus_ImageDispose($hBmp) _GUICtrlTreeView_SetStateImageList($hTreeView, $hImageList) Return True EndFunc ;==>_SetDarkTreeViewCheckboxesGDIp Func _SetDarkTreeViewCheckboxes($hTreeView, $iW = 16, $iH = 16) Local $hImageList = _GUIImageList_Create($iW, $iH, 5, 3) Local $hBmp_GDI = _WinAPI_ExtractThemeBackground($g_hGUI, 2) ;thanks to WildByDesign for the idea! _GUIImageList_Add($hImageList, $hBmp_GDI) _WinAPI_DeleteObject($hBmp_GDI) $hBmp_GDI = _WinAPI_ExtractThemeBackground($g_hGUI, 5) _GUIImageList_Add($hImageList, $hBmp_GDI) _WinAPI_DeleteObject($hBmp_GDI) _GUICtrlTreeView_SetStateImageList($hTreeView, $hImageList) Return True EndFunc ;==>_SetDarkTreeViewCheckboxes Func _WinAPI_ExtractThemeBackground($hGUI, $iState, $iPart = 3, $iWidth = 16, $iHeight = 16) Local $hTheme = _WinAPI_OpenThemeData($hGUI, "DarkMode_DarkTheme::Button") If @error Then Return SetError(1, 0, 0) Local $hDC = _WinAPI_GetDC($hGUI) Local $hHBitmap = _WinAPI_CreateCompatibleBitmap($hDC, $iWidth, $iHeight) Local $hMemDC = _WinAPI_CreateCompatibleDC($hDC) Local $hObjOld = _WinAPI_SelectObject($hMemDC, $hHBitmap) Local $tRECT = _WinAPI_CreateRectEx(0, 0, $iWidth, $iHeight) _WinAPI_DrawThemeBackground($hTheme, $iPart, $iState, $hMemDC, $tRECT) If @error Then _WinAPI_CloseThemeData($hTheme) Return SetError(2, 0, 0) EndIf _WinAPI_SelectObject($hMemDC, $hObjOld) _WinAPI_ReleaseDC($hGUI, $hDC) _WinAPI_DeleteDC($hMemDC) _WinAPI_CloseThemeData($hTheme) Return $hHBitmap EndFunc ;==>_WinAPI_ExtractThemeBackground Func _EnableMenuHotTrack($hMenu) If Not $hMenu Then Return False Local $tagMENUINFO = "dword cbSize;dword fMask;dword dwStyle;uint cyMax;handle hbrBack;dword dwContextHelpID;ulong_ptr dwMenuData" Local Const $MIM_STYLE = 0x00000010 Local Const $MNS_HOTTRACK = 0x08000000 Local $tMI = DllStructCreate($tagMENUINFO) With $tMI .cbSize = DllStructGetSize($tMI) .fMask = $MIM_STYLE .dwStyle = $MNS_HOTTRACK EndWith _GUICtrlMenu_SetMenuInfo($hMenu, $tMI) ; redraw menus _GUICtrlMenu_DrawMenuBar($g_hGUI) Return True EndFunc ;==>_EnableMenuHotTrack Func _OverpaintWhiteLine() ; The bright artifact line sits exactly 1px above the client area top edge. ; Instead of computing caption+border+menu heights manually (DPI-fragile), ; we locate the client rect in window coordinates and paint 1px above it. ; Get client rect and convert from client to screen coordinates Local $rcClient = _WinAPI_GetClientRect($g_hGUI) DllCall("user32.dll", "int", "MapWindowPoints", _ "hwnd", $g_hGUI, _ ; source: client coords "hwnd", 0, _ ; target: screen coords "ptr", DllStructGetPtr($rcClient), _ "uint", 2) ; 2 points = RECT If @error Then Return SetError(1, 0, 0) ; Make client rect window-relative (subtract window origin) Local $rcWindow = _WinAPI_GetWindowRect($g_hGUI) _WinAPI_OffsetRect($rcClient, -$rcWindow.left, -$rcWindow.top) ; Build a 1px-high rect just above the client area top — that's the artifact line Local $rcAnnoyingLine = DllStructCreate($tagRECT) With $rcAnnoyingLine .left = $rcClient.left .right = $rcClient.right .bottom = $rcClient.top ; bottom = client top .top = $rcClient.top - 1 ; top = 1px above client EndWith ; GetDCEx with DCX_WINDOW grants access to the non-client area ; DCX_INTERSECTRGN limits drawing to the provided region (full window here) Local $hRgn = _WinAPI_CreateRectRgn(-20000, -20000, 20000, 20000) Local $hDC = DllCall("user32.dll", "handle", "GetDCEx", _ "hwnd", $g_hGUI, "handle", $hRgn, _ "dword", BitOR($DCX_WINDOW, $DCX_INTERSECTRGN))[0] Local $hBrush = _WinAPI_CreateSolidBrush(_ColorToCOLORREF($COLOR_BG_DARK)) _WinAPI_FillRect($hDC, $rcAnnoyingLine, $hBrush) _WinAPI_ReleaseDC($g_hGUI, $hDC) _WinAPI_DeleteObject($hBrush) Return 1 EndFunc ;==>_OverpaintWhiteLine Func _ColorToCOLORREF($iColor) ;RGB to BGR Local $iR = BitAND(BitShift($iColor, 16), 0xFF) Local $iG = BitAND(BitShift($iColor, 8), 0xFF) Local $iB = BitAND($iColor, 0xFF) Return BitOR(BitShift($iB, -16), BitShift($iG, -8), $iR) EndFunc ;==>_ColorToCOLORREF ; Registers a control for DPI-aware repositioning. ; Base coordinates (x, y, w, h) are at 100% DPI - _ApplyDPIScaling multiplies them by $g_fScale. ; fontsize > 0 triggers WM_SETFONT with the shared $g_hCtrlFont on each DPI change. Func _AddControlForDPI($iCtrlID, $x, $y, $w, $h, $fontsize = 8.5, $fontname = "Arial") If $iCtrlID Then $g_aCtrlDPI[$g_iCtrlCountDPI][0] = $iCtrlID $g_aCtrlDPI[$g_iCtrlCountDPI][1] = $x $g_aCtrlDPI[$g_iCtrlCountDPI][2] = $y $g_aCtrlDPI[$g_iCtrlCountDPI][3] = $w $g_aCtrlDPI[$g_iCtrlCountDPI][4] = $h $g_aCtrlDPI[$g_iCtrlCountDPI][5] = $fontsize $g_aCtrlDPI[$g_iCtrlCountDPI][6] = $fontname $g_iCtrlCountDPI += 1 EndIf EndFunc ;==>_AddControlForDPI ; Registers a control (by AutoIt ControlID) for dark mode subclassing and theming. Func _AddControlForSubclass($iCtrlID) Local $hCtrl = GUICtrlGetHandle($iCtrlID) If $hCtrl Then $g_aControls[$g_iControlCount][0] = $iCtrlID $g_aControls[$g_iControlCount][1] = $hCtrl $g_aControls[$g_iControlCount][2] = 0 ; reserved for old WndProc (not used with SetWindowSubclass) $g_iControlCount += 1 EndIf EndFunc ;==>_AddControlForSubclass ; Registers a control (by HWND, e.g. native controls not created via GUICtrlCreate) for subclassing. Func _AddControlHandleForSubclass($hCtrl) If $hCtrl Then $g_aControls[$g_iControlCount][0] = 0 $g_aControls[$g_iControlCount][1] = $hCtrl $g_aControls[$g_iControlCount][2] = 0 $g_iControlCount += 1 EndIf EndFunc ;==>_AddControlHandleForSubclass Func _ApplyDarkModeToAllControls() ; DWM Dark Mode for the main window _WinAPI_SetPreferredAppMode($APPMODE_FORCEDARK) ; Create subclass callback If Not $g_pSubclassProc Then $g_pSubclassProc = DllCallbackRegister("_SubclassProc", "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr") ; Subclass all controls Local $hCtrl, $sClass, $hEdit, $hComboLBox, $hHeader, $hUpDown For $i = 0 To $g_iControlCount - 1 $hCtrl = $g_aControls[$i][1] If $hCtrl Then $sClass = _WinAPI_GetClassName($hCtrl) ; Use SetWindowSubclass _WinAPI_SetWindowSubclass($hCtrl, DllCallbackGetPtr($g_pSubclassProc), $i, 0) ; Special themes for different control types Switch StringLower($sClass) Case "edit", "richedit", "richedit20a", "richedit20w" _WinAPI_SetWindowTheme($hCtrl, "DarkMode_CFD", 0) Case "button" _WinAPI_SetWindowTheme($hCtrl, "DarkMode_Explorer", 0) Case "combobox" _WinAPI_SetWindowTheme($hCtrl, "DarkMode_CFD", 0) ; Handle ComboBox child-edit $hEdit = _WinAPI_FindWindowEx($hCtrl, "Edit") If $hEdit Then _WinAPI_SetWindowTheme($hEdit, "DarkMode_CFD", 0) _WinAPI_AllowDarkModeForWindow($hEdit, True) EndIf ; ComboBox dropdown list $hComboLBox = _WinAPI_FindWindowEx($hCtrl, "ComboLBox") If $hComboLBox Then _WinAPI_SetWindowTheme($hComboLBox, "DarkMode_Explorer", 0) _WinAPI_AllowDarkModeForWindow($hComboLBox, True) EndIf Case "syslistview32" _WinAPI_SetWindowTheme($hCtrl, "DarkMode_Explorer", 0) ; Enable double-buffering to prevent flicker during owner-draw _SendMessage($hCtrl, $LVM_SETEXTENDEDLISTVIEWSTYLE, $LVS_EX_DOUBLEBUFFER, $LVS_EX_DOUBLEBUFFER) ; LVM_SETEXTENDEDLISTVIEWSTYLE ; Apply dark theme to the ListView header control $hHeader = _SendMessage($hCtrl, $LVM_GETHEADER, 0, 0) If $hHeader Then _WinAPI_SetWindowTheme($hHeader, "DarkMode_ItemsView", 0) EndIf Case "systreeview32" _WinAPI_SetWindowTheme($hCtrl, "DarkMode_Explorer", 0) Case "msctls_trackbar32" ; Slider _WinAPI_SetWindowTheme($hCtrl, "DarkMode_Explorer", 0) Case "systabcontrol32" _WinAPI_SetWindowTheme($hCtrl, "DarkMode_Explorer", "") ;must be "" ; tab-Control background _SendMessage($hCtrl, $TCM_SETBKCOLOR, 0, $COLOR_BG_DARK) ; Try to make the UpDown (spinner for too many tabs) dark as well $hUpDown = _WinAPI_FindWindowEx($hCtrl, "msctls_updown32") If $hUpDown Then _WinAPI_SetWindowTheme($hUpDown, "DarkMode_Explorer", 0) Case "listbox" _WinAPI_SetWindowTheme($hCtrl, "DarkMode_Explorer", 0) Case "msctls_progress32" _WinAPI_SetWindowTheme($hCtrl, "DarkMode_CopyEngine", 0) Case "scrollbar" _WinAPI_SetWindowTheme($hCtrl, "DarkMode_Explorer", 0) Case "sysdatetimepick32" ;~ ConsoleWrite(_WinAPI_SetWindowTheme($hCtrl, "Explorer", 0) & @CRLF) ;~ _WinAPI_AllowDarkModeForWindow($hCtrl, True) Case "msctls_statusbar32" _WinAPI_SetWindowTheme($hCtrl, "DarkMode_DarkTheme", 0) Case Else _WinAPI_SetWindowTheme($hCtrl, "DarkMode_Explorer", 0) EndSwitch _WinAPI_AllowDarkModeForWindow($hCtrl, True) EndIf Next ; Update theme system _WinAPI_RefreshImmersiveColorPolicyState() _WinAPI_FlushMenuThemes() _WinAPI_DwmSetWindowAttribute($g_hGUI, $DWMWA_USE_IMMERSIVE_DARK_MODE, True) ; Redraw GUI _WinAPI_RedrawWindow($g_hGUI, 0, 0, $RDW_UPDATENOW) EndFunc ;==>_ApplyDarkModeToAllControls Func _CleanupSubclassing() ; Remove all subclasses If $g_pSubclassProc Then Local $hCtrl For $i = 0 To $g_iControlCount - 1 $hCtrl = $g_aControls[$i][1] If $hCtrl Then _WinAPI_RemoveWindowSubclass($hCtrl, DllCallbackGetPtr($g_pSubclassProc), $i) EndIf Next DllCallbackFree($g_pSubclassProc) $g_pSubclassProc = 0 EndIf EndFunc ;==>_CleanupSubclassing Func _SubclassProc($hWnd, $iMsg, $wParam, $lParam, $iID, $pData) Switch $iMsg Case $WM_NOTIFY Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam) Local $hFrom = $tNMHDR.hWndFrom Local $iCode = $tNMHDR.Code If $iCode = $NM_CUSTOMDRAW Then Local $tNMCD = DllStructCreate($tagNMCUSTOMDRAW, $lParam) Local $dwStage = $tNMCD.dwDrawStage Local $hDC = $tNMCD.hdc Switch StringLower(_WinAPI_GetClassName($hFrom)) Case "sysheader32" Switch $dwStage Case $CDDS_PREPAINT Return $CDRF_NOTIFYITEMDRAW Case $CDDS_ITEMPREPAINT _WinAPI_SetTextColor($hDC, _ColorToCOLORREF($COLOR_TEXT_LIGHT)) _WinAPI_SetBkColor($hDC, _ColorToCOLORREF($COLOR_BG_DARK)) Return BitOR($CDRF_NEWFONT, $CDRF_NOTIFYPOSTPAINT) EndSwitch EndSwitch EndIf Case $WM_PAINT Return _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) Case $WM_NCPAINT ; WS_EX_CLIENTEDGE border is drawn in WM_NCPAINT (non-client area), not WM_CTLCOLOR. ; We let Windows draw the default frame first, then overdraw it with our dark border. Local $sClass = StringLower(_WinAPI_GetClassName($hWnd)) If $sClass = "edit" Or $sClass = "listbox" Then Local $iRet = _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) Local $hDC = _WinAPI_GetWindowDC($hWnd) Local $tRECT = _WinAPI_GetWindowRect($hWnd) Local $iW = $tRECT.Right - $tRECT.Left Local $iH = $tRECT.Bottom - $tRECT.Top Local $hPen = _WinAPI_CreatePen(0, 1, _ColorToCOLORREF($COLOR_BORDER)) Local $hOldPen = _WinAPI_SelectObject($hDC, $hPen) Local $hNull = _WinAPI_GetStockObject(5) Local $hOldBr = _WinAPI_SelectObject($hDC, $hNull) DllCall("gdi32.dll", "bool", "Rectangle", "handle", $hDC, "int", 0, "int", 0, "int", $iW, "int", $iH) _WinAPI_SelectObject($hDC, $hOldPen) _WinAPI_SelectObject($hDC, $hOldBr) _WinAPI_DeleteObject($hPen) _WinAPI_ReleaseDC($hWnd, $hDC) Return $iRet EndIf EndSwitch Return _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) EndFunc ;==>_SubclassProc Func _DateProc($hWnd, $iMsg, $wParam, $lParam) Switch $iMsg Case $WM_PAINT Local $tPaint = DllStructCreate($tagPAINTSTRUCT) Local $hDC = _WinAPI_BeginPaint($hWnd, $tPaint) Local $tClient = _WinAPI_GetClientRect($hWnd) Local $iW = $tClient.Right Local $iH = $tClient.Bottom ; --- Memory DC for flicker-free rendering --- Local $hMemDC = _WinAPI_CreateCompatibleDC($hDC) Local $hBitmap = _WinAPI_CreateCompatibleBitmap($hDC, $iW, $iH) Local $hOldBmp = _WinAPI_SelectObject($hMemDC, $hBitmap) ; 1. Let Windows draw the light-mode control into memory DC _WinAPI_CallWindowProc($g_hDateOldProc, $hWnd, $WM_PRINTCLIENT, $hMemDC, $PRF_CLIENT) ; 2. Invert all pixels (background becomes black, text white, selection orange) Local $tRECT = DllStructCreate($tagRECT) $tRECT.right = $iW $tRECT.bottom = $iH _WinAPI_InvertRect($hMemDC, $tRECT) ; --- 3. PIXEL HACK: destroy orange highlight & set background color --- ; Strategy: render the light-mode control via WM_PRINTCLIENT, invert all pixels, ; then scan the bitmap and replace near-black (inverted white background) with the ; exact GUI background color, and convert all remaining pixels to grayscale. ; This eliminates the orange selection highlight and unifies the background. Local $iSize = $iW * $iH Local $tPixels = DllStructCreate("dword c[" & $iSize & "]") ; Load pixel array directly from bitmap memory Local $iBytes = DllCall("gdi32.dll", "long", "GetBitmapBits", "handle", $hBitmap, "long", $iSize * 4, "ptr", DllStructGetPtr($tPixels))[0] If $iBytes = $iSize * 4 Then Local $iPixel, $r, $g, $b, $iGray For $i = 1 To $iSize $iPixel = $tPixels.c(($i)) ; Split into color channels $b = BitAND($iPixel, 0xFF) $g = BitAND(BitShift($iPixel, 8), 0xFF) $r = BitAND(BitShift($iPixel, 16), 0xFF) ; Convert to grayscale (orange becomes mid-gray) $iGray = Int(($r + $g + $b) / 3) ; Very dark pixel = inverted white background If $iGray < 15 Then $iPixel = $COLOR_BG_DARK ; Replace with exact GUI background color Else ; Grayscale value for text (white) and selection (gray) ; (negative BitShift shifts left in AutoIt) $iPixel = BitOR(BitShift($iGray, -16), BitShift($iGray, -8), $iGray) EndIf $tPixels.c(($i)) = $iPixel Next ; Write cleaned pixels back into the bitmap DllCall("gdi32.dll", "long", "SetBitmapBits", "handle", $hBitmap, "long", $iSize * 4, "ptr", DllStructGetPtr($tPixels)) EndIf ; --- END PIXEL HACK --- ; --- Border color (hover effect) --- Local $iBorderColor = $COLOR_BORDER If _WinAPI_GetFocus() = $hWnd Then $iBorderColor = $COLOR_BORDER Local $tCursorPos = DllStructCreate($tagPOINT) DllCall("user32.dll", "bool", "GetCursorPos", "struct*", $tCursorPos) DllCall("user32.dll", "bool", "ScreenToClient", "hwnd", $hWnd, "struct*", $tCursorPos) If $tCursorPos.X >= 0 And $tCursorPos.X <= $iW And $tCursorPos.Y >= 0 And $tCursorPos.Y <= $iH Then $iBorderColor = $COLOR_BORDER_LIGHT EndIf ; --- Draw border --- Local $hPen = _WinAPI_CreatePen(0, 1, _ColorToCOLORREF($iBorderColor)) Local $hNullBr = _WinAPI_GetStockObject(5) Local $hOldPen = _WinAPI_SelectObject($hMemDC, $hPen) Local $hOldBr = _WinAPI_SelectObject($hMemDC, $hNullBr) DllCall("gdi32.dll", "bool", "Rectangle", "handle", $hMemDC, "int", 0, "int", 0, "int", $iW, "int", $iH) _WinAPI_SelectObject($hMemDC, $hOldPen) _WinAPI_SelectObject($hMemDC, $hOldBr) _WinAPI_DeleteObject($hPen) ; --- Copy finished result to screen in one step (no flicker) --- _WinAPI_BitBlt($hDC, 0, 0, $iW, $iH, $hMemDC, 0, 0, $SRCCOPY) ; --- Cleanup --- _WinAPI_SelectObject($hMemDC, $hOldBmp) _WinAPI_DeleteObject($hBitmap) _WinAPI_DeleteDC($hMemDC) _WinAPI_EndPaint($hWnd, $tPaint) Return 0 Case $WM_ERASEBKGND Return 1 Case $WM_SETFOCUS, $WM_KILLFOCUS Local $iRet = _WinAPI_CallWindowProc($g_hDateOldProc, $hWnd, $iMsg, $wParam, $lParam) _WinAPI_InvalidateRect($hWnd, 0, False) Return $iRet Case $WM_MOUSEMOVE Local $iRet = _WinAPI_CallWindowProc($g_hDateOldProc, $hWnd, $iMsg, $wParam, $lParam) If Not $g_bHover Then $g_bHover = True _WinAPI_InvalidateRect($hWnd, 0, False) EndIf Return $iRet Case $WM_MOUSELEAVE $g_bHover = False _WinAPI_InvalidateRect($hWnd, 0, False) EndSwitch Return _WinAPI_CallWindowProc($g_hDateOldProc, $hWnd, $iMsg, $wParam, $lParam) EndFunc ;==>_DateProc Func _MakeMenuOwnerDraw($hWnd) ; Converts all top-level menu items to MFT_OWNERDRAW so WM_MEASUREITEM / WM_DRAWITEM ; can render them with the dark color scheme. Must be called again after every DPI change ; to force Windows to re-send WM_MEASUREITEM with updated dimensions. $g_hMenu = _GUICtrlMenu_GetMenu($hWnd) If Not $g_hMenu Then Return False Local $iCount = _GUICtrlMenu_GetItemCount($g_hMenu) If $iCount <= 0 Then Return False ReDim $g_aMenuText[$iCount] Local $tText, $iLen For $i = 0 To $iCount - 1 ; GetMenuStringW is more reliable than _GUICtrlMenu_GetItemText for Unicode menu strings $tText = DllStructCreate("wchar s[256]") $iLen = DllCall("user32.dll", "int", "GetMenuStringW", "handle", $g_hMenu, "uint", $i, "struct*", $tText, "int", 255, "uint", $MF_BYPOSITION) If IsArray($iLen) And $iLen[0] > 0 Then $g_aMenuText[$i] = $tText.s Else $g_aMenuText[$i] = "" EndIf ; Flag item as owner-drawn - triggers WM_MEASUREITEM immediately _GUICtrlMenu_SetItemType($g_hMenu, $i, $MFT_OWNERDRAW, True) Next ; Force immediate repaint of the menu bar _GUICtrlMenu_DrawMenuBar($hWnd) _WinAPI_RedrawWindow($hWnd, 0, 0, BitOR($RDW_INVALIDATE, $RDW_UPDATENOW)) Return True EndFunc ;==>_MakeMenuOwnerDraw Func _WM_DPICHANGED($hWnd, $iMsg, $wParam, $lParam) #forceref $iMsg _WinAPI_LockWindowUpdate($hWnd) ; suppress painting during DPI transition ; LoWord(wParam) = new DPI value sent by Windows $g_fScale = _WinAPI_LoWord($wParam) / 96 ; lParam = suggested window RECT already adjusted for new DPI - use it directly Local $tRECT = DllStructCreate($tagRECT, $lParam) Local $iX = $tRECT.left, $iY = $tRECT.top, $iW = $tRECT.right - $iX, $iH = $tRECT.bottom - $iY _WinAPI_SetWindowPos($hWnd, 0, $iX, $iY, $iW, $iH, BitOR($SWP_NOZORDER, $SWP_NOACTIVATE)) ; Reposition/resize all registered controls and apply new font _ApplyDPIScaling($g_fScale) ; Recreate menu font for new DPI. ; Old font is kept alive until AFTER _MakeMenuOwnerDraw so WM_MEASUREITEM can still use it. Local $hOldMenuFont = $g_hMenuFont Local $iHeight = -Round(_WinAPI_MulDiv(8.5, _WinAPI_LoWord($wParam), 72)) $g_hMenuFont = _WinAPI_CreateFont($iHeight, 0, 0, 0, $FW_NORMAL, False, False, False, _ $DEFAULT_CHARSET, $OUT_DEFAULT_PRECIS, $CLIP_DEFAULT_PRECIS, $PROOF_QUALITY, $DEFAULT_PITCH, "Arial") ; Re-register owner-draw -> forces WM_MEASUREITEM with the new font already active _MakeMenuOwnerDraw($g_hGUI) If $hOldMenuFont Then _WinAPI_DeleteObject($hOldMenuFont) ; safe to delete now _EnableMenuHotTrack($g_hMenu) ; Rescale statusbar part widths using the base (unscaled) values in $g_aStatusbarParts If $g_hStatusbar Then Local $aScaledParts[4] For $i = 0 To 3 $aScaledParts[$i] = $g_aStatusbarParts[$i] * $g_fScale Next _GUICtrlStatusBar_SetParts($g_hStatusbar, $aScaledParts) _SendMessage($g_hStatusbar, $WM_SIZE, 0, 0) EndIf _WinAPI_LockWindowUpdate(0) Return 1 EndFunc ;==>_WM_DPICHANGED Func _WM_MEASUREITEM($hWnd, $iMsg, $wParam, $lParam) Local $tagMEASUREITEM = "uint CtlType;uint CtlID;uint itemID;uint itemWidth;uint itemHeight;ulong_ptr itemData" Local $t = DllStructCreate($tagMEASUREITEM, $lParam) If Not IsDllStruct($t) Then Return $GUI_RUNDEFMSG If $t.CtlType <> $ODT_MENU Then Return $GUI_RUNDEFMSG ; only handle menu items Local $itemID = $t.itemID ; itemID is the menu item command ID, not its position. ; AutoIt assigns IDs starting at 3 for the first top-level menu item. Local $iPos = -1 For $i = 0 To UBound($g_aMenuText) - 1 If $itemID = ($i + 3) Then ; offset 3 = AutoIt internal menu ID base $iPos = $i ExitLoop EndIf Next ; Fallback if ID mapping failed If $iPos < 0 Then $iPos = $itemID If $iPos < 0 Or $iPos >= UBound($g_aMenuText) Then $iPos = 0 Local $sText = $g_aMenuText[$iPos] ; Measure text using DEFAULT_GUI_FONT - Windows keeps this stock object DPI-aware automatically. ; Using a window DC here is intentional: DEFAULT_GUI_FONT is a stock object not affected by DC caching. ; Multiply by $g_fScale because GetTextExtentPoint32 returns logical pixels at 96 DPI baseline. Local $hDC = _WinAPI_GetDC($hWnd) Local $hFont = _WinAPI_GetStockObject($DEFAULT_GUI_FONT) Local $hOldFont = _WinAPI_SelectObject($hDC, $hFont) Local $tSize = _WinAPI_GetTextExtentPoint32($hDC, $sText) Local $iTextWidth = $tSize.X * $g_fScale Local $iTextHeight = $tSize.Y * $g_fScale _WinAPI_SelectObject($hDC, $hOldFont) _WinAPI_ReleaseDC($hWnd, $hDC) ; Pass measured size back to Windows (no padding needed - DrawText uses exact rect) $t.itemWidth = $iTextWidth $t.itemHeight = $iTextHeight Return 1 EndFunc ;==>_WM_MEASUREITEM Func _WM_DRAWITEM($hWnd, $iMsg, $wParam, $lParam) Local $tagDRAWITEM = "uint CtlType;uint CtlID;uint itemID;uint itemAction;uint itemState;ptr hwndItem;handle hDC;" & _ "long left;long top;long right;long bottom;ulong_ptr itemData" Local $t = DllStructCreate($tagDRAWITEM, $lParam) If Not IsDllStruct($t) Then Return $GUI_RUNDEFMSG If $t.CtlType <> $ODT_MENU Then Return $GUI_RUNDEFMSG Local $hDC = $t.hDC Local $left = $t.left Local $top = $t.top Local $right = $t.right Local $bottom = $t.bottom Local $state = $t.itemState Local $itemID = $t.itemID ; convert itemID to position Local $iPos = -1 For $i = 0 To UBound($g_aMenuText) - 1 If $itemID = ($i + 3) Then $iPos = $i ExitLoop EndIf Next If $iPos < 0 Then $iPos = $itemID If $iPos < 0 Or $iPos >= UBound($g_aMenuText) Then $iPos = 0 Local $sText = $g_aMenuText[$iPos] $sText = StringReplace($sText, "&", "") ; Colors Local $clrBG = _ColorToCOLORREF($COLOR_BG_DARK) Local $clrSel = _ColorToCOLORREF($COLOR_MENU_SELECT) Local $clrText = _ColorToCOLORREF($COLOR_TEXT_LIGHT) Static $iDrawCount = 0 Static $bFullBarDrawn = False ; Track how many items have been drawn in this WM_DRAWITEM cycle. ; When the first item (iPos=0) is drawn, fill the entire menu bar background first ; to avoid leftover pixels between items during redraws. $iDrawCount += 1 ; If we are at the first item AND the bar has not yet been drawn If $iPos = 0 And Not $bFullBarDrawn Then ; Get the full window width Local $tClient = _WinAPI_GetClientRect($hWnd) Local $iFullWidth = $tClient.right ; Fill the entire menu bar Local $tFullMenuBar = DllStructCreate($tagRECT) With $tFullMenuBar .left = 0 .top = $top .right = $iFullWidth + 3 .bottom = $bottom EndWith Local $hFullBrush = _WinAPI_CreateSolidBrush($clrBG) _WinAPI_FillRect($hDC, $tFullMenuBar, $hFullBrush) _WinAPI_DeleteObject($hFullBrush) EndIf ; After drawing all items, mark as "drawn" If $iDrawCount >= UBound($g_aMenuText) Then $bFullBarDrawn = True $iDrawCount = 0 EndIf ; Draw background for the area AFTER the last menu item If $iPos = (UBound($g_aMenuText) - 1) Then ; Last menu Local $tClient = _WinAPI_GetClientRect($hWnd) Local $iFullWidth = $tClient.right ; Fill only the area to the RIGHT of the last menu item If $right < $iFullWidth Then Local $tEmptyArea = DllStructCreate($tagRECT) With $tEmptyArea .left = $right .top = $top .right = $iFullWidth + _WinAPI_GetSystemMetricsForDpi($SM_CYMENU, Round($g_fScale * 96)) .bottom = $bottom EndWith Local $hEmptyBrush = _WinAPI_CreateSolidBrush($clrBG) _WinAPI_FillRect($hDC, $tEmptyArea, $hEmptyBrush) _WinAPI_DeleteObject($hEmptyBrush) EndIf EndIf ; Draw item background (selected = lighter) Local $bSelected = BitAND($state, $ODS_SELECTED) Local $bHot = BitAND($state, $ODS_HOTLIGHT) Local $hBrush If $bSelected Then $hBrush = _WinAPI_CreateSolidBrush($clrSel) ElseIf $bHot Then $hBrush = _WinAPI_CreateSolidBrush(_ColorToCOLORREF($COLOR_HOTTRACK_MENU)) Else $hBrush = _WinAPI_CreateSolidBrush($clrBG) EndIf Local $tItemRect = DllStructCreate($tagRECT) With $tItemRect .left = $left .top = $top .right = $right .bottom = $bottom EndWith _WinAPI_FillRect($hDC, $tItemRect, $hBrush) _WinAPI_DeleteObject($hBrush) ; Setup font Local $hFont = ($g_hMenuFont ? $g_hMenuFont : _WinAPI_GetStockObject($DEFAULT_GUI_FONT)) Local $hOldFont = _WinAPI_SelectObject($hDC, $hFont) _WinAPI_SetBkMode($hDC, $TRANSPARENT) _WinAPI_SetTextColor($hDC, $clrText) ; Draw text Local $tTextRect = DllStructCreate($tagRECT) With $tTextRect .left = $left + 10 .top = $top + 4 .right = $right - 10 .bottom = $bottom - 4 EndWith DllCall("user32.dll", "int", "DrawTextW", "handle", $hDC, "wstr", $sText, "int", -1, "ptr", DllStructGetPtr($tTextRect), "uint", BitOR($DT_SINGLELINE, $DT_VCENTER, $DT_LEFT)) If $hOldFont Then _WinAPI_SelectObject($hDC, $hOldFont) Return 1 EndFunc ;==>_WM_DRAWITEM Func _WM_CTLCOLOR($hWnd, $iMsg, $wParam, $lParam) Local $hDC = $wParam Local $hCtrl = $lParam ; If the control is the special green label -> return green background If $hCtrl = $g_hLabelGreen Then ; black text on a green background _WinAPI_SetTextColor($hDC, _ColorToCOLORREF(0x000000)) _WinAPI_SetBkColor($hDC, _ColorToCOLORREF(0x00FF00)) _WinAPI_SetBkMode($hDC, $OPAQUE) ; important, otherwise it remains transparent and you cannot see the background If $g_hBrushGreen Then Return $g_hBrushGreen EndIf ; --- Special case: Make "Sample Pic" label transparent --- If $hCtrl = $g_hLabelPic Then ; set transparent background _WinAPI_SetBkMode($hDC, $TRANSPARENT) ; set text color (if necessary) - e.g., white _WinAPI_SetTextColor($hDC, _ColorToCOLORREF($COLOR_TEXT_LIGHT)) ; return NULL_BRUSH (stock object), so Windows does NOT fill with your dark brush Local $hNull = _WinAPI_GetStockObject(5) ; 5 = NULL_BRUSH If $hNull Then Return $hNull ; Fallback if not available: Return $GUI_RUNDEFMSG EndIf ; --- Default behavior for all other statics / controls --- _WinAPI_SetTextColor($hDC, _ColorToCOLORREF($COLOR_TEXT_LIGHT)) Local $hBrush = $g_hBrushEdit Local $iColor = $COLOR_EDIT_BG Switch $iMsg Case $WM_CTLCOLORBTN $hBrush = $g_hBrushButton $iColor = $COLOR_BUTTON_BG Case $WM_CTLCOLORSTATIC $hBrush = $g_hBrushBg $iColor = $COLOR_BG_DARK EndSwitch _WinAPI_SetBkColor($hDC, _ColorToCOLORREF($iColor)) _WinAPI_SetBkMode($hDC, $TRANSPARENT) Return $hBrush EndFunc ;==>_WM_CTLCOLOR Func _WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam) #forceref $hWnd, $iMsg, $wParam Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $tInfo, $tBuffer, $tBuffer2, $iCtrl $tNMHDR = DllStructCreate($tagNMHDR, $lParam) $hWndFrom = HWnd($tNMHDR.hWndFrom) $iIDFrom = $tNMHDR.IDFrom $iCode = $tNMHDR.Code ; --- Slider (msctls_trackbar32) custom drawing --- If $iCode = $NM_CUSTOMDRAW And StringLower(_WinAPI_GetClassName($hWndFrom)) = "msctls_trackbar32" Then Local $tNMCD = DllStructCreate($tagNMCUSTOMDRAW, $lParam) Local $dwStage = $tNMCD.dwDrawStage Local $hDC = $tNMCD.hdc Local $dwItemSpec = $tNMCD.dwItemSpec Switch $dwStage Case $CDDS_PREPAINT ; Remove focus rectangle from slider DllStructSetData($tNMCD, "ItemState", BitXOR(DllStructGetData($tNMCD, "ItemState"), $CDIS_FOCUS)) Return $CDRF_NOTIFYITEMDRAW ; request per-item notifications Case $CDDS_ITEMPREPAINT Local Const $TBCD_TICS = 0x0001 ; tick marks Local Const $TBCD_THUMB = 0x0002 ; draggable thumb Local Const $TBCD_CHANNEL = 0x0003 ; slider channel/track Local $tRECT = DllStructCreate($tagRECT) $tRECT.left = $tNMCD.left $tRECT.top = $tNMCD.top $tRECT.right = $tNMCD.right $tRECT.bottom = $tNMCD.bottom Switch $dwItemSpec Case $TBCD_TICS ; Let Windows draw tick marks normally Return $CDRF_DODEFAULT Case $TBCD_THUMB ; Draw thumb as a pentagon (rectangle + downward arrow) Local $iL = $tNMCD.left Local $iT = $tNMCD.top Local $iR = $tNMCD.right - 1 ; -1 to stay within bounds and avoid paint artifacts Local $iB = $tNMCD.bottom Local $iMid = ($iL + $iR) / 2 ; horizontal center (tip of arrow) Local $iSplit = $iB - ($iR - $iL) / 2 ; y-position where rectangle ends and arrow begins ; Pentagon points: top-left, top-right, right-middle, bottom-tip, left-middle Local $tPoints = DllStructCreate("int p[10]") $tPoints.p((1)) = $iL $tPoints.p((2)) = $iT $tPoints.p((3)) = $iR $tPoints.p((4)) = $iT $tPoints.p((5)) = $iR $tPoints.p((6)) = $iSplit $tPoints.p((7)) = $iMid $tPoints.p((8)) = $iB $tPoints.p((9)) = $iL $tPoints.p((10)) = $iSplit ; Fill and outline thumb with blue accent color Local $hBrush = _WinAPI_CreateSolidBrush(_ColorToCOLORREF(0x0078D4)) Local $hPen = _WinAPI_CreatePen(0, 1, _ColorToCOLORREF($COLOR_CONTROL_BG)) Local $hOldBrush = _WinAPI_SelectObject($hDC, $hBrush) Local $hOldPen = _WinAPI_SelectObject($hDC, $hPen) DllCall("gdi32.dll", "bool", "Polygon", "handle", $hDC, "struct*", $tPoints, "int", 5) _WinAPI_SelectObject($hDC, $hOldBrush) _WinAPI_SelectObject($hDC, $hOldPen) _WinAPI_DeleteObject($hBrush) _WinAPI_DeleteObject($hPen) Return $CDRF_SKIPDEFAULT ; skip default drawing Case $TBCD_CHANNEL ; Fill channel with border color Local $hBrush = _WinAPI_CreateSolidBrush(_ColorToCOLORREF($COLOR_BORDER)) _WinAPI_FillRect($hDC, $tRECT, $hBrush) _WinAPI_DeleteObject($hBrush) Return $CDRF_SKIPDEFAULT ; skip default drawing EndSwitch EndSwitch EndIf ; --- Per-control notification handling --- Local Static $iTheme Switch $hWndFrom Case $g_hDate ; thanks to argumentum for the code :-) Switch $iCode Case $NM_SETFOCUS ; Disable visual theme when DateTime control receives focus _WinAPI_SetThemeAppProperties(0) Case $NM_KILLFOCUS _WinAPI_SetThemeAppProperties($iTheme) ; cudos to argumentum Case $DTN_DROPDOWN ; Apply dark colors when the calendar dropdown opens Local $iCtrl = _GUICtrlDTP_GetMonthCal($hWndFrom) ; get the MonthCal child handle _WinAPI_SetWindowTheme($iCtrl, "", "") ; remove theme for manual color control _GUICtrlMonthCal_SetColor($iCtrl, $MCSC_TEXT, $COLOR_TEXT_LIGHT) _GUICtrlMonthCal_SetColor($iCtrl, $MCSC_TITLEBK, $COLOR_BG_DARK) _GUICtrlMonthCal_SetColor($iCtrl, $MCSC_TITLETEXT, $COLOR_TEXT_LIGHT) _GUICtrlMonthCal_SetColor($iCtrl, $MCSC_MONTHBK, $COLOR_BG_DARK) _GUICtrlMonthCal_SetColor($iCtrl, $MCSC_TRAILINGTEXT, $COLOR_TEXT_LIGHT) Case $DTN_CLOSEUP ; Calendar dropdown closed - no action needed EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>_WM_NOTIFY Func _WM_ACTIVATE($hWnd, $iMsg, $wParam, $lParam) If $hWnd <> $g_hGUI Then Return $GUI_RUNDEFMSG _OverpaintWhiteLine() Return $GUI_RUNDEFMSG EndFunc ;==>_WM_ACTIVATE Func _WM_WINDOWPOSCHANGED($hWnd, $iMsg, $wParam, $lParam) If $hWnd <> $g_hGUI Then Return $GUI_RUNDEFMSG _OverpaintWhiteLine() Return $GUI_RUNDEFMSG EndFunc ;==>_WM_WINDOWPOSCHANGED Func _WM_MENUCOMMAND($hWnd, $iMsg, $wParam, $lParam) #forceref $hWnd, $iMsg Local $iPos = $wParam ;Menu Item Position (0-based index) Local $hMenu = $lParam ;Menu Handle Switch $hMenu Case $g_hMenu1 ConsoleWrite("From Menu One" & @CRLF) Switch $iPos Case 0 ; SubMenu One A ConsoleWrite("SubMenu One A clicked" & @CRLF) Case 1 ; SubMenu One B ConsoleWrite("SubMenu One B clicked" & @CRLF) Case 2 ; About ConsoleWrite("About clicked!" & @CRLF) GUICtrlSendToDummy($g_AboutDummy) Return 0 EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>_WM_MENUCOMMAND Func _WM_SYSCOMMAND($hWnd, $iMsg, $wParam, $lParam) #forceref $hWnd, $iMsg, $lParam Switch BitAND($wParam, 0x0000FFFF) Case $idAbout GUICtrlSendToDummy($g_AboutDummy) EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>_WM_SYSCOMMAND Func _CleanupBrushes() ; Release all GDI objects created at startup. Called on GUI close. If $g_hBrushEdit Then _WinAPI_DeleteObject($g_hBrushEdit) If $g_hBrushButton Then _WinAPI_DeleteObject($g_hBrushButton) If $g_hBrushBg Then _WinAPI_DeleteObject($g_hBrushBg) If $g_hBrushGreen Then _WinAPI_DeleteObject($g_hBrushGreen) If $g_hMenuFont Then _WinAPI_DeleteObject($g_hMenuFont) If $g_hCtrlFont Then _WinAPI_DeleteObject($g_hCtrlFont) ; control font created by _ApplyDPIScaling Local $j For $j = 0 To UBound($g_aCustomFonts) - 1 If $g_aCustomFonts[$j] Then _WinAPI_DeleteObject($g_aCustomFonts[$j]) Next EndFunc ;==>_CleanupBrushes Func _EnableDarkScrollBars() ; Apply DarkMode_Explorer theme to all controls that have scrollbars. ; Also handles TreeView with $TVS_CHECKBOXES which creates explicit ScrollBar child windows. Local $tScrollInfo, $sClass, $hCtrl, $hChild For $i = 0 To $g_iControlCount - 1 $hCtrl = $g_aControls[$i][1] If Not $hCtrl Then ContinueLoop ; 1ï¸ Normal attempt (works for most controls) $tScrollInfo = _GUIScrollBars_GetScrollInfoEx($hCtrl, 1) If IsDllStruct($tScrollInfo) Then _WinAPI_SetWindowTheme($hCtrl, "DarkMode_Explorer", 0) ; 2ï¸ Extension: If the control has its own scrollbar child windows (e.g., TreeView with $TVS_CHECKBOXES) $hChild = _WinAPI_GetWindow($hCtrl, $GW_CHILD) While $hChild $sClass = _WinAPI_GetClassName($hChild) If StringCompare($sClass, "ScrollBar") = 0 Then ; Set DarkMode on the ScrollBar itself _WinAPI_SetWindowTheme($hChild, "DarkMode_Explorer", 0) _WinAPI_AllowDarkModeForWindow($hChild, True) EndIf $hChild = _WinAPI_GetWindow($hChild, $GW_HWNDNEXT) WEnd Next EndFunc ;==>_EnableDarkScrollBars Func _WinProc($hWnd, $iMsg, $wParam, $lParam) ; Custom window procedure for tab control with Dark Mode Switch $iMsg Case $WM_ERASEBKGND Return 1 ; Prevent background erase to avoid flicker Case $WM_PAINT Local $tPaint = DllStructCreate($tagPAINTSTRUCT) Local $hDC = DllCall("user32.dll", "handle", "BeginPaint", "hwnd", $hWnd, "struct*", $tPaint) If @error Or Not $hDC[0] Then Return _WinAPI_CallWindowProc($g_hProc, $hWnd, $iMsg, $wParam, $lParam) $hDC = $hDC[0] ; Get client rectangle Local $tClient = _WinAPI_GetClientRect($hWnd) If Not IsDllStruct($tClient) Then _WinAPI_EndPaint($hWnd, $tPaint) Return 0 EndIf Local $iWidth = $tClient.Right Local $iHeight = $tClient.Bottom ; Create memory DC for double buffering Local $hMemDC = _WinAPI_CreateCompatibleDC($hDC) Local $hBitmap = _WinAPI_CreateCompatibleBitmap($hDC, $iWidth, $iHeight) Local $hOldBmp = _WinAPI_SelectObject($hMemDC, $hBitmap) ; Fill background but exclude overlapping GUI controls from painting Local $hParent = _WinAPI_GetParent($hWnd) Local $hChild = _WinAPI_GetWindow($hParent, $GW_CHILD) Local $tCR, $tPR = _WinAPI_GetWindowRect($hWnd) Local $left, $top, $right, $bottom While $hChild If $hChild <> $hWnd And _WinAPI_IsWindowVisible($hChild) Then $tCR = _WinAPI_GetWindowRect($hChild) ; Only exclude controls that lie fully within the tab control area If $tCR.left >= $tPR.left And $tCR.right <= $tPR.right And $tCR.top >= $tPR.top And $tCR.bottom <= $tPR.bottom Then $left = $tCR.left - $tPR.left $top = $tCR.top - $tPR.top $right = $tCR.right - $tPR.left $bottom = $tCR.bottom - $tPR.top ; Exclude from offscreen bitmap (prevents black fill) DllCall("gdi32.dll", "int", "ExcludeClipRect", "handle", $hMemDC, "int", $left, "int", $top, "int", $right, "int", $bottom) ; Exclude from screen DC (prevents BitBlt overwrite) DllCall("gdi32.dll", "int", "ExcludeClipRect", "handle", $hDC, "int", $left, "int", $top, "int", $right, "int", $bottom) EndIf EndIf $hChild = _WinAPI_GetWindow($hChild, $GW_HWNDNEXT) WEnd ; Fill background Local $hBrush = _WinAPI_CreateSolidBrush(_ColorToCOLORREF($COLOR_BG_DARK)) _WinAPI_FillRect($hMemDC, $tClient, $hBrush) _WinAPI_DeleteObject($hBrush) ; Get tab info Local $iTabCount = _SendMessage($hWnd, $TCM_GETITEMCOUNT, 0, 0) Local $iCurSel = _SendMessage($hWnd, $TCM_GETCURSEL, 0, 0) ; Setup font Local $hFont = _SendMessage($hWnd, $WM_GETFONT, 0, 0) If Not $hFont Then $hFont = _WinAPI_GetStockObject($DEFAULT_GUI_FONT) Local $hOldFont = _WinAPI_SelectObject($hMemDC, $hFont) _WinAPI_SetBkMode($hMemDC, $TRANSPARENT) _WinAPI_SetTextColor($hMemDC, _ColorToCOLORREF($COLOR_TEXT_LIGHT)) ; Draw each tab Local $tRECT, $iLeft, $iTop, $iRight, $iBottom, $tItem, $tText, $bSelected, $iTabColor, $hTabBrush, $tTabRect, _ $sText, $hPen, $hOldPen, $hPenSep, $hOldPenSep, $tTextRect, $hBorderPen, $hOldBorderPen, $hNullBrush, $hOldBorderBrush For $i = 0 To $iTabCount - 1 ; Get tab rectangle using TCM_GETITEMRECT $tRECT = DllStructCreate($tagRECT) $aResult = DllCall("user32.dll", "lresult", "SendMessageW", "hwnd", $hWnd, "uint", $TCM_GETITEMRECT, "wparam", $i, "struct*", $tRECT) If @error Or Not $aResult[0] Then ContinueLoop $iLeft = $tRECT.Left $iTop = $tRECT.Top $iRight = $tRECT.Right $iBottom = $tRECT.Bottom ; Skip if rectangle is invalid If $iLeft >= $iRight Or $iTop >= $iBottom Then ContinueLoop ; Get tab text $tItem = DllStructCreate("uint Mask;dword dwState;dword dwStateMask;ptr pszText;int cchTextMax;int iImage;lparam lParam") $tText = DllStructCreate("wchar Text[256]") With $tItem .Mask = $TCIF_TEXT .pszText = DllStructGetPtr($tText) .cchTextMax = 256 EndWith DllCall("user32.dll", "lresult", "SendMessageW", "hwnd", $hWnd, "uint", $TCM_GETITEMW, "wparam", $i, "struct*", $tItem) $sText = DllStructGetData($tText, "Text") ; Draw tab background $bSelected = ($i = $iCurSel) $iTabColor = $bSelected ? $COLOR_BUTTON_BG : $COLOR_BG_DARK $hTabBrush = _WinAPI_CreateSolidBrush(_ColorToCOLORREF($iTabColor)) $tTabRect = DllStructCreate($tagRECT) With $tTabRect .Left = $iLeft .Top = $iTop .Right = $iRight .Bottom = $iBottom EndWith _WinAPI_FillRect($hMemDC, $tTabRect, $hTabBrush) _WinAPI_DeleteObject($hTabBrush) ; Draw selection indicator (top border for selected tab) If $bSelected Then $hPen = _WinAPI_CreatePen(0, 2, _ColorToCOLORREF(0x0078D4)) ; Blue accent $hOldPen = _WinAPI_SelectObject($hMemDC, $hPen) _WinAPI_MoveTo($hMemDC, $iLeft, $iTop) _WinAPI_LineTo($hMemDC, $iRight - 2, $iTop) _WinAPI_SelectObject($hMemDC, $hOldPen) _WinAPI_DeleteObject($hPen) EndIf ; Draw separator between tabs If $i < $iTabCount - 1 Then $hPenSep = _WinAPI_CreatePen(0, 1, _ColorToCOLORREF($COLOR_BORDER)) $hOldPenSep = _WinAPI_SelectObject($hMemDC, $hPenSep) _WinAPI_MoveTo($hMemDC, $iRight - 1, $iTop + 4) _WinAPI_LineTo($hMemDC, $iRight - 1, $iBottom - 4) _WinAPI_SelectObject($hMemDC, $hOldPenSep) _WinAPI_DeleteObject($hPenSep) EndIf ; Draw text centered in tab $tTextRect = DllStructCreate($tagRECT) With $tTextRect .Left = $iLeft + 6 .Top = $iTop + 3 .Right = $iRight - 6 .Bottom = $iBottom - 3 EndWith DllCall("user32.dll", "int", "DrawTextW", _ "handle", $hMemDC, _ "wstr", $sText, _ "int", -1, _ "struct*", $tTextRect, _ "uint", BitOR($DT_CENTER, $DT_VCENTER, $DT_SINGLELINE)) Next ; Draw border around entire control $hBorderPen = _WinAPI_CreatePen(0, 1, _ColorToCOLORREF($COLOR_BORDER)) $hOldBorderPen = _WinAPI_SelectObject($hMemDC, $hBorderPen) $hNullBrush = _WinAPI_GetStockObject(5) ; NULL_BRUSH $hOldBorderBrush = _WinAPI_SelectObject($hMemDC, $hNullBrush) DllCall("gdi32.dll", "bool", "Rectangle", "handle", $hMemDC, "int", 0, "int", 0, "int", $iWidth, "int", $iHeight) _WinAPI_SelectObject($hMemDC, $hOldBorderPen) _WinAPI_SelectObject($hMemDC, $hOldBorderBrush) _WinAPI_DeleteObject($hBorderPen) ; Copy to screen _WinAPI_BitBlt($hDC, 0, 0, $iWidth, $iHeight, $hMemDC, 0, 0, $SRCCOPY) ; Cleanup _WinAPI_SelectObject($hMemDC, $hOldFont) _WinAPI_SelectObject($hMemDC, $hOldBmp) _WinAPI_DeleteObject($hBitmap) _WinAPI_DeleteDC($hMemDC) _WinAPI_EndPaint($hWnd, $tPaint) Return 0 Case $WM_PARENTNOTIFY ; Fired when a child window is created inside the tab control. ; The tab spinner (msctls_updown32) is created lazily by Windows when tabs overflow - ; it doesn't exist at init time, so we theme it here the moment it appears. If _WinAPI_LoWord($wParam) = $WM_CREATE Then Local $hNewChild = HWnd($lParam) ; lParam carries the new child's HWND as integer - must cast! If StringLower(_WinAPI_GetClassName($hNewChild)) = "msctls_updown32" Then _WinAPI_AllowDarkModeForWindow($hNewChild, True) _WinAPI_SetWindowTheme($hNewChild, "DarkMode_Explorer", 0) _SendMessage($hNewChild, $WM_THEMECHANGED, 0, 0) EndIf EndIf Return _WinAPI_CallWindowProc($g_hProc, $hWnd, $iMsg, $wParam, $lParam) EndSwitch Return _WinAPI_CallWindowProc($g_hProc, $hWnd, $iMsg, $wParam, $lParam) EndFunc ;==>_WinProc Func _WinAPI_FindWindowEx($hParent, $sClass, $sTitle = "", $hAfter = 0) Local $ret = DllCall("user32.dll", "hwnd", "FindWindowExW", "hwnd", $hParent, "hwnd", $hAfter, "wstr", $sClass, "wstr", $sTitle) If @error Or Not IsArray($ret) Then Return 0 Return $ret[0] EndFunc ;==>_WinAPI_FindWindowEx #Region DarkMode API Func _WinAPI_ShouldAppsUseDarkMode() Local $aResult = DllCall("UxTheme.dll", "bool", 132) If @error Then Return SetError(1, 0, False) Return ($aResult[0] <> 0) EndFunc ;==>_WinAPI_ShouldAppsUseDarkMode Func _WinAPI_AllowDarkModeForWindow($hWND, $bAllow = True) Local $aResult = DllCall("UxTheme.dll", "bool", 133, "hwnd", $hWND, "bool", $bAllow) If @error Then Return SetError(1, 0, False) Return ($aResult[0] <> 0) EndFunc ;==>_WinAPI_AllowDarkModeForWindow Func _WinAPI_FlushMenuThemes() Local $aResult = DllCall("UxTheme.dll", "none", 136) If @error Then Return SetError(1, 0, False) Return True EndFunc ;==>_WinAPI_FlushMenuThemes Func _WinAPI_RefreshImmersiveColorPolicyState() Local $aResult = DllCall("UxTheme.dll", "none", 104) If @error Then Return SetError(1, 0, False) Return True EndFunc ;==>_WinAPI_RefreshImmersiveColorPolicyState Func _WinAPI_IsDarkModeAllowedForWindow($hWND) Local $aResult = DllCall("UxTheme.dll", "bool", 137, "hwnd", $hWND) If @error Then Return SetError(1, 0, False) Return ($aResult[0] <> 0) EndFunc ;==>_WinAPI_IsDarkModeAllowedForWindow Func _WinAPI_GetIsImmersiveColorUsingHighContrast($iIMMERSIVE_HC_CACHE_MODE) Local $aResult = DllCall("UxTheme.dll", "bool", 106, "long", $iIMMERSIVE_HC_CACHE_MODE) If @error Then Return SetError(1, 0, False) Return ($aResult[0] <> 0) EndFunc ;==>_WinAPI_GetIsImmersiveColorUsingHighContrast Func _WinAPI_OpenNcThemeData($hWND, $tClassList) Local $aResult = DllCall("UxTheme.dll", "hwnd", 49, "hwnd", $hWND, "struct*", $tClassList) If @error Then Return SetError(1, 0, False) Return $aResult[0] EndFunc ;==>_WinAPI_OpenNcThemeData Func _WinAPI_ShouldSystemUseDarkMode() Local $aResult = DllCall("UxTheme.dll", "bool", 138) If @error Then Return SetError(1, 0, False) Return ($aResult[0] <> 0) EndFunc ;==>_WinAPI_ShouldSystemUseDarkMode Func _WinAPI_IsDarkModeAllowedForApp() Local $aResult = DllCall("UxTheme.dll", "bool", 139) If @error Then Return SetError(1, 0, False) Return ($aResult[0] <> 0) EndFunc ;==>_WinAPI_IsDarkModeAllowedForApp Func _WinAPI_AllowDarkModeForApp($bAllow = True) ;Windows 10 Build 17763 Return _WinAPI_SetPreferredAppMode($bAllow ? 1 : 0) ; 1 = AllowDark, 0 = Default EndFunc ;==>_WinAPI_AllowDarkModeForApp Func _WinAPI_SetPreferredAppMode($iPreferredAppMode) ;Windows 10 Build 18362+ Local $aResult = DllCall("UxTheme.dll", "long", 135, "long", $iPreferredAppMode) If @error Then Return SetError(1, 0, False) Return $aResult[0] EndFunc ;==>_WinAPI_SetPreferredAppMode #EndRegion DarkMode API #Region WinAPI DPI ;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-adjustwindowrectexfordpi Func _WinAPI_AdjustWindowRectExForDpi($dpi, $dwStyle, $dwExStyle, $bMenu = False) Local $tRECT = DllStructCreate($tagRECT) Local $aResult = DllCall("user32.dll", "bool", "AdjustWindowRectExForDpi", "struct*", $tRECT, "dword", $dwStyle, "bool", $bMenu, "dword", $dwExStyle, "int", $dpi) ;requires Win10 v1607+ / no server support If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) If Not $aResult[0] Then Return SetError(2, @extended, 0) Return $tRECT EndFunc ;==>_WinAPI_AdjustWindowRectExForDpi ;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-systemparametersinfofordpi Func _WinAPI_SystemParametersInfoForDpi($uiAction, $uiParam, $pvParam, $fWinIni, $dpi) Local $aResult = DllCall("user32.dll", "bool", "SystemParametersInfoForDpi", "uint", $uiAction, "uint", $uiParam, "struct*", $pvParam, "uint", $fWinIni, "uint", $dpi) ;requires Win10 v1607+ / no server support If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) If Not $aResult[0] Then Return SetError(2, @extended, 0) Return $aResult[0] EndFunc ;==>_WinAPI_SystemParametersInfoForDpi ;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-inheritwindowmonitor Func _WinAPI_InheritWindowMonitor($hWnd, $hWndInherit) Local $aResult = DllCall("user32.dll", "bool", "InheritWindowMonitor", "hwnd", $hWnd, "hwnd", $hWndInherit) ;requires Win10 v1803+ / Windows Server 2016+ If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) If Not $aResult[0] Then Return SetError(2, @extended, 0) Return $aResult[0] EndFunc ;==>_WinAPI_InheritWindowMonitor ;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-isvaliddpiawarenesscontext Func _WinAPI_IsValidDpiAwarenessContext($DPI_AWARENESS_CONTEXT_value) Local $aResult = DllCall("user32.dll", "bool", "IsValidDpiAwarenessContext", @AutoItX64 ? "int64" : "int", $DPI_AWARENESS_CONTEXT_value) ;requires Win10 v1607+ / no server support If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) If Not $aResult[0] Then Return SetError(2, @extended, 0) Return $aResult[0] EndFunc ;==>_WinAPI_IsValidDpiAwarenessContext ;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-logicaltophysicalpointforpermonitordpi Func _WinAPI_LogicalToPhysicalPointForPerMonitorDPI($hWnd, $iX, $iY) Local $tPOINT = DllStructCreate($tagPOINT) $tPOINT.x = $iX $tPOINT.y = $iY Local $aResult = DllCall("user32.dll", "bool", "LogicalToPhysicalPointForPerMonitorDPI", "hwnd", $hWnd, "struct*", $tPOINT) ;requires Win 8.1+ / no server support If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) If Not $aResult[0] Then Return SetError(2, @extended, 0) Return $tPOINT EndFunc ;==>_WinAPI_LogicalToPhysicalPointForPerMonitorDPI ;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-physicaltologicalpointforpermonitordpi Func _WinAPI_PhysicalToLogicalPointForPerMonitorDPI($hWnd, $iX, $iY) Local $tPOINT = DllStructCreate($tagPOINT) $tPOINT.X = $iX $tPOINT.Y = $iY Local $aResult = DllCall("user32.dll", "bool", "PhysicalToLogicalPointForPerMonitorDPI", "hwnd", $hWnd, "struct*", $tPOINT) ;requires Win 8.1+ / no server support If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) If Not $aResult[0] Then Return SetError(2, @extended, 0) Return $tPOINT EndFunc ;==>_WinAPI_PhysicalToLogicalPointForPerMonitorDPI Func _GDIPlus_GetDPI($hGUI = 0) Local $hGfx = _GDIPlus_GraphicsCreateFromHWND($hGUI) If @error Then Return SetError(1, @extended, 0) Local $aResult = DllCall($__g_hGDIPDll, "int", "GdipGetDpiX", "handle", $hGfx, "float*", 0) If @error Then Return SetError(2, @extended, 0) _GDIPlus_GraphicsDispose($hGfx) Return $aResult[2] EndFunc ;==>_GDIPlus_GetDPI Func _WinAPI_GetDPI($hWnd = 0) $hWnd = (Not $hWnd ? _WinAPI_GetDesktopWindow() : $hWnd) Local Const $hDC = _WinAPI_GetDC($hWnd) If @error Then Return SetError(1, 0, 0) Local Const $iDPI = _WinAPI_GetDeviceCaps($hDC, $LOGPIXELSX) If @error Or Not $iDPI Then _WinAPI_ReleaseDC($hWnd, $hDC) Return SetError(2, 0, 0) EndIf _WinAPI_ReleaseDC($hWnd, $hDC) Return $iDPI EndFunc ;==>_WinAPI_GetDPI ;https://learn.microsoft.com/en-us/windows/win32/api/shellscalingapi/nf-shellscalingapi-getdpiformonitor Func _WinAPI_GetDpiForMonitor($hMonitor = 0, $dpiType = $MDT_DEFAULT) If $hMonitor = 0 Then Local $aMonitors = _WinAPI_EnumDisplayMonitors() If @error Or Not IsArray($aMonitors) Then Return SetError(1, 0, 0) Local $i For $i = 1 To $aMonitors[0][0] If _WinAPI_GetMonitorInfo($aMonitors[$i][0])[2] = 1 Then $hMonitor = $aMonitors[$i][0] ExitLoop EndIf Next EndIf Local $tx = DllStructCreate("uint dpiX"), $tY = DllStructCreate("uint dpiY") Local $aResult = DllCall("Shcore.dll", "long", "GetDpiForMonitor", "handle", $hMonitor, "long", $dpiType, "struct*", $tx, "struct*", $tY) If @error Or Not IsArray($aResult) Then Return SetError(2, 0, 0) If $aResult[0] <> 0 Then Return SetError(3, $aResult[0], 0) Return $tx.dpiX EndFunc ;==>_WinAPI_GetDpiForMonitor ;https://learn.microsoft.com/en-us/windows/win32/api/shellscalingapi/nf-shellscalingapi-getdpiformonitor Func _WinAPI_GetDpiForMonitor2($hMonitor, $dpiType = $MDT_EFFECTIVE_DPI) Local $tDpiX = DllStructCreate("uint dpiX") Local $tDpiY = DllStructCreate("uint dpiY") Local $aResult = DllCall("Shcore.dll", "long", "GetDpiForMonitor", _ ;Win8.1+ "handle", $hMonitor, _ "int", $dpiType, _ "struct*", $tDpiX, _ "struct*", $tDpiY) If @error Or Not IsArray($aResult) Then Return SetError(1, @error, 0) If $aResult[0] <> 0 Then Return SetError(2, $aResult[0], 0) ; HRESULT check Local $aReturn[2] = [DllStructGetData($tDpiX, "dpiX"), DllStructGetData($tDpiY, "dpiY")] Return $aReturn ; Returns both X and Y DPI EndFunc ;==>_WinAPI_GetDpiForMonitor2 ;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdpiforwindow Func _WinAPI_GetDpiForWindow($hWnd) Local $aResult = DllCall("user32.dll", "uint", "GetDpiForWindow", "hwnd", $hWnd) ;requires Win10 v1607+ / no server support If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) If Not $aResult[0] Then Return SetError(2, @extended, 0) Return $aResult[0] EndFunc ;==>_WinAPI_GetDpiForWindow ;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdpiforsystem Func _WinAPI_GetDpiForSystem() Local $aResult = DllCall("user32.dll", "uint", "GetDpiForSystem") ;requires Win10 v1607+ / no server support If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) If Not $aResult[0] Then Return SetError(2, @extended, 0) Return $aResult[0] EndFunc ;==>_WinAPI_GetDpiForSystem ;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getthreaddpiawarenesscontext Func _WinAPI_GetThreadDpiAwarenessContext() Local $aResult = DllCall("user32.dll", (@AutoItX64 ? "int64" : "int"), "GetThreadDpiAwarenessContext") ;requires Win10 v1607+ / no server support If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) If Not $aResult[0] Then Return SetError(2, @extended, 0) Return $aResult[0] EndFunc ;==>_WinAPI_GetThreadDpiAwarenessContext ;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdpifromdpiawarenesscontext Func _WinAPI_GetDpiFromDpiAwarenessContext($DPI_AWARENESS_CONTEXT_value) Local $aResult = DllCall("user32.dll", "uint", "GetDpiFromDpiAwarenessContext", @AutoItX64 ? "int64" : "int", $DPI_AWARENESS_CONTEXT_value) ;requires Win10 v1803+ / Windows Server 2016+ If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) If Not $aResult[0] Then Return SetError(2, @extended, 0) Return $aResult[0] EndFunc ;==>_WinAPI_GetDpiFromDpiAwarenessContext ;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getawarenessfromdpiawarenesscontext Func _WinAPI_GetAwarenessFromDpiAwarenessContext($DPI_AWARENESS_CONTEXT_value) Local $aResult = DllCall("user32.dll", "uint", "GetAwarenessFromDpiAwarenessContext", @AutoItX64 ? "int64" : "int", $DPI_AWARENESS_CONTEXT_value) ;requires Win10 v1607+ / no server support If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) If Not $aResult[0] Then Return SetError(2, @extended, 0) Return $aResult[0] EndFunc ;==>_WinAPI_GetAwarenessFromDpiAwarenessContext ;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdpiawarenesscontextforprocess Func _WinAPI_GetDpiAwarenessContextForProcess($hProcess) Local $aResult = DllCall("user32.dll", (@AutoItX64 ? "int64" : "int"), "GetDpiAwarenessContextForProcess", "handle", $hProcess) ;requires Win10 v1803+ / Windows Server 2016+ If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) If Not $aResult[0] Then Return SetError(2, @extended, 0) Return $aResult[0] EndFunc ;==>_WinAPI_GetDpiAwarenessContextForProcess ;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getsystemdpiforprocess Func _WinAPI_GetSystemDpiForProcess($hProcess) Local $aResult = DllCall("user32.dll", "uint", "GetSystemDpiForProcess", "handle", $hProcess) ;requires Win10 v1803+ / Windows Server 2016+ If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) If Not $aResult[0] Then Return SetError(2, @extended, 0) Return $aResult[0] EndFunc ;==>_WinAPI_GetSystemDpiForProcess ;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowdpiawarenesscontext Func _WinAPI_GetWindowDpiAwarenessContext($hWnd) Local $aResult = DllCall("user32.dll", (@AutoItX64 ? "int64" : "int"), "GetWindowDpiAwarenessContext", "hwnd", $hWnd) ;requires Win10 v1607+ / no server support If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) If Not $aResult[0] Then Return SetError(2, @extended, 0) Return $aResult[0] EndFunc ;==>_WinAPI_GetWindowDpiAwarenessContext ;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setprocessdpiawarenesscontext Func _WinAPI_SetProcessDpiAwarenessContext($DPI_AWARENESS_CONTEXT_value) Local $aResult = DllCall("user32.dll", "bool", "SetProcessDpiAwarenessContext", @AutoItX64 ? "int64" : "int", $DPI_AWARENESS_CONTEXT_value) ;requires Win10 v1703+ / Windows Server 2016+ If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) If Not $aResult[0] Then Return SetError(2, @extended, 0) Return $aResult[0] EndFunc ;==>_WinAPI_SetProcessDpiAwarenessContext ;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setthreaddpiawarenesscontext Func _WinAPI_SetThreadDpiAwarenessContext($DPI_AWARENESS_CONTEXT_value) Local $aResult = DllCall("user32.dll", (@AutoItX64 ? "int64" : "int"), "SetThreadDpiAwarenessContext", @AutoItX64 ? "int64" : "int", $DPI_AWARENESS_CONTEXT_value) ;requires Win10 v1703+ / Windows Server 2016+ If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) If Not $aResult[0] Then Return SetError(2, @extended, 0) Return $aResult[0] EndFunc ;==>_WinAPI_SetThreadDpiAwarenessContext ;https://learn.microsoft.com/en-us/windows/win32/api/shellscalingapi/nf-shellscalingapi-setprocessdpiawareness Func _WinAPI_SetProcessDpiAwareness($PROCESS_DPI_AWARENESS = $DPI_AWARENESS_PER_MONITOR_AWARE) Local $aResult = DllCall("Shcore.dll", "long", "SetProcessDpiAwareness", "int", $PROCESS_DPI_AWARENESS) ;requires Win 8.1+ / Server 2012 R2+ If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) If $aResult[0] Then Return SetError(2, $aResult[0], 0) Return 1 EndFunc ;==>_WinAPI_SetProcessDpiAwareness Func _WinAPI_SetDPIAwareness($iAwarenessLevel = $DPI_AWARENESS_PER_MONITOR_AWARE, $iMode = 1) If @OSBuild < 6000 Then Return SetError(100, 0, 0) ; $iAwarenessLevel unified for all Windows versions: ; 0 = UNAWARE ; 1 = SYSTEM_AWARE ; 2 = PER_MONITOR_AWARE (default) ; 3 = PER_MONITOR_AWARE_V2 (Win10 1703+ only) ; 4 = UNAWARE_GDISCALED (Win10 1803+ only) $iAwarenessLevel = ($iAwarenessLevel < 0) ? (-$iAwarenessLevel - 1) : ($iAwarenessLevel > 4) ? 4 : $iAwarenessLevel Switch @OSBuild Case 6000 To 9199 ; Vista - Windows 8 Local $aResult = DllCall("user32.dll", "bool", "SetProcessDPIAware") If Not IsArray($aResult) Or Not $aResult[0] Then Return SetError(1, 0, 0) Case 9200 To 13999 ; Windows 8.1 - Windows 10 Build 14393 ; Limit to 0-2 for this version Local $iLegacyLevel = ($iAwarenessLevel > 2) ? 2 : $iAwarenessLevel If _WinAPI_SetProcessDpiAwareness($iLegacyLevel) = 0 Then Return SetError(2, @error, 0) Case Else ; Windows 10 Build 14393+ ; Convert to DPI_AWARENESS_CONTEXT values Local $aContextMap[5] = [$DPI_AWARENESS_CONTEXT_UNAWARE, _ ; -1 $DPI_AWARENESS_CONTEXT_SYSTEM_AWARE, _ ; -2 $DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE, _ ; -3 $DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2, _ ; -4 $DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED _ ; -5 ] ; Limit V2 and GDISCALED to compatible Windows versions If $iAwarenessLevel = 3 And @OSBuild < 15063 Then $iAwarenessLevel = 2 ; V2 requires 1703+ If $iAwarenessLevel = 4 And @OSBuild < 17134 Then $iAwarenessLevel = 2 ; GDISCALED requires 1803+ Local $iDpiContext = $aContextMap[$iAwarenessLevel] $iMode = ($iMode < 1) ? 1 : ($iMode > 2) ? 2 : $iMode Local $iResult Switch $iMode Case 1 ; Process-wide setting $iResult = _WinAPI_SetProcessDpiAwarenessContext($iDpiContext) If Not $iResult Or @error Then Return SetError(3, @error, 0) Case 2 ; Thread-specific setting $iResult = _WinAPI_SetThreadDpiAwarenessContext($iDpiContext) If Not $iResult Or @error Then Return SetError(4, @error, 0) EndSwitch EndSwitch ; Retrieve DPI value Local $iDPI If @OSBuild < 9200 Then $iDPI = _WinAPI_GetDPI() If @error Or Not $iDPI Then Return SetError(5, 0, 0) Else $iDPI = _WinAPI_GetDpiForMonitor() If @error Or Not $iDPI Then Return SetError(6, 0, 0) EndIf Return $iDPI EndFunc ;==>_WinAPI_SetDPIAwareness ;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-aredpiawarenesscontextsequal Func _WinAPI_AreDpiAwarenessContextsEqual($dpiContextA, $dpiContextB) Local $aResult = DllCall("user32.dll", "bool", "AreDpiAwarenessContextsEqual", _ ;Win10 1607+ @AutoItX64 ? "int64" : "int", $dpiContextA, _ @AutoItX64 ? "int64" : "int", $dpiContextB) If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, False) Return $aResult[0] EndFunc ;==>_WinAPI_AreDpiAwarenessContextsEqual ;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-enablenonclientdpiscaling Func _WinAPI_EnableNonClientDpiScaling($hWnd) Local $aResult = DllCall("user32.dll", "bool", "EnableNonClientDpiScaling", "hwnd", $hWnd) ;Win10 1607+ If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) If Not $aResult[0] Then Return SetError(2, @extended, 0) Return $aResult[0] EndFunc ;==>_WinAPI_EnableNonClientDpiScaling ;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getsystemmetricsfordpi Func _WinAPI_GetSystemMetricsForDpi($nIndex, $dpi) Local $aResult = DllCall("user32.dll", "int", "GetSystemMetricsForDpi", "int", $nIndex, "uint", $dpi) ;Win10 1607+ If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) Return $aResult[0] EndFunc ;==>_WinAPI_GetSystemMetricsForDpi ;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setdialogdpichangebehavior Func _WinAPI_GetDialogDpiChangeBehavior($hWnd) Local $aResult = DllCall("user32.dll", "int", "GetDialogDpiChangeBehavior", "hwnd", $hWnd) ;Win10 1703+ If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) Return $aResult[0] EndFunc ;==>_WinAPI_GetDialogDpiChangeBehavior Func _WinAPI_SetDialogDpiChangeBehavior($hWnd, $mask, $values) Local $aResult = DllCall("user32.dll", "bool", "SetDialogDpiChangeBehavior", "hwnd", $hWnd, "int", $mask, "int", $values) ;Win10 1703+ If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) If Not $aResult[0] Then Return SetError(2, @extended, 0) Return $aResult[0] EndFunc ;==>_WinAPI_SetDialogDpiChangeBehavior ;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setdialogcontroldpichangebehavior Func _WinAPI_GetDialogControlDpiChangeBehavior($hWnd) Local $aResult = DllCall("user32.dll", "int", "GetDialogControlDpiChangeBehavior", "hwnd", $hWnd) ;Win10 1703+ If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) Return $aResult[0] EndFunc ;==>_WinAPI_GetDialogControlDpiChangeBehavior Func _WinAPI_SetDialogControlDpiChangeBehavior($hWnd, $mask, $values) Local $aResult = DllCall("user32.dll", "bool", "SetDialogControlDpiChangeBehavior", "hwnd", $hWnd, "int", $mask, "int", $values) ;Win10 1703+ If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) If Not $aResult[0] Then Return SetError(2, @extended, 0) Return $aResult[0] EndFunc ;==>_WinAPI_SetDialogControlDpiChangeBehavior ;https://learn.microsoft.com/en-us/windows/win32/api/uxtheme/nf-uxtheme-openthemedatafordpi Func _WinAPI_OpenThemeDataForDpi($hWnd, $pszClassList, $dpi) Local $aResult = DllCall("uxtheme.dll", "handle", "OpenThemeDataForDpi", "hwnd", $hWnd, "wstr", $pszClassList, "uint", $dpi) ;Win10 1703+ If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) Return $aResult[0] EndFunc ;==>_WinAPI_OpenThemeDataForDpi #EndRegion WinAPI DPI Edited 2 hours ago by UEZ Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ
argumentum Posted 18 hours ago Posted 18 hours ago (edited) <removed> Edited 17 hours ago by argumentum Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting.
UEZ Posted 18 hours ago Author Posted 18 hours ago Hmm. when I start it at 175% or from 100% -> 175% . I had also the problems with the measurement of the menus but for me it works as you can see in the screenshot. Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ
WildByDesign Posted 18 hours ago Posted 18 hours ago Here is what it looks like at 125% scaling which I use daily: Spoiler
WildByDesign Posted 18 hours ago Posted 18 hours ago Regarding the white line, I have noticed this measurement issue before with your Overpaintwhiteline() function. For example, it shows differently whether the GUICreate allows resizable or not and so on. It does not seem to adapt to some differences and it seems DPI as well. The function that @ahmet helped me with a while back uses MapWindowPoints and I have never seen the white line on any DPI or differences in GUICreate options. I cannot pretend that I understand how it works, because I don't. But I will share it here and you can play around with it. Func _drawUAHMenuNCBottomLine($hWnd) Local $rcClient = __WinAPI_GetClientRect($hWnd) DllCall($hUser32Dll, "int", "MapWindowPoints", _ "hwnd", $hWnd, _ ; hWndFrom "hwnd", 0, _ ; hWndTo "ptr", DllStructGetPtr($rcClient), _ "uint", 2) ;number of points - 2 for RECT structure If @error Then ;MsgBox($MB_ICONERROR, "Error", @error) Exit EndIf Local $rcWindow = __WinAPI_GetWindowRect($hWnd) __WinAPI_OffsetRect($rcClient, -$rcWindow.left, -$rcWindow.top) Local $rcAnnoyingLine = DllStructCreate($tagRECT) $rcAnnoyingLine.left = $rcClient.left $rcAnnoyingLine.top = $rcClient.top $rcAnnoyingLine.right = $rcClient.right $rcAnnoyingLine.bottom = $rcClient.bottom $rcAnnoyingLine.bottom = $rcAnnoyingLine.top $rcAnnoyingLine.top = $rcAnnoyingLine.top - 1 Local $hRgn = __WinAPI_CreateRectRgn(0,0,8000,8000) Local $hDC = __WinAPI_GetDCEx($hWnd,$hRgn, BitOR($DCX_WINDOW,$DCX_INTERSECTRGN)) Local $hFullBrush = __WinAPI_CreateSolidBrush($COLOR_MENU_BG) __WinAPI_FillRect($hDC, $rcAnnoyingLine, $hFullBrush) __WinAPI_ReleaseDC($hWnd, $hDC) __WinAPI_DeleteObject($hFullBrush) EndFunc ;==>_drawUAHMenuNCBottomLine UEZ 1
WildByDesign Posted 18 hours ago Posted 18 hours ago Here is the math that I used for the DPI measurements of the menubar items. I don't know if it will be helpful or not. But I will share here just in case. ; get window DPI for measurement adjustments $iDPIpct = Round(__WinAPI_GetDpiForWindow($hGUI) / 96, 2) * 100 If @error Then $iDPIpct = 100 Func _WM_MEASUREITEM($hWnd, $iMsg, $wParam, $lParam) ;... ; Set dimensions with padding (with high DPI) $t.itemWidth = _CalcMenuItemWidth($iDPIpct, $iTextWidth) $t.itemHeight = $iTextHeight + 1 ;... EndFunc ;==>_WM_MEASUREITEM Func _CalcMenuItemWidth($iDPIpct, $iTextWidth) If $iDPIpct < 100 Or $iDPIpct > 400 Then Return $iTextWidth - 5 EndIf Local Const $iSteps = Int(($iDPIpct - 100) / 25) Return $iTextWidth - (4 * $iSteps) EndFunc ;==>_CalcMenuItemWidth
UEZ Posted 7 hours ago Author Posted 7 hours ago 10 hours ago, WildByDesign said: Regarding the white line, I have noticed this measurement issue before with your Overpaintwhiteline() function. For example, it shows differently whether the GUICreate allows resizable or not and so on. It does not seem to adapt to some differences and it seems DPI as well. The function that @ahmet helped me with a while back uses MapWindowPoints and I have never seen the white line on any DPI or differences in GUICreate options. I cannot pretend that I understand how it works, because I don't. But I will share it here and you can play around with it. Func _drawUAHMenuNCBottomLine($hWnd) Local $rcClient = __WinAPI_GetClientRect($hWnd) DllCall($hUser32Dll, "int", "MapWindowPoints", _ "hwnd", $hWnd, _ ; hWndFrom "hwnd", 0, _ ; hWndTo "ptr", DllStructGetPtr($rcClient), _ "uint", 2) ;number of points - 2 for RECT structure If @error Then ;MsgBox($MB_ICONERROR, "Error", @error) Exit EndIf Local $rcWindow = __WinAPI_GetWindowRect($hWnd) __WinAPI_OffsetRect($rcClient, -$rcWindow.left, -$rcWindow.top) Local $rcAnnoyingLine = DllStructCreate($tagRECT) $rcAnnoyingLine.left = $rcClient.left $rcAnnoyingLine.top = $rcClient.top $rcAnnoyingLine.right = $rcClient.right $rcAnnoyingLine.bottom = $rcClient.bottom $rcAnnoyingLine.bottom = $rcAnnoyingLine.top $rcAnnoyingLine.top = $rcAnnoyingLine.top - 1 Local $hRgn = __WinAPI_CreateRectRgn(0,0,8000,8000) Local $hDC = __WinAPI_GetDCEx($hWnd,$hRgn, BitOR($DCX_WINDOW,$DCX_INTERSECTRGN)) Local $hFullBrush = __WinAPI_CreateSolidBrush($COLOR_MENU_BG) __WinAPI_FillRect($hDC, $rcAnnoyingLine, $hFullBrush) __WinAPI_ReleaseDC($hWnd, $hDC) __WinAPI_DeleteObject($hFullBrush) EndFunc ;==>_drawUAHMenuNCBottomLine Back in my office with 3 monitors: checked the _OverpaintWhiteLine() and yes, didn't work. Changed it to the code above and it seems to work now - please test! WildByDesign 1 Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ
UEZ Posted 7 hours ago Author Posted 7 hours ago 10 hours ago, WildByDesign said: Here is the math that I used for the DPI measurements of the menubar items. I don't know if it will be helpful or not. But I will share here just in case. ; get window DPI for measurement adjustments $iDPIpct = Round(__WinAPI_GetDpiForWindow($hGUI) / 96, 2) * 100 If @error Then $iDPIpct = 100 Func _WM_MEASUREITEM($hWnd, $iMsg, $wParam, $lParam) ;... ; Set dimensions with padding (with high DPI) $t.itemWidth = _CalcMenuItemWidth($iDPIpct, $iTextWidth) $t.itemHeight = $iTextHeight + 1 ;... EndFunc ;==>_WM_MEASUREITEM Func _CalcMenuItemWidth($iDPIpct, $iTextWidth) If $iDPIpct < 100 Or $iDPIpct > 400 Then Return $iTextWidth - 5 EndIf Local Const $iSteps = Int(($iDPIpct - 100) / 25) Return $iTextWidth - (4 * $iSteps) EndFunc ;==>_CalcMenuItemWidth I cannot see in the screenshots any misplacement except the screenshot from @argumentum Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ
WildByDesign Posted 6 hours ago Posted 6 hours ago 1 hour ago, UEZ said: Back in my office with 3 monitors: checked the _OverpaintWhiteLine() and yes, didn't work. Changed it to the code above and it seems to work now - please test! The white line is perfect now. I also tested it by adding $WS_OVERLAPPEDWINDOW to the GUICreate and resized, maximized, etc. The white line is overpainted perfectly in all scenarios that I could test. 1 hour ago, UEZ said: I cannot see in the screenshots any misplacement except the screenshot Here are the problems that I see at 100%, 125% and 150: Progress label is cutting off the progress bar Sample Avi label is cutting off part of tab control Sample Tab with TabItems label is cutting off side of tab control and only shows 5-10% of the time I had to start the GUI many times until I could get the screenshot since the label disappears most of the time Too much space on right side of each menubar item when you hover over it The Sample Tab with TabItems is an easy fix because the text is simply too long. If that is shortened to something like "Sample Tab One", it fixes that problem. Would making the label backgrounds transparent fix the other label cutoffs? Screenshot with the updated test sample: Spoiler
UEZ Posted 5 hours ago Author Posted 5 hours ago (edited) Hmmm, I have no problems with the label sizes - thus I cannot reproduce it. Another white line seems to occur at 200% above the menus At 200% Red line is just for testing purposes. Edited 5 hours ago by UEZ Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now