Gui that looks like a MsgBox

Post your working scripts, libraries and tools for AHK v1.1 and older
iPhilip
Posts: 801
Joined: 02 Oct 2013, 12:21

Gui that looks like a MsgBox

28 Jul 2015, 14:33

Hi Folks,

Just for fun, I wanted to see if I could put together a Gui that looks like a simple MsgBox.
The benefit of this is that you can add Gui controls, such as links, and it will still have the look and feel of a MsgBox.

Enjoy,

iPhilip

Code: Select all

#NoEnv

Title := "Gui or MsgBox?"
Text  := "One of these windows is a Gui.`nThe other one is a MsgBox.`n`nCan you tell the difference?"

MsgBox(Title,Text)
MsgBox, , %Title%, %Text%
Return

MsgBox(Title,Text) {
   static WhiteBox,TextBox
   
   FontName     := "Segoe UI"    ; Name of font for text in Gui
   FontSize     := 9             ; Gui font size
   Gap          := 26            ; Spacing above and below text in top area of the Gui
   LeftMargin   := 12            ; Left Gui margin
   RightMargin  := 8             ; Space between right side of button and right Gui edge
   ButtonWidth  := 88            ; Width of OK button
   ButtonHeight := 26            ; Height of OK button
   ButtonOffset := 30            ; Offset between the right side of text and right edge of button
   MinGuiWidth  := 138           ; Minimum width of Gui
   SS_WHITERECT := 0x0006        ; Gui option for white rectangle (http://ahkscript.org/boards/viewtopic.php?p=20053#p20053)

   BottomGap := LeftMargin                          ; Set the distance between the bottom of the white box and the top of the OK button
   BottomHeight := ButtonHeight+2*LeftMargin+3      ; Calculate the height of the bottom section of the Gui
   Gui, Font, s%FontSize%, %FontName%               ; Set the font size and name
   Gui, +ToolWindow -MinimizeBox -MaximizeBox       ; Set the Gui so it doesn't have the icon, the minimize button, and the maximize button
   Gui, Add, Text, x0 y0 %SS_WHITERECT% vWhiteBox   ; Add a white box at the top of the window
   if Text                                                                    ; If the text field is not blank ...
   {  Gui, Add, Text, x%LeftMargin% y%Gap% BackgroundTrans vTextBox, %Text%   ; Add the text to the Gui
      GuiControlGet, Size, Pos, TextBox                                       ; Get the position of the text box
      GuiWidth := LeftMargin+SizeW+ButtonOffset+RightMargin+1                 ; Calculate the Gui width
      GuiWidth := GuiWidth < MinGuiWidth ? MinGuiWidth : GuiWidth             ; Make sure that it's not smaller than MinGuiWidth
      WhiteBoxHeight := SizeY+SizeH+Gap                                       ; Calculate the height of the white box
   }
   else                                                                       ; If the text field is blank ...
   {  GuiWidth := MinGuiWidth                                                 ; Set the width of the Gui to MinGuiWidth
      WhiteBoxHeight := 2*Gap+1                                               ; Set the height of the white box
      BottomGap++                                                             ; Increase the gap above the button by one
      BottomHeight--                                                          ; Decrease the height of the bottom section of the Gui
   }
   GuiControl, Move, WhiteBox, w%GuiWidth% h%WhiteBoxHeight%   ; Adjust the width and height of the white box
   ButtonX := GuiWidth-RightMargin-ButtonWidth                 ; Calculate the horizontal position of the button
   ButtonY := WhiteBoxHeight+BottomGap                         ; Calculate the vertical position of the button
   Gui, Add, Button, x%ButtonX% y%ButtonY% w%ButtonWidth% h%ButtonHeight% Default, OK   ; Add the OK button
   GuiHeight := WhiteBoxHeight+BottomHeight                    ; Calculate the overall height of the Gui
   Gui, Show, w%GuiWidth% h%GuiHeight%, %Title%                ; Show the Gui
   Gui, -ToolWindow                                            ; Remove the ToolWindow option so that the Gui has rounded corners and no icon
                                                               ; Trick from http://ahkscript.org/boards/viewtopic.php?p=11519#p11519
   Return

   ButtonOK:
   GuiClose:
   GuiEscape:
   Gui Destroy
   Return
}
Windows 10 Pro (64 bit) - AutoHotkey v2.0+ (Unicode 64-bit)
MJs
Posts: 454
Joined: 23 Sep 2014, 03:29

Re: Gui that looks like a MsgBox

01 Aug 2015, 00:26

nice idea, very nice
have you thought of using API functions to get the font information?
since it the user can change it
you don"t need to use (-|+ToolWindow) as you can use (-|+)SysMenu, that way no need for the visual effect
Guest10
Posts: 578
Joined: 01 Oct 2013, 02:50

Re: Gui that looks like a MsgBox

01 Aug 2015, 20:23

Nice job! Can you add No and Cancel buttons, too? :morebeard: :lol:
vasili111
Posts: 747
Joined: 21 Jan 2014, 02:04
Location: Georgia

Re: Gui that looks like a MsgBox

06 Aug 2015, 04:20

Nice! Thank you :)
DRAKON-AutoHotkey: Visual programming for AutoHotkey.
iPhilip
Posts: 801
Joined: 02 Oct 2013, 12:21

Re: Gui that looks like a MsgBox

10 Aug 2015, 14:26

Thank you all for the feedback.
MJs wrote:nice idea, very nice
Thank you! :)
MJs wrote:have you thought of using API functions to get the font information?
since it the user can change it
I followed your suggestion and developed a GetMsgBoxFontInfo function to do so. I posted it in a separate thread and below as well.
MJs wrote:you don"t need to use (-|+ToolWindow) as you can use (-|+)SysMenu, that way no need for the visual effect
Unfortunately the SysMenu option also omits the close button in the title bar so the MsgBoxGui no longer looks like a MsgBox.
Guest10 wrote:Nice job! Can you add No and Cancel buttons, too? :morebeard: :lol:
I will leave that as an "exercise for the reader". :lol:
vasili111 wrote:Nice! Thank you :)
You are welcome! :)


Here is the updated version of the MsgBoxGui function along with the GetMsgBoxFontInfo function for sake of completeness:

Code: Select all

MsgBoxGui(Title, Text, Timeout:=0) {
   global TextBox                       ; This variable can be used to update the text in the MsgBoxGui
   static WhiteBox
   
   static Gap          := 26            ; Spacing above and below text in top area of the Gui
   static LeftMargin   := 12            ; Left Gui margin
   static RightMargin  := 8             ; Space between right side of button and right Gui edge
   static ButtonWidth  := 88            ; Width of OK button
   static ButtonHeight := 26            ; Height of OK button
   static ButtonOffset := 30            ; Offset between the right side of text and right edge of button
   static MinGuiWidth  := 138           ; Minimum width of Gui
   static SS_WHITERECT := 0x0006        ; Gui option for white rectangle (http://ahkscript.org/boards/viewtopic.php?p=20053#p20053)

   BottomGap := LeftMargin                      ; Set the distance between the bottom of the white box and the top of the OK button
   BottomHeight := ButtonHeight+2*BottomGap+3   ; Calculate the height of the bottom section of the Gui
   if !GetMsgBoxFontInfo(FontName,FontSize,FontWeight,IsFontItalic)             ; Get the MsgBox font information
      Return false                                                              ; If there is a problem getting the font information, return false
   GuiOptions := "s" FontSize " w" FontWeight (IsFontItalic ? " italic" : "")   ; Define a string with the Gui options
   Gui, Font, %GuiOptions%, %FontName%                                          ; Set the font options and name
   Gui, +LastFound +ToolWindow -MinimizeBox -MaximizeBox                        ; Set the Gui so it doesn't have an icon or the minimize and maximize buttons
   Gui, Add, Text, x0 y0 %SS_WHITERECT% vWhiteBox                               ; Add a white box at the top of the window
   if Text                                                                      ; If the text field is not blank ...
   {  Gui, Add, Link, x%LeftMargin% y%Gap% BackgroundTrans vTextBox, %Text%     ; Add the text to the Gui allowing for any links in it
      GuiControlGet, Size, Pos, TextBox                                         ; Get the position of the text box
      GuiWidth := LeftMargin+SizeW+ButtonOffset+RightMargin+1                   ; Calculate the Gui width
      GuiWidth := GuiWidth < MinGuiWidth ? MinGuiWidth : GuiWidth               ; Make sure that it's not smaller than MinGuiWidth
      WhiteBoxHeight := SizeY+SizeH+Gap                                         ; Calculate the height of the white box
   }
   else                                                                         ; If the text field is blank ...
   {  GuiWidth := MinGuiWidth                                                   ; Set the width of the Gui to MinGuiWidth
      WhiteBoxHeight := 2*Gap+1                                                 ; Set the height of the white box
      BottomGap++                                                               ; Increase the gap above the button by one
      BottomHeight--                                                            ; Decrease the height of the bottom section of the Gui
   }
   GuiControl, Move, WhiteBox, w%GuiWidth% h%WhiteBoxHeight%   ; Adjust the width and height of the white box
   ButtonX := GuiWidth-RightMargin-ButtonWidth                 ; Calculate the horizontal position of the button
   ButtonY := WhiteBoxHeight+BottomGap                         ; Calculate the vertical position of the button
   Gui, Add, Button, x%ButtonX% y%ButtonY% w%ButtonWidth% h%ButtonHeight% Default, OK   ; Add the OK button
   GuiControl, Focus, OK                                       ; Sets keyboard focus to the OK button
   GuiHeight := WhiteBoxHeight+BottomHeight                    ; Calculate the overall height of the Gui
   Gui, Show, w%GuiWidth% h%GuiHeight%, %Title%                ; Show the Gui
   Gui, -ToolWindow                                            ; Remove the ToolWindow option so that the Gui has rounded corners and no icon
                                                               ; Trick from http://ahkscript.org/boards/viewtopic.php?p=11519#p11519
   if Timeout                                                  ; If the Timeout parameter has been specified ...
      SetTimer, GuiClose, % -Timeout*1000                      ; Start a timer to destroy the MsgBoxGui after Timeout seconds
   Return true

   ButtonOK:
   GuiClose:
   GuiEscape:
   Gui Destroy
   Return
}

; Reference: http://ahkscript.org/boards/viewtopic.php?f=6&t=9122

GetMsgBoxFontInfo(ByRef Name:="", ByRef Size:=0, ByRef Weight:=0, ByRef IsItalic:=0) {
   ; SystemParametersInfo constant for retrieving the metrics associated with the nonclient area of nonminimized windows
   static SPI_GETNONCLIENTMETRICS := 0x0029
   
   static NCM_Size        := 40 + 5*(A_IsUnicode ? 92 : 60)   ; Size of NONCLIENTMETRICS structure (not including iPaddedBorderWidth)
   static MsgFont_Offset  := 40 + 4*(A_IsUnicode ? 92 : 60)   ; Offset for lfMessageFont in NONCLIENTMETRICS structure
   static Size_Offset     := 0    ; Offset for cbSize in NONCLIENTMETRICS structure
   
   static Height_Offset   := 0    ; Offset for lfHeight in LOGFONT structure
   static Weight_Offset   := 16   ; Offset for lfWeight in LOGFONT structure
   static Italic_Offset   := 20   ; Offset for lfItalic in LOGFONT structure
   static FaceName_Offset := 28   ; Offset for lfFaceName in LOGFONT structure
   static FACESIZE        := 32   ; Size of lfFaceName array in LOGFONT structure
                                  ; Maximum number of characters in font name string
   
   VarSetCapacity(NCM, NCM_Size, 0)              ; Set the size of the NCM structure and initialize it
   NumPut(NCM_Size, &NCM, Size_Offset, "UInt")   ; Set the cbSize element of the NCM structure
   ; Get the system parameters and store them in the NONCLIENTMETRICS structure (NCM)
   if !DllCall("SystemParametersInfo"            ; If the SystemParametersInfo function returns a NULL value ...
             , "UInt", SPI_GETNONCLIENTMETRICS
             , "UInt", NCM_Size
             , "Ptr", &NCM
             , "UInt", 0)                        ; Don't update the user profile
      Return false                               ; Return false
   Name   := StrGet(&NCM + MsgFont_Offset + FaceName_Offset, FACESIZE)          ; Get the font name
   Height := NumGet(&NCM + MsgFont_Offset + Height_Offset, "Int")               ; Get the font height
   Size   := DllCall("MulDiv", "Int", -Height, "Int", 72, "Int", A_ScreenDPI)   ; Convert the font height to the font size in points
   ; Reference: http://stackoverflow.com/questions/2944149/converting-logfont-height-to-font-size-in-points
   Weight   := NumGet(&NCM + MsgFont_Offset + Weight_Offset, "Int")             ; Get the font weight (400 is normal and 700 is bold)
   IsItalic := NumGet(&NCM + MsgFont_Offset + Italic_Offset, "UChar")           ; Get the italic state of the font
   Return true
}
I added a parameter similar to the Timeout parameter for the MsgBox command and the function now supports links as well (see Example #2 below).

Here is some code with three fun examples demonstrating the capabilities of the function.

Code: Select all

#NoEnv

; Example #1: Demonstration of identical windows

GuiTitle = Gui or MsgBox?
MsgBoxTitle = Gui or MsgBox?
Text  = One of these windows is a Gui.`nThe other one is a MsgBox.`n`nCan you tell the difference?
MsgBoxGui(GuiTitle,Text)
WinGetPos, X, Y, W
WinMove X -= W/2+10   ; Move the MsgBoxGui to the left of the center of the window
SetTimer, MoveTimer, 1
MsgBox, , %MsgBoxTitle%, %Text%
Gui Destroy

; Example #2: Demonstration of how links work in MsgBoxGui's

GuiTitle = This is a MsgBoxGui
Text  = Links may be used anywhere in the text of a MsgBoxGui.`n<a href="http://ahkscript.org">This</a> is an example.
MsgBoxGui(GuiTitle,Text)
WinGetPos, X, Y, W
WinMove X -= W/2+10   ; Move the MsgBoxGui to the left of the center of the window
MsgBoxTitle = This is a MsgBox
Text  = Links cannot be used inside of a MsgBox.`n<a href="http://ahkscript.org">This</a> is an example.
SetTimer, MoveTimer, 1
MsgBox, , %MsgBoxTitle%, %Text%
Gui Destroy

; Example #3: Demonstration of a timed MsgBoxGui

GuiTitle = Timed MsgBoxGui
Timeout := 10
Text  = This MsgBoxGui will expire after %Timeout% seconds.
MsgBoxGui(GuiTitle,Text,Timeout)
SetTimer, TimeoutTimer, 1000

; Exit when the MsgBoxGui closes

WinWaitClose
ExitApp
Return

; Timers

MoveTimer:
IfWinActive %MsgBoxTitle% ahk_class #32770
{  WinMove, X+W+20, Y   ; Move the MsgBox to the right of the center of the window
   SetTimer, MoveTimer, Off
}
Return

TimeoutTimer:
Timeout--
GuiControl, , TextBox, This MsgBoxGui will expire after %Timeout% seconds.
if Timeout = 1
   SetTimer, TimeoutTimer, Off
Return
Windows 10 Pro (64 bit) - AutoHotkey v2.0+ (Unicode 64-bit)
User avatar
Soft
Posts: 174
Joined: 07 Jan 2015, 13:18
Location: Seoul
Contact:

Re: Gui that looks like a MsgBox

11 Aug 2015, 22:44

beautiful work!
AutoHotkey & AutoHotkey_H v1.1.22.07
Guest10
Posts: 578
Joined: 01 Oct 2013, 02:50

Re: Gui that looks like a MsgBox

14 Aug 2015, 05:50

The Link inside the MsgBox is the best feature! :geek:
garry
Posts: 3740
Joined: 22 Dec 2013, 12:50

Re: Gui that looks like a MsgBox

14 Aug 2015, 08:38

nice script
small examples with MSGBOX und GUI

Code: Select all

;- msgbox timer
t=9
msgbox, 262208,TIMER %t% seconds,This MsgBoxGui will expire after %T% seconds. ,%t%
exitapp

Code: Select all

;- msgbox timer
#SingleInstance
SetTimer, A1, 1000
t=9
msgbox, 262208,TIMERx,This MsgBoxGui will expire after %t% seconds. ,%t%
return

A1:
t--
WinActivate
IfWinNotExist, TIMERx
     return
ControlSetText, Button1, &%t%
return

Code: Select all

;- Timer example GUI
c0=D4D0C8        ;- gray normal msgbox
Gui,2:Color,c%c0%
Gui,2:Font,S10 cBlack,FixedSys
GuiTitle = Timed MsgBoxGui
T := 10
Text  = This MsgBoxGui will expire after %T% seconds.
Gui,2:add,text,x10 y10 vT1,%text%
Gui,2:show,,%guititle%
settimer,a1,1000
return

a1:
t--
if t=-1
   exitapp
GuiControl,2:,T1,This MsgBoxGui will expire after %T% seconds.
return

2Guiclose:
exitapp

Code: Select all

;-- hyperlink example GUI
c0=D4D0C8          ;- gray normal msgbox
Gui,2:Color,c%c0%
Gui,2:Font,S10 cBlack,FixedSys
Gui,2:Add, Link,, This is a <a href="http://ahkscript.org">link</a> to start http://ahkscript.org
Gui,2:Add, Link,, Underscore text like <a id="1">this</a> or <a id="2">that</a>
Gui,2:show
return
2Guiclose:
exitapp
sowen
Posts: 3
Joined: 19 Aug 2015, 21:04

Re: Gui that looks like a MsgBox

19 Aug 2015, 21:14

Love the MsgBoxGui !! Cool stuff....the ability to add a link is awesome enough...but.... :D

Any way to add an image to the MsgBoxGui ?

ie:
Text = Links may be used anywhere in the text of a MsgBoxGui.`n<a href="http://ahkscript.org">This</a> is an example.<img src="smiley.gif" alt="Smiley face" height="42" width="42">
MsgBoxGui(GuiTitle,Text)
MJs
Posts: 454
Joined: 23 Sep 2014, 03:29

Re: Gui that looks like a MsgBox

24 Aug 2015, 06:40

iPhilip wrote:I followed your suggestion and developed a GetMsgBoxFontInfo function to do so.
thanks, and thank you the nice implementation.
pneumatic
Posts: 338
Joined: 05 Dec 2016, 01:51

Re: Gui that looks like a MsgBox

18 Jan 2017, 11:23

Just a warning about using GuiMsgBoxes, when opening the GuiMsgBox it will steal the A_DefaultGui. So for example if your GuiMsgBox is in the middle of a bunch of generic GuiControl commands , they won't work after the GuiMsgBox is dismissed (unless they explicitly specify which Gui they operate on , eg. Guicontrol, MyGui: ...). To get around it you can store A_DefaultGui into a global variable at the beginning of the GuiMsgBox function , and then restore it via Gui %previousGui%:Default after OK/Cancel has been clicked. But this has a limitation for example if you have 2 Gui's open and both spawn message boxes, the order in which you close them determines which Gui becomes the default one after that. I tried using an array of A_DefaultGui's and pushing/popping them off, but have no idea how to index them with unique identifiers which match up to each GuiMsgBox and restore the corresponding default GUI. Anyway, simplest method is to just design your script where every Gui related command has its own unique GUI name , or only ever have 1 GuiMsgBox open at a time. Another thing to keep track of is every GuiMsgBox needs to have a unique title because you will probably be using WinWaitClose to pause the script while waiting for a user response, and that operates on win titles.

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: Auntiejack56 and 124 guests