11#NoTrayIcon
2- #AutoIt3Wrapper_Au3Check_Parameters= - d - w 1 - w 2 - w 3 - w 4 - w 5 - w 6 - w 7
32#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
43#AutoIt3Wrapper_Icon=
54#AutoIt3Wrapper_Outfile= mdMsgBox.exe
98#AutoIt3Wrapper_AU3Check_Parameters= - d - w 1 - w 2 - w 3 - w 4 - w 5 - w 6 - w 7
109#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
1110
11+ ; ~ #AutoIt3Wrapper_UseX64=y
12+
1213#include < GUIConstantsEx.au3>
1314#include < WindowsConstants.au3>
1415#include " ..\NetWebView2Lib.au3"
1516
1617; ----------------------------------------------------------------------------------------
1718; Title...........: 019-mdMsgBox.au3
1819; Description.....: Markdown Modern MsgBox (WebView2)
19- ; AutoIt Version..: 3.3.18.0 Author: ioa747 Script Version: 0.1
20+ ; AutoIt Version..: 3.3.18.0 Author: ioa747 Script Version: 0.3
2021; Note............: Testet in Windows 11 Pro 25H2 Date:20/03/2026
2122; ## The dependencies are in the folder @ScriptDir & "\JS_Lib"
2223; 🏆 Thanks to https://github.com/markedjs/marked/
2324; 🏆 Thanks to https://fontawesome.com/search?ic=free-collection
2425; ----------------------------------------------------------------------------------------
2526
26- ; ~ DllCall("User32.dll", "bool", "SetProcessDpiAwarenessContext", "int_ptr", -2)
27+ $_g_bNetWebView2_DebugInfo = False ; NetWebView2 DebugInfo
2728
28- $_g_bNetWebView2_DebugInfo = False
29+ DllCall ( " User32.dll " , " bool " , " SetProcessDpiAwarenessContext " , " int_ptr " , - 4 ) ; (-4 = Per Monitor V2)
2930
3031Global $g_hGUI , $g_hBkColor , $g_hTxtColor , $g_hFootColor , $g_iMaxWidth , $g_iMaxHeight , $g_iLeft , $g_iTop , $g_sTitle , $g_sText , _
31- $g_sButtons , $g_sBtnDefColor , $g_sBtnColor , $g_sBtnResult , $g_aBtn , $g_iTimer , $g_iTopMost , $g_hParent
32+ $g_sButtons , $g_sBtnDefColor , $g_sBtnColor , $g_sBtnResult , $g_aBtn , $g_iTimer , $g_iTopMost , $g_hParent , $g_sFile
3233
3334$g_hGUI = 0
3435$g_hBkColor = Hex (0x2B2B2B , 6 ) ; Dark slate gray
@@ -48,10 +49,26 @@ $g_aBtn = StringSplit($g_sButtons, "|", 1)
4849$g_iTimer = 0 ; Default: No timer
4950$g_iTopMost = 0
5051$g_hParent = 0
52+ $g_sFile = " "
53+
54+ ; === Testing ===
55+ ; ~ $g_sTitle = "Markdown MsgBox"
56+ ; ~ $g_sText = "" & _
57+ ; ~ "# 🎯 Make your Choice" & @CRLF & _
58+ ; ~ "This is a **Modern UI** message box." & @CRLF & _
59+ ; ~ "* 1️⃣ **Engine:** WebView2" & @CRLF & _
60+ ; ~ "* 2️⃣ **Parser:** Marked.js" & @CRLF & _
61+ ; ~ "* 3️⃣ **Logic:** AutoIt Bridge"
62+ ; ~ $g_sButtons = "1|2|3|~CANCEL"
63+ ; ~ $g_aBtn = StringSplit($g_sButtons, "|", 1)
64+
5165
5266_CmdLine_Parsing()
5367
68+ If FileExists ($g_sFile ) Then $g_sText = FileRead ($g_sFile )
69+
5470; === Execution ===
71+ Global $g_fDpiScale = _GetNearestWindowsDpi()
5572Global $oWebV2M
5673Global $sResult = _MarkdownMsgBox()
5774ConsoleWrite ($sResult & @CRLF )
@@ -101,17 +118,24 @@ Func _CmdLine_Parsing()
101118 $g_iTopMost = (Int (StringReplace ($sCmd , " /TopMost:" , " " )) ? $WS_EX_TOPMOST : 0 )
102119 Case StringInStr ($sCmd , " /Parent:" )
103120 $g_hParent = HWnd (StringReplace ($sCmd , " /Parent:" , " " ))
121+ Case StringInStr ($sCmd , " /File:" )
122+ $g_sFile = StringReplace ($sCmd , " /File:" , " " )
123+ ; We remove any extra quotes if the user entered /File:"path"
124+ $g_sFile = StringReplace ($g_sFile , ' "' , " " )
104125 EndSelect
105126 Next
106127 EndIf
107128EndFunc ; ==>_CmdLine_Parsing
108129; ---------------------------------------------------------------------------------------
109130Func _MarkdownMsgBox()
131+
110132 ; Create the GUI Window (Hidden)
111133 $g_hGUI = GUICreate ($g_sTitle , $g_iMaxWidth , $g_iMaxHeight , - 1 , - 1 , BitOR ($WS_CAPTION , $WS_POPUP , $WS_SYSMENU , $WS_CLIPCHILDREN ), $g_iTopMost , $g_hParent )
112134 GUISetIcon (@ScriptFullPath )
113135 GUISetBkColor ($g_hBkColor )
114136
137+ GUIRegisterMsg (0x02E0 , WM_DPICHANGED) ; 0x02E0 = WM_DPICHANGED
138+
115139 $oWebV2M = _NetWebView2_CreateManager(" " , " Web_Events_" , " --allow-file-access-from-files --disable-web-security" ) ; 👈
116140 _NetWebView2_GetBridge($oWebV2M , " JS_Events_" )
117141
@@ -162,27 +186,41 @@ Volatile Func JS_Events_OnMessageReceived($oWebV2M, $hGUI, $sMessage)
162186 #forceref $oWebV2M
163187
164188 If StringLeft ($sMessage , 7 ) = " RESIZE|" Then
165- ; Cancel _EmergencyShow timer immediately since JS is responding
166189 AdlibUnRegister (" _EmergencyShow" )
167190
168191 Local $aData = StringSplit ($sMessage , " |" )
169192 If $aData [0 ] < 3 Then Return
170193
194+ ; Getting the Scale Factor
195+ $g_fDpiScale = _GetNearestWindowsDpi()
196+ ConsoleWrite (" $g_fDpiScale=" & $g_fDpiScale & @CRLF )
197+
171198 Local $iW = Int ($aData [2 ]), $iH = Int ($aData [3 ])
172199
173- ; Constraints
174- If $iW > $g_iMaxWidth Then $iW = $g_iMaxWidth
175- If $iW < 300 Then $iW = 300
176- If $iH > $g_iMaxHeight Then $iH = $g_iMaxHeight
177- If $iH < 120 Then $iH = 120
200+ ; Dynamic Constraints based on Scaling
201+ Local $iMinW = 300 * $g_fDpiScale
202+ Local $iMaxW = $g_iMaxWidth * $g_fDpiScale
203+ Local $iMaxH = $g_iMaxHeight * $g_fDpiScale
204+
205+ If $iW > $iMaxW Then $iW = $iMaxW
206+ If $iW < $iMinW Then $iW = $iMinW
207+ If $iH > $iMaxH Then $iH = $iMaxH
208+
178209
179- ; Final dimensions with window chrome offsets
210+ ; Add margins (Titlebar etc.)
180211 Local $iFinalW = $iW + 6
181- Local $iFinalH = $iH + 30
212+ Local $iFinalH = $iH + 29
213+
214+ ; Download Work Area (Screen without Taskbar)
215+ Local $tRect = DllStructCreate (" int Left;int Top;int Right;int Bottom" )
216+ DllCall (" user32.dll" , " bool" , " SystemParametersInfo" , " uint" , 48 , " uint" , 0 , " ptr" , DllStructGetPtr ($tRect ), " uint" , 0 ) ; 48 = SPI_GETWORKAREA
217+
218+ Local $iWA_W = DllStructGetData ($tRect , " Right" ) - DllStructGetData ($tRect , " Left" )
219+ Local $iWA_H = DllStructGetData ($tRect , " Bottom" ) - DllStructGetData ($tRect , " Top" )
182220
183- ; Use Global Left/Top if set, otherwise center
184- Local $iTargetLeft = ($g_iLeft = - 1 ) ? ( @DesktopWidth - $iFinalW ) / 2 : $g_iLeft
185- Local $iTargetTop = ($g_iTop = - 1 ) ? ( @DesktopHeight - $iFinalH ) / 2 : $g_iTop
221+ ; Position calculation (Center in Work Area)
222+ Local $iTargetLeft = ($g_iLeft = - 1 ) ? DllStructGetData ( $tRect , " Left " ) + ( $iWA_W - $iFinalW ) / 2 : $g_iLeft
223+ Local $iTargetTop = ($g_iTop = - 1 ) ? DllStructGetData ( $tRect , " Top " ) + ( $iWA_H - $iFinalH ) / 2 : $g_iTop
186224
187225 ; Resize and Show
188226 WinMove ($hGUI , " " , $iTargetLeft , $iTargetTop , $iFinalW , $iFinalH )
@@ -294,47 +332,132 @@ Func _RenderMarkdown()
294332EndFunc ; ==>_RenderMarkdown
295333; ---------------------------------------------------------------------------------------
296334Func _CSS()
297- Local $hBCol , $sButtons = " "
298- For $i = 1 To $g_aBtn [0 ]
299- $hBCol = (StringLeft ($g_aBtn [$i ], 1 ) = " ~" ? $g_sBtnDefColor : $g_sBtnColor )
300- $sButtons &= " .btn-" & $i & " { background: #" & $hBCol & " ; color: white; border: none; " & _
301- (StringLeft ($g_aBtn [$i ], 1 ) = " ~" ? " font-weight: bold; " : " " ) & " }"
302- Next
303-
304- Local $sStyle = " "
305- ; ΠΡΟΣΘΗΚΗ MARGIN-BOTTOM ΓΙΑ ΝΑ ΜΗΝ ΕΙΝΑΙ ΣΤΡΙΜΩΓΜΕΝΑ
306- $sStyle &= " h1, h2, h3, h4, h5, h6 { margin: 0 0 15px 0; border-bottom: 1px solid #333; padding-bottom: 5px; color: #ffffff; }" & _
307- " ul, ol { margin: 10px 0; padding-left: 25px; }" & _
308- " li { margin-bottom: 5px; padding: 0; }" & _
309- " #view p { margin-bottom: 10px; padding: 0; }" & _
310- " a { color: #4da6ff; text-decoration: none; }"
311-
312- $sStyle &= " body { font-family: 'Segoe UI', Tahoma, sans-serif; background: #" & $g_hBkColor & " ; " & _
313- " color: #" & $g_hTxtColor & " ; margin: 0; padding: 0; overflow: hidden; outline: none; }" & _
314- " #main-container { width: 100%; display: block; text-align: left; word-wrap: break-word; outline: none; }" & _
315- " #view { padding: 20px; min-height: 50px; }" ; white-space: pre-wrap;
316-
317- $sStyle &= " .footer { background: #" & $g_hFootColor & " ; padding: 12px; text-align: right; " & _
318- " border-top: 1px solid #333; width: 100%; box-sizing: border-box; }" & _
319- " .btn { padding: 8px 16px; margin-left: 6px; border-radius: 3px; cursor: pointer; font-size: 13px; " & _
320- " transition: filter 0.2s; outline: none; }" & $sButtons & _
321- " .btn:hover { filter: brightness(1.2); } .btn:focus { outline: 2px solid #ffffff; outline-offset: 2px; }"
322-
323- Return $sStyle
324- EndFunc
335+ Local $hBCol , $sButtons = " "
336+ For $i = 1 To $g_aBtn [0 ]
337+ $hBCol = (StringLeft ($g_aBtn [$i ], 1 ) = " ~" ? $g_sBtnDefColor : $g_sBtnColor )
338+ $sButtons &= " .btn-" & $i & " { background: #" & $hBCol & " ; color: white; border: none; " & _
339+ (StringLeft ($g_aBtn [$i ], 1 ) = " ~" ? " font-weight: bold; " : " " ) & " }"
340+ Next
341+
342+ Local $sStyle = " "
343+ ; Markdown elements
344+ $sStyle &= " h1, h2, h3, h4, h5, h6 { margin: 0 0 15px 0; color: #ffffff; }" & _
345+ " ul, ol { margin: 10px 0; padding-left: 25px; }" & _
346+ " li { margin-bottom: 5px; padding: 0; }" & _
347+ " #view p { margin-bottom: 10px; padding: 0; }" & _
348+ " a { color: #4da6ff; text-decoration: none; }" & _
349+ " blockquote { " & _
350+ " border-left: 5px solid #4CAF50; " & _
351+ " background-color: #252525; " & _
352+ " margin: 1.5em 0; " & _
353+ " padding: 10px 20px; " & _
354+ " color: #aaaaaa; " & _
355+ " font-style: italic; " & _
356+ " }"
357+
358+ $sStyle &= " pre, code { " & _
359+ " font-family: 'Consolas', 'Courier New', monospace; " & _
360+ " background-color: #1e1e1e; " & _
361+ " padding: 2px 4px; " & _
362+ " border-radius: 4px; " & _
363+ " color: #dcdcdc; " & _
364+ " white-space: pre-wrap; " & _
365+ " word-wrap: break-word; " & _
366+ " }" & _
367+ " pre { " & _
368+ " padding: 15px; " & _
369+ " margin: 10px 0; " & _
370+ " line-height: 1.5; " & _
371+ " display: block; " & _
372+ " overflow-x: hidden; " & _
373+ " }"
374+
375+
376+ $sStyle &= " body { " & _
377+ " font-family: 'Segoe UI', Tahoma, sans-serif; " & _
378+ " background: #" & $g_hBkColor & " ; " & _
379+ " color: #" & $g_hTxtColor & " ; " & _
380+ " margin: 0; padding: 0; outline: none; " & _
381+ " display: block; " & _
382+ " overflow-x: hidden; " & _
383+ " overflow-y: auto; " & _
384+ " word-wrap: break-word; " & _
385+ " overflow-wrap: break-word; " & _
386+ " }" & _
387+ " #main-container { " & _
388+ " width: 100%; " & _
389+ " display: block; " & _
390+ " text-align: left; " & _
391+ " outline: none; " & _
392+ " box-sizing: border-box; " & _
393+ " }" & _
394+ " #view { " & _
395+ " padding: 20px; " & _
396+ " min-height: 50px; " & _
397+ " box-sizing: border-box; " & _
398+ " }"
399+
400+
401+ $sStyle &= " .footer { background: #" & $g_hFootColor & " ; padding: 12px; text-align: right; " & _
402+ " border-top: 1px solid #333; width: 100%; box-sizing: border-box; }" & _
403+ " .btn { padding: 8px 16px; margin-left: 6px; border-radius: 3px; cursor: pointer; font-size: 13px; " & _
404+ " transition: filter 0.2s; outline: none; }" & $sButtons & _
405+ " .btn:hover { filter: brightness(1.2); } .btn:focus { outline: 2px solid #ffffff; outline-offset: 2px; }"
406+
407+ Return $sStyle
408+ EndFunc ; ==>_CSS
325409; ---------------------------------------------------------------------------------------
326410Func _EscapeForJS($sText )
327- $sText = StringReplace ($sText , " \" , " \\" )
328- $sText = StringReplace ($sText , " '" , " \'" )
411+ $sText = StringReplace ($sText , " \" , " \\" )
412+ $sText = StringReplace ($sText , " '" , " \'" )
329413
330414 $sText = StringReplace ($sText , @CRLF & @CRLF , " \\n \\n" )
331415 $sText = StringReplace ($sText , " " , " " )
332416
333- $sText = StringReplace ($sText , @CRLF , " \\n" )
334- $sText = StringReplace ($sText , @CR , " \\n" )
335- $sText = StringReplace ($sText , @LF , " \\n" )
336- Return " '" & $sText & " '"
417+ $sText = StringReplace ($sText , @CRLF , " \\n" )
418+ $sText = StringReplace ($sText , @CR , " \\n" )
419+ $sText = StringReplace ($sText , @LF , " \\n" )
420+ Return " '" & $sText & " '"
337421EndFunc ; ==>_EscapeForJS
422+ ; ---------------------------------------------------------------------------------------
423+ Func _GetNearestWindowsDpi()
424+ Local $hDC = _WinAPI_GetDC(0 )
425+ Local $iLogY = _WinAPI_GetDeviceCaps($hDC , 90 ) ; LOGPIXELSY
426+ _WinAPI_ReleaseDC(0 , $hDC )
427+
428+ Local $iCurrentPct = Round (($iLogY / 96 ) * 100 )
429+ Local $iBestMatch = 100
430+ Local $iDiff = 9999
431+
432+ ; Table with the official Windows Scaling steps
433+ Local $aDpiVals [12 ] = [100 , 125 , 150 , 175 , 200 , 225 , 250 , 300 , 350 , 400 , 450 , 500 ]
434+
435+ For $i = 0 To UBound ($aDpiVals ) - 1
436+ If Abs ($iCurrentPct - $aDpiVals [$i ]) < $iDiff Then
437+ $iDiff = Abs ($iCurrentPct - $aDpiVals [$i ])
438+ $iBestMatch = $aDpiVals [$i ]
439+ EndIf
440+ Next
441+
442+ Return $iBestMatch / 100 ; Returns clean factor: 1.0, 1.25, 1.5, 1.75...
443+ EndFunc ; ==>_GetNearestWindowsDpi
444+ ; ---------------------------------------------------------------------------------------
445+ Func WM_DPICHANGED($hWnd , $iMsg , $wParam , $lParam )
446+ #forceref $iMsg
447+
448+ ; lParam already has the correct dimensions for the new DPI
449+ Local $tRect = DllStructCreate (" int Left;int Top;int Right;int Bottom" , $lParam )
450+ WinMove ($hWnd , " " , DllStructGetData ($tRect , " Left" ), DllStructGetData ($tRect , " Top" ), _
451+ DllStructGetData ($tRect , " Right" ) - DllStructGetData ($tRect , " Left" ), _
452+ DllStructGetData ($tRect , " Bottom" ) - DllStructGetData ($tRect , " Top" ))
453+ $g_fDpiScale = BitAND ($wParam , 0xFFFF ) / 96
454+ ConsoleWrite (" -$g_fDpiScale=" & $g_fDpiScale & @CRLF )
455+
456+ Return 0
457+ EndFunc ; ==>WM_DPICHANGED
458+ ; ---------------------------------------------------------------------------------------
459+
460+
338461
339462#CS Helper function for client script
340463 ;---------------------------------------------------------------------------------------
@@ -395,5 +518,6 @@ EndFunc ;==>_EscapeForJS
395518 /Timer:0
396519 /TopMost:0
397520 /Parent:0
521+ /File:""
398522
399523#CE Helper function for client script
0 commit comments