Multiple GUI's with Toggle

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
scriptor2016
Posts: 860
Joined: 21 Dec 2015, 02:34

Multiple GUI's with Toggle

13 Jan 2018, 02:27

Man, I throw in the towel. Using toggles is something I just cannot grasp.

I'm building this script, and I have two GUIs. One is named WINAMP, the other is named NOTEPAD.

When you hover the cursor over the bottom GUI, a tooltip says 'NOTEPAD IN'. When you hover the cursor off of the GUI, the tooltip says "NOTEPAD OUT". This part works (almost).

For the top GUI, when you hover over it, the tooltip says 'WINAMP IN'. But the problem here is when you hover off of it, it says 'NOTEPAD OUT' instead of saying 'WINAMP OUT'. I cannot for the life of me figure this out.


And the 2nd problem - if you hover up and down between the two GUIs (while constraining the cursor between the two), the tooltips aren't working either.

I know this is all to do with the toggles, but as I said I am having major troubles understanding the concept.

Would someone be so kind to try and run this code and take a look?

Code: Select all

set=1 
 
Gui, 1: Color, FF9900
Gui, 1: +AlwaysOnTop -Caption -Sysmenu -Border  
Gui, 1: Font, cWhite
Gui, 1: Add, Text,, WINAMP
Gui, 1: Show, x100 y100 w80 h30, WINAMP
 
Gui, 2: Color, 99CCFF
Gui, 2: +AlwaysOnTop -Caption -Sysmenu -Border  
Gui, 2: Font, cWhite
Gui, 2: Add, Text,, NOTEPAD
Gui, 2: Show, x100 y130 w80 h30, NOTEPAD
 
SetTimer, MouseOverGUI, 125
Return

MouseOverGUI:
{
Gui, Submit, NoHide
wingetpos, x, y
MouseGetPos, , , id, control
WinGetTitle, title, ahk_id %id%
 
if title = WINAMP
{
{
       if( set = "1" )
       {
       tooltip, WINAMP IN
	   set = 0
       }
	   return
}	   
       if( set = "0" )
       {
       tooltip, WINAMP OUT
	   set = 1
       }
	   return
}   
	   
if title = NOTEPAD
{
       if( set = "1" )
       {
       tooltip, NOTEPAD IN
	   set = 0
       }
	   return
}	   
       if( set = "0" )
       {
       tooltip, NOTEPAD OUT
	   set = 1
       }
	   return	   
} 
return

just me
Posts: 9457
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Multiple GUI's with Toggle

13 Jan 2018, 03:56

You should check your block { ... } structure (indentation is helpful in this case):

Code: Select all

MouseOverGUI:
{  ; <<<<< dispensable
   Gui, Submit, NoHide
   wingetpos, x, y
   MouseGetPos, , , id, control
   WinGetTitle, title, ahk_id %id%
   ; -----------------------------------
   if title = WINAMP
   {
      {  ; <<<<< dispensable
         if( set = "1" )
         {
            tooltip, WINAMP IN
            set = 0
         }
         return
      }  ; <<<<< dispensable
      if( set = "0" )
      {
         tooltip, WINAMP OUT
         set = 1
      }
      return
   }
   ; -----------------------------------
   if title = NOTEPAD
   {
      if( set = "1" )
      {
         tooltip, NOTEPAD IN
         set = 0
      }
      return
   }
   ; -----------------------------------
   if( set = "0" )
   {
      tooltip, NOTEPAD OUT
      set = 1
   }
   return
}  ; <<<<< dispensable
return
scriptor2016
Posts: 860
Joined: 21 Dec 2015, 02:34

Re: Multiple GUI's with Toggle

13 Jan 2018, 04:21

hi just me, thanks -I tried replacing my timer with your timer ..but same result (sorry, I keep playing with this but so far the results are the same)

I trust you're right. There's something wrong with the block structure. And probably the toggle as well. This is driving me insane
just me
Posts: 9457
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Multiple GUI's with Toggle

13 Jan 2018, 05:24

Hi scriptor2016,
But the problem here is when you hover off of it, it says 'NOTEPAD OUT' instead of saying 'WINAMP OUT'. I cannot for the life of me figure this out.
I didn't change your block structure, I just changed the indentation to clarify what's wrong with it. Don't you see it?

And there are other issues in your timer. A simple 0/1 toggle is not enough when you're playing with more than one window. You should use the window title to keep track of which window you are entering / leaving.
Rindis
Posts: 213
Joined: 23 Dec 2013, 13:58
Location: Norway
Contact:

Re: Multiple GUI's with Toggle

13 Jan 2018, 05:36

Code: Select all

set=0
 
Gui, 1: Color, FF9900
Gui, 1: +AlwaysOnTop -Caption -Sysmenu -Border  
Gui, 1: Font, cWhite
Gui, 1: Add, Text,, WINAMP
Gui, 1: Show, x100 y100 w80 h30, WINAMP
 
Gui, 2: Color, 99CCFF
Gui, 2: +AlwaysOnTop -Caption -Sysmenu -Border  
Gui, 2: Font, cWhite
Gui, 2: Add, Text,, NOTEPAD
Gui, 2: Show, x100 y130 w80 h30, NOTEPAD
 
SetTimer, MouseOverGUI, 125
Return

MouseOverGUI:

   Gui, Submit, NoHide
   wingetpos, x, y
   MouseGetPos, , , id, control
   WinGetTitle, title, ahk_id %id%
   ; -----------------------------------
   if title = WINAMP
   {
      
       tooltip, WINAMP IN
       set = WINAMP
         return
   }
   if title = NOTEPAD
   {

       tooltip, NOTEPAD IN
       set = NOTEPAD
      return
   }
   

   if( title != WINAMP ) && (title != NOTEPAD)
   {
      if set = WINAMP
      {
      tooltip, WINAMP OUT
      return
      }
      if set = NOTEPAD
      {
      tooltip, NOTEPAD OUT
      return
      }
      else
      {
         return
      }
   }
    
return

esc::
ExitApp


garry
Posts: 3770
Joined: 22 Dec 2013, 12:50

Re: Multiple GUI's with Toggle

13 Jan 2018, 05:38

example with onmessage instead settimer
EDIT : @ Rindis your example works fine

Code: Select all

#warn
global title
Gui, 1: Color, FF9900
Gui, 1: +AlwaysOnTop -Caption -Sysmenu -Border
Gui, 1: Font, cWhite
Gui, 1: Add, Text,, WINAMP
Gui, 1: Show, x100 y100 w80 h30, WINAMP

Gui, 2: Color, 99CCFF
Gui, 2: +AlwaysOnTop -Caption -Sysmenu -Border
Gui, 2: Font, cWhite
Gui, 2: Add, Text,, NOTEPAD
Gui, 2: Show, x100 y130 w80 h30, NOTEPAD
OnMessage(0x200, "WM_MOUSEMOVE")
Return

GuiClose:
ExitApp
esc::exitapp

WM_MOUSEMOVE() { ; mouse hover
MouseGetPos, , , id, control
WinGetTitle, title, ahk_id %id%
Tooltip % title
	setTimer ttOff, -300
}
ttOff(){
tooltip,%title%_OUT
sleep,800
	tooltip
}
;===============================================
scriptor2016
Posts: 860
Joined: 21 Dec 2015, 02:34

Re: Multiple GUI's with Toggle

13 Jan 2018, 15:48

just me - thanks - I'll keep studying this as it is indeed a little more in depth that I had thought.

Rindis/garry - onmessage works 0x200 works, but It sends the tooltip continuously. I want it to send the tooltip just once upon entering the GUI and then just once upon exiting- this is where I thought the timer with a toggle (which would stop the repetitive sending of the tooltips) would be a better approach instead of onmessage . I'm afraid this might be out of my realms lol.
just me
Posts: 9457
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Multiple GUI's with Toggle

13 Jan 2018, 16:51

As an example using associative arrays:

Code: Select all

#NoEnv
PrevTitle := ""
; Associative arrays of window titles and associated tooltips
EnterTT := {NOTEPAD: "NOTEPAD IN", WINAMP: "WINAMP IN"}
LeaveTT := {NOTEPAD: "NOTEPAD OUT", WINAMP: "WINAMP OUT"}

Gui, 1: Color, FF9900
Gui, 1: +AlwaysOnTop -Caption -Sysmenu -Border
Gui, 1: Font, cWhite
Gui, 1: Add, Text,, WINAMP
Gui, 1: Show, x100 y100 w80 h30, WINAMP

Gui, 2: Color, 99CCFF
Gui, 2: +AlwaysOnTop -Caption -Sysmenu -Border
Gui, 2: Font, cWhite
Gui, 2: Add, Text,, NOTEPAD
Gui, 2: Show, x100 y130 w80 h30, NOTEPAD

SetTimer, MouseOverGUI, 125
Return

MouseOverGUI:
   MouseGetPos, , , WinID
   WinGetTitle, Title, ahk_id %WinID%
   If (Title <> PrevTitle) {
      SetTimer, KillTT, -1000
      If EnterTT.Haskey(Title)            ; the new window is one of the GUI windows
         ToolTip, % (LeaveTT.HasKey(PrevTitle) ? LeaveTT[PrevTitle] . "`n" : "") . EnterTT[Title]
      Else If LeaveTT.HasKey(PrevTitle)   ; the previous window is one of the GUI windows
         ToolTip, % LeaveTT[PrevTitle]
      PrevTitle:= Title
   }
Return

KillTT:
   ToolTip
Return
scriptor2016
Posts: 860
Joined: 21 Dec 2015, 02:34

Re: Multiple GUI's with Toggle

14 Jan 2018, 01:29

hello just me, I am very greatful. It is working perfectly and I have understood enough of your script to help me move forward. I've studied over your code and am now starting to grasp it. As proof, I will show you how far I have come with your help. I think this is almost there, but again I am stuck.

I am building a menu GUI which will have all the buttons on top of eachother. When a button is clicked, it will do something (run a program, for example). This GUI, when complete, will have as many as 50 or more buttons so even though there are 3 right now, there will be many more as I continue to add to it.

My goal here is to have "rollover" text for each button. So when you hover over any of the gui's (i.e. buttons), the text color on that button changes to white.

For the WINAMP button, when you hover on it, the text turns to white (this is successful so far.) And when you hover off of WINAMP, the text color returns to black.

My final 2 obstacles:

1. when you hover off of WINAMP to the right, left or above the button, the text successfully returns to black. But if you hover off of it downwards towards NOTEPAD, the text of WINAMP stays black instead of returning to white.

2. The rollover/hover color change works only on WINAMP, but not on NOTEPAD or PICTUS.

The reason for my delayed response this evening is that I have spent all afternoon trying to solve this but again I ask for assistance as I have now hit a wall. I cannot figure these two problems out. I can show the code here:

Code: Select all

#NoEnv
PrevTitle := ""
; Associative arrays of window titles and associated tooltips
EnterTT := {NOTEPAD: "NOTEPAD IN", WINAMP: "WINAMP IN", PICTUS: "PICTUS IN"}
LeaveTT := {NOTEPAD: "NOTEPAD OUT", WINAMP: "WINAMP OUT", PICTUS: "PICTUS OUT"}

Gui, 1: Color, FF9900
Gui, 1: +AlwaysOnTop -Caption -Sysmenu -Border
Gui, 1: Font, cBlack
Gui, 1: Add, Text,, WINAMP
Gui, 1: Show, x100 y100 w80 h30, WINAMP

Gui, 2: Color, 99CCFF
Gui, 2: +AlwaysOnTop -Caption -Sysmenu -Border
Gui, 2: Font, cBlack
Gui, 2: Add, Text,, NOTEPAD
Gui, 2: Show, x100 y130 w80 h30, NOTEPAD

Gui, 3: Color, 669966
Gui, 3: +AlwaysOnTop -Caption -Sysmenu -Border
Gui, 3: Font, cBlack
Gui, 3: Add, Text,, PICTUS
Gui, 3: Show, x100 y160 w80 h30, PICTUS


OnMessage(0x201, "WM_LBUTTONDOWN") 


SetTimer, MouseOverGUI, 125
Return

MouseOverGUI:
   MouseGetPos, , , WinID
   WinGetTitle, Title, ahk_id %WinID%
   If (Title <> PrevTitle) 
   {
      SetTimer, KillTT, -1000
      If EnterTT.Haskey(Title)            ; the new window is one of the GUI windows
	  {
		 Gui, Font, cWhite
         GuiControl, Font, %Title%
		 GuiControl, Show, %Title%
		 }
		 
		 
      Else If LeaveTT.HasKey(PrevTitle)   ; the previous window is one of the GUI windows
	  
	   {
		 Gui, Font, cBlack
         GuiControl, Font, %PrevTitle%
		 GuiControl, Show, %PrevTitle%
		 }
		 
      PrevTitle:= Title
   }
Return

KillTT:
   ToolTip
Return


WM_LBUTTONDOWN(wParam, lParam, Msg) 
{
MouseGetPos, , , id, control
WinGetTitle, title2, ahk_id %id%

if title2 = WINAMP
{
tooltip, you clicked WINAMP so do what you want here
return
}

if title2 = NOTEPAD
{
tooltip, you clicked NOTEPAD so do what you want here
return
}

if title2 = PICTUS
{
tooltip, you clicked PICTUS so do what you want here
return
}
}
 
just me
Posts: 9457
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Multiple GUI's with Toggle

14 Jan 2018, 05:04

Hello scriptor2016,

you need to specify the Gui in GuiControl if you work with another than the default Gui. That's why your approach will only work for Gui 1.

To change control's text color is different from showing tooltips on entering as well as leaving a Gui window. So I changed the concept to rely on window IDs (HWNDs) instead of titles:

Code: Select all

#NoEnv
; Variable which holds the ID (HWND) of the currently hovered window
PrevID := ""
; Associative array of Gui window IDs (HWNDs) and the associated control text
IDArray := []

Gui, 1: +AlwaysOnTop -Caption -Sysmenu -Border +HwndHGUI ; Hwnd option added
Gui, 1: Color, FF9900
Gui, 1: Font, cBlack
Gui, 1: Margin, 0, 0
Gui, 1: Add, Text, w80 h30 cBlack Center +0x0200 vWINAMP gClicked, WINAMP ; control name added
Gui, 1: Show, x100 y100, WINAMP
IDArray[HGUI] := "WINAMP" ; store the ID of the Gui and the associated control name in the array

Gui, 2: +AlwaysOnTop -Caption -Sysmenu -Border +HwndHGUI
Gui, 2: Color, 99CCFF
Gui, 2: Font, cBlack
Gui, 2: Margin, 0, 0
Gui, 2: Add, Text, w80 h30 cBlack Center +0x0200 vNOTEPAD gClicked, NOTEPAD
Gui, 2: Show, x100 y130, NOTEPAD
IDArray[HGUI] := "NOTEPAD"

Gui, 3: +AlwaysOnTop -Caption -Sysmenu -Border +HwndHGUI
Gui, 3: Color, 669966
Gui, 3: Font, cBlack
Gui, 3: Margin, 0, 0
Gui, 3: Add, Text, w80 h30 cBlack Center +0x0200 vPICTUS gClicked, PICTUS
Gui, 3: Show, x100 y160, PICTUS
IDArray[HGUI] := "PICTUS"

SetTimer, MouseOverGUI, 125
Return

MouseOverGUI:
   MouseGetPos, , , WinID
   If (WinID <> PrevID)
   {
      If IDArray.HasKey(PrevID) { ; the previous  window is one of the GUI windows
         Gui, %PrevID%: Font, cBlack
         GuiControl, %PrevID%: Font, % IDArray[PrevID]
      }
      If IDArray.HasKey(WinID) {  ; the new window is one of the GUI windows
         Gui, %WinID%: Font, cWhite
         GuiControl, %WinID%: Font, % IDArray[WinID]
      }
      PrevID := WinID
   }
Return

Clicked:
   ToolTip, You clicked on %A_GuiControl% so do what you want here!
   SetTimer, KillTT, -1000
Return

KillTT:
   ToolTip
Return
But you might be interested in another concept using buttons. All you need is the FCB() function posted here. I added it to the example:

Code: Select all

#NoEnv

Gui, +AlwaysOnTop -Caption
Gui, Margin, 0, 0
Gui, Add, Button, xm w80 h30 vWINAMP gClicked +HwndHBTN, WINAMP
FCB_Create(HBTN, [0xFF9900], ["Black", "White"])
Gui, Add, Button, xm w80 h30 vNOTEPAD gClicked +HwndHBTN, NOTEPAD
FCB_Create(HBTN, [0x99CCFF], ["Black", "White"])
Gui, Add, Button, xm w80 h30 vPICTUS gClicked +HwndHBTN, PICTUS
FCB_Create(HBTN, [0x669966], ["Black", "White"])
Gui, Show, x100 y100
Return

GuiEscape:
ExitApp

Clicked:
   ToolTip, You clicked on %A_GuiControl% so do what you want here!
   SetTimer, KillTT, -1000
Return

KillTT:
   ToolTip
Return


; ================================================================================================================================
; Function:       Creates flat colored push buttons with up to 6 colors for the different button states.
; Syntax:         FCB_Create(Hwnd, BkgColors[, TxtColors])
; Parameters:
;     Hwnd        -  The handle (HWND) to the button.
;     BkgColors   -  An array of up to 6 color values used to draw the background of the button.
;                    The first element is mandatory. Its value will be used for all other omitted or empty elements.
;     TxtColors   -  An array of up to 6 color values used to draw the text of the button.
;                    If the first element is omitted it will be set to the default text color.
;                    The value of the first element will be used for all other omitted or empty elements.
;                    Default: "" -> use the default text color for all states.
; Return values:
;     Returns True on success; otherwise False.
; Remarks:
;     All color values can be passed either as AHK HTML color name (e.g. "Navy") or RGB integer value (e.g. 0xRRGGBB).
;
;     MSDN defines 6 states (msdn.microsoft.com/en-us/library/windows/desktop/bb775975(v=vs.85).aspx):
;         PBS_NORMAL    = 1
;	      PBS_HOT       = 2
;	      PBS_PRESSED   = 3
;	      PBS_DISABLED  = 4
;	      PBS_DEFAULTED = 5
;	      PBS_STYLUSHOT = 6
;     On Win Vista and 7 the colors specified for states 5 and 6 are used to animate the current default button.
; ================================================================================================================================
FCB_Create(Hwnd, BkgColors, TxtColors := "") {
   ; System colors
   Static DefTxtColor := DllCall("GetSysColor", "Int", 18, "UInt") ; default text color
        , DisBkgColor := ""                                        ; disabled background color
        , DisTxtColor := DllCall("GetSysColor", "Int", 17, "UInt") ; disabled text color
   ; Stock objects
   Static DCB := DllCall("GetStockObject", "Int", 18, "UPtr") ; DC_BRUSH
        , DCP := DllCall("GetStockObject", "Int", 19, "UPtr") ; DC_PEN
   ; Messages
   Static WM_GETFONT := 0x31
   ; Styles
   Static BS_DEFPUSHBUTTON := 0x01, BS_LEFT := 0x0100, BS_RIGHT := 0x0200, BS_CENTER := 0x0300, BS_TOP := 0x0400
        , BS_BOTTOM := 0x0800, BS_VCENTER := 0x0C00, BS_MULTILINE := 0x2000, WS_DISABLED := 0x08000000
        , BS_CHECKBOX := 0x02, BS_RADIOBUTTON := 0x04, BS_GROUPBOX := 0x07, BS_AUTORADIOBUTTON := 0x09
        , RCBUTTONS := BS_CHECKBOX | BS_RADIOBUTTON | BS_AUTORADIOBUTTON
   ; DrawText format flags
   Static DT_LEFT := 0x00, DT_TOP := 0x00, DT_CENTER := 0x01, DT_RIGHT := 0x02, DT_VCENTER := 0x04
        , DT_BOTTOM := 0x08, DT_WORDBREAK := 0x10, DT_SINGLELINE := 0x20, DT_NOCLIP := 0x0100, DT_CALCRECT := 0x0400
        , DT_END_ELLIPSIS := 0x8000, DT_PATH_ELLIPSIS := 0x4000
   ; Image list flags
   Static ILC_COLOR32 := 0x20
   ; =============================================================================================================================
   ; Get the backgound color for disabled buttons on first call
   If (DisBkgColor = "") {
      LGB := DllCall("GetStockObject", "Int",  1, "UPtr") ; LTGRAY_BRUSH
      VarSetCapacity(LB, 16, 0) ; LOGBRUSH
      DllCall("GetObject", "Ptr", LGB, "Int", A_PtrSize = 8 ? 16 : 12, "Ptr", &LB)
      DisBkgColor := NumGet(LB, 4, "UInt")
      DllCall("DeleteObject", "Ptr", LGB)
   }
   ; -----------------------------------------------------------------------------------------------------------------------------
   ; Check the control parameter
   If !DllCall("IsWindow", "Ptr", Hwnd, "UPtr")
      Return False
   ; Get and check control's class and styles
   WinGetClass, BtnClass, ahk_id %Hwnd%
   ControlGet, BtnStyle, Style, , , ahk_id %Hwnd%
   If (BtnClass != "Button") || ((BtnStyle & 0xF ^ BS_GROUPBOX) = 0) || ((BtnStyle & RCBUTTONS) > 1)
      Return False
   ; -----------------------------------------------------------------------------------------------------------------------------
   ; Check and convert the color parameters
   ; Background colors
   If !(IsObject(BkgColors)) || (BkgColors[1] = "")
      Return False
   If !(BkgArray := FCB_GetColors(BkgColors, 0))
      Return False
   ; Text colors
   If !(IsObject(TxtColors)) || (TxtColors.MaxIndex() = "")
      TxtArray := [DefTxtColor, DefTxtColor, DefTxtColor, DefTxtColor, DefTxtColor, DefTxtColor]
   Else If !(TxtArray := FCB_GetColors(TxtColors, DefTxtColor))
      Return False
   ; -----------------------------------------------------------------------------------------------------------------------------
   ; Get the button's properties.
   HFN := DllCall("SendMessage", "Ptr", Hwnd, "UInt", 0x31, "Ptr", 0, "Ptr", 0, "UPtr") ; WM_GETFONT
   ControlGetText, BtnCaption, , ahk_id %Hwnd%
   VarSetCapacity(CtlRect, 16, 0)
   DllCall("GetClientRect", "Ptr", Hwnd, "Ptr", &CtlRect)
   CtlW := NumGet(CtlRect, 8, "Int")
   CtlH := NumGet(CtlRect, 12, "Int")
   ; -----------------------------------------------------------------------------------------------------------------------------
   ; Create a compatible memory DC and a compatible bitmap for drawing
   HDC := DllCall("GetDC", "Ptr", Hwnd, "UPtr")
   MDC := DllCall("CreateCompatibleDC", "Ptr", HDC, "UPtr")
   HBM := DllCall("CreateCompatibleBitmap", "Ptr", HDC, "Int", CtlW, "Int", CtlH, "UPtr")
   HBM := DllCall("CopyImage", "Ptr", HBM, "UInt", 0, "Int", 0, "Int", 0, "UInt", 0x2008, "UPtr")
   DllCall("SelectObject", "Ptr", MDC, "Ptr", DCB)
   DllCall("SelectObject", "Ptr", MDC, "Ptr", DCP)
   DllCall("SelectObject", "Ptr", MDC, "Ptr", HFN)
   DllCall("ReleaseDC", "Ptr", Hwnd, "Ptr", HDC)
   ; -----------------------------------------------------------------------------------------------------------------------------
   ; Calculate the text rectangle
   CenterBtn := BtnStyle & BS_CENTER
   DT_ALIGN := CenterBtn = BS_CENTER ? DT_CENTER
             : CenterBtn = BS_RIGHT  ? DT_RIGHT
             : CenterBtn = BS_LEFT   ? DT_LEFT
                                     : DT_CENTER
   DT_ALIGN |= (BtnStyle & BS_MULTILINE) ? DT_WORDBREAK : DT_END_ELLIPSIS
   VC := BtnStyle & BS_VCENTER
   If (VC = BS_VCENTER) || (VC = BS_BOTTOM) || (VC = 0) {
      VarSetCapacity(TxtRect, 16, 0)
      NumPut(NumGet(CtlRect, 0, "Int64"), TxtRect, 0, "Int64")
      NumPut(NumGet(CtlRect, 8, "Int64"), TxtRect, 8, "Int64")
      TxtT := NumGet(TxtRect, 4, "Int")
      TxtB := NumGet(TxtRect, 12, "Int")
      DllCall("DrawText", "Ptr", MDC, "Str", BtnCaption, "Int", -1, "Ptr", &TxtRect, "UInt", DT_ALIGN | DT_CALCRECT)
      D := TxtB - NumGet(TxtRect, 12, "Int")
      TxtT += (VC = BS_BOTTOM) ? D : D // 2
      NumPut(TxtT, CtlRect, 4, "Int")
      NumPut(TxtB, CtlRect, 12, "Int")
   }
   ; -----------------------------------------------------------------------------------------------------------------------------
   ; Create the bitmaps for each button state and add them to an image list
   HIL := DllCall("ImageList_Create", "UInt", CtlW, "UInt", CtlH, "UInt", ILC_COLOR32, "Int", 6, "Int", 0, "UPtr")
   Loop, 6 {
      OBM := DllCall("SelectObject", "Ptr", MDC, "Ptr", HBM)
      BtnDisabled := BtnStyle & WS_DISABLED
      BkgColor := BtnDisabled ? DisBkgColor : BkgArray[A_Index]
      TxtColor := BtnDisabled ? DisTxtColor : TxtArray[A_Index]
      DllCall("SetDCBrushColor", "Ptr", MDC, "UInt", BkgColor)
      DllCall("SetDCPenColor", "Ptr", MDC, "UInt", BkgColor)
      DllCall("Rectangle", "Ptr", MDC, "Int", 0, "Int", 0, "Int", CtlW, "Int", CtlH)
      DllCall("SetBkMode", "Ptr", MDC, "Int", 1)
      DllCall("SetTextColor", "Ptr", MDC, "UInt", TxtColor)
      DllCall("DrawText", "Ptr", MDC, "Str", BtnCaption, "Int", -1, "Ptr", &CtlRect, "UInt", DT_ALIGN)
      DllCall("SelectObject", "Ptr", MDC, "Ptr", OBM)
      DllCall("ImageList_Add", "Ptr", HIL, "Ptr", HBM, "Ptr", 0)
      If (BtnDisabled)
         Break
   }
   ; -----------------------------------------------------------------------------------------------------------------------------
   ; Create a BUTTON_IMAGELIST structure
   VarSetCapacity(BIL, 20 + A_PtrSize, 0)
   NumPut(HIL, BIL, 0, "Ptr")
   Numput(4, BIL, A_PtrSize + 16, "UInt") ; BUTTON_IMAGELIST_ALIGN_CENTER
   ; Assign the ImageList to the button
   Control, Style, +0x0080, , ahk_id %Hwnd% ; BS_BITMAP
   DllCall("SendMessage", "Ptr", Hwnd, "UInt", 0x1602, "Ptr", 0, "Ptr", 0) ; BCM_SETIMAGELIST
   DllCall("SendMessage", "Ptr", Hwnd, "UInt", 0x1602, "Ptr", 0, "Ptr", &BIL)
   ; -----------------------------------------------------------------------------------------------------------------------------
   ; Free the GDI objects
   DllCall("DeleteDC", "Ptr", MDC)
   DllCall("DeleteObject", "Ptr", HBM)
   ; -----------------------------------------------------------------------------------------------------------------------------
   ; All done
   Return True
}
; ================================================================================================================================
; Internally called function to convert the colors to BGR
; ================================================================================================================================
FCB_GetColors(ColorArray, DefColor) {
   ; HTML colors (BGR)
   Static HTML := {BLACK:   0x000000, GRAY: 0x808080, SILVER: 0xC0C0C0, WHITE: 0xFFFFFF, MAROON: 0x000080, PURPLE: 0x800080
                 , FUCHSIA: 0xFF00FF, RED:  0x0000FF, GREEN:  0x008000, OLIVE: 0x008080, YELLOW: 0x00FFFF, LIME:   0x00FF00
                 , NAVY:    0x800000, TEAL: 0x808000, AQUA:   0xFFFF00, BLUE:  0xFF0000}
   Colors := []
   Loop, 6 {
      CurrColor := ColorArray[A_Index]
      If (CurrColor = "")
         CurrColor := A_Index = 1 ? DefColor : Colors[1]
      Else If (HTML.HasKey(CurrColor))
         CurrColor := HTML[CurrColor]
      Else
         CurrColor := ((CurrColor & 0xFF0000) >> 16) | (CurrColor & 0x00FF00) | ((CurrColor & 0x0000FF) << 16)
      If (CurrColor = "")
         Return False
      Colors[A_Index] := CurrColor
   }
   Return Colors
}
scriptor2016
Posts: 860
Joined: 21 Dec 2015, 02:34

Re: Multiple GUI's with Toggle

14 Jan 2018, 16:28

Hello just me, this is fantastc. It should become a sticky topic as I bet many other users would love to use this. Your code is excellent - it works just as planned. I hadn't realized that adding rollover images on multiple GUIs could be such a challenge. I owe you a beer.

Just wondering, if we wanted to change the background color of the GUIs on rollover as well, would that be an easy addition or would it be a large overhaul to the code?
just me
Posts: 9457
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Multiple GUI's with Toggle

15 Jan 2018, 04:29

Hi scriptor2016,

which of the two versions do you mean? Also, the GUI background is not visible for both versions.
scriptor2016
Posts: 860
Joined: 21 Dec 2015, 02:34

Re: Multiple GUI's with Toggle

15 Jan 2018, 10:46

I'm thinking the second version (the one with the FCB function) as that seems a little easier for me to understand. But whichever is easier.

Yes, sorry, I meant changing the colors of the buttons on mouseover, not changing the color of the GUI backgrounds, my mistake.
just me
Posts: 9457
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Multiple GUI's with Toggle

15 Jan 2018, 10:54

You can specify a second color in the BkgColors array (the second parameter of FCB()) which will be used as the background color for the hot (hovered) state.
scriptor2016
Posts: 860
Joined: 21 Dec 2015, 02:34

Re: Multiple GUI's with Toggle

15 Jan 2018, 11:14

alright, awesome.. I'm going to try this soon as I can and I will report back with the progress :)

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Chunjee, gsxr1300, inseption86, jaka1, mebelantikjaya, mikeyww and 308 guests