Jump to content

A Recreation Of TrayMenu Style Separators using GUI Label Controls : Tutorial

Recommended Posts

This may or may not be useful and comes in play if you are not using a UDF or the built-in methods or 3rd party code for creating menus and layouts.

I wrote this with the assumption the reader is new to the language and doesn't have a lot of experience yet.

Possible Reasons
1: You are writing Gui elements yourself from scratch.  Why?  because you just desire to.
2: Need for something to work a specific way that the built-in methods do not allow for.
3: You just want a learning exercise.

I was trying to figure out how to recreate the separators you see in tray menus with that same style inside a GUI using Label Controls.
You know those single lines that separate menu items when you use  

TrayCreateItem("") ; Create a separator line.

See Attached Image

Either there is no single GUI control to allow for the exact styling of separator lines seen in the Tray Menu OR I haven't discovered it yet.

My solution:

The color codes in RGB HEX

0xD5DFE5  ;~  A light blue grey color
0xFFFFFF  ;~  Color white

When you insert your Label Control leave the "text" part empty and do not use any option flags.
Some of the Style and Ex Style options prevent coloring and sizing the control. 

GUICtrlCreateLabel("", LEFT, TOP, WIDTH, HEIGHT)


You need TWO controls and TWO background color settings 


Horizontal Separator  - White Color goes on bottom

GUICtrlCreateLabel("", LEFT, TOP, WIDTH, HEIGHT)         ;~  Empty Label Control
GUICtrlSetBKColor(-1, 0xD5DFE5)                          ;~  Background Color Setting for previous Label Control
GUICtrlCreateLabel("", LEFT, TOP + 1, WIDTH, HEIGHT)     ;~  Second Label Control needs to be distanced one away from previous Label Control
GUICtrlSetBKColor(-1, 0xFFFFFF)


Vertical Separator - White Color is on INSIDE or to the Right of the grey line

GUICtrlCreateLabel("", LEFT, TOP, HEIGHT, WIDTH)         ;~ Reverse Width and Height
GUICtrlSetBKColor(-1, 0xD5DFE5)                          
GUICtrlCreateLabel("", LEFT + 1, TOP, HEIGHT, WIDTH)     ;~ Add ONE to the LEFT not the TOP 
GUICtrlSetBKColor(-1, 0xFFFFFF)

This will MATCH the Tray Menu separators in color and look.  

Separator Line.jpg

Edited by iAmNewbe
Link to post
Share on other sites

Full Code Sample

#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <TrayConstants.au3> ; Required for the $TRAY_ICONSTATE_SHOW constant.

Opt("TrayMenuMode", 3) ; The default tray menu items will not be shown and items are not checked when selected. These are options 1 and 2 for TrayMenuMode.

HotKeySet("{ESC}", "close")


Func Example()

    Global $hGui = GUICreate("Example", 200, 120, -1, -1)

    GUISetState(@SW_SHOW, $hGui)

    #Region ;~ Vertical Separator
    GUICtrlCreateLabel("", 30, 20, 1, 90) ; L T W H
    GUICtrlSetBKColor(-1, 0xD5DFE5)
    GUICtrlCreateLabel("", 31, 20, 1, 90) ; L T W H
    GUICtrlSetBKColor(-1, 0xFFFFFF)

    #Region ;~ Horizontal Separator
    GUICtrlCreateLabel("", 32, 40, 150, 1) ; L T W H
    GUICtrlSetBKColor(-1, 0xD5DFE5)
    GUICtrlCreateLabel("", 32, 41, 150, 1) ; L T W H
    GUICtrlSetBKColor(-1, 0xFFFFFF)

    GUICtrlCreateLabel("Separator Lines Example", 32, 55, 150, 20, $SS_CENTER) ; L T W H Style StyleEX

    #Region ;~ Horizontal Separator
    GUICtrlCreateLabel("", 32, 81, 150, 1) ; L T W H
    GUICtrlSetBKColor(-1, 0xD5DFE5)
    GUICtrlCreateLabel("", 32, 82, 150, 1) ; L T W H
    GUICtrlSetBKColor(-1, 0xFFFFFF)

    #Region ;~ Tray Menu
    TrayCreateItem("") ; Create a separator line.
    TrayCreateItem("Separator Lines Example")
    TrayCreateItem("") ; Create a separator line.

    Local $idExit = TrayCreateItem("Exit")

    TraySetState($TRAY_ICONSTATE_SHOW) ; Show the tray menu.

    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE

        Switch TrayGetMsg()
            Case $idExit ; Exit the loop.
EndFunc   ;==>Example

Func close()


Link to post
Share on other sites
Posted (edited)

Basically you just put two controls next to each other and color one, one color and another something else.

I was writing a question about this on HOW to do this and in the process I figured it out.
Since I wrote most of it already I just finished it into a little tutorial for those not already in the know on this.

I am sure I will forget this and will need at sometime to rediscover so this is also a tutorial for my future self when I forget.

There used to be a tutorial or scripts section in the forums, I am not able to find it or would put it there instead of here. Since it is GUI related I posted to the GUI Help and Support section.

Edited by iAmNewbe
Link to post
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By water
      Internet Explorer is nearly dead, newer versions of Firefox can't any longer be automated using Stilgar's FF UDF.
      Hence more and more users (including me) need to look at automating Webbrowsers using WebDriver.
      That's why I have started to create a tutorial in the wiki.
      It should describe all necessary steps from intallation to usage.

      I'm still collecting ideas for the tutorial - that's where you come into play.
      What do you expect to see in such a tutorial?
      Which browsers should be covered (Firefox, Chrome and Edge are settled)? Any questions for the FAQ? Which (high level) coding examples do you expect (like "How to attach to a running browser instance") ... Like to see your comments
      Add "Tools" section and add ChroPath plugin. Done. FAQ: "How to attach to a running browser instance". Done. Explain the difference between iuiautomation, iaccessible, autoit, webdriver. Done. The AutoIt FAQ 40 has been extended. Detailed description of each function. Done Example for "how to deal with downloading". Use function _WD_DownloadFile. Example for "how to deal with popups (alerts, print or save dialog). Use function_WD_AlertRespond to respond to a user prompt. Example for "how to deal with multiple tabs". Use functions _WD_NewTab (create a new tab), _WD_Window (close or switch to a tab) and _WD_Attach (attach to existing tab).
    • By TheDcoder
      Hello Guys! I wanted to share all my knowledge on arrays! Hope may enjoy the article , Lets start!
      Declaring arrays!
      Declaring arrays is a little different than other variables: 
      ; Rules to follow while declaring arrays: ; ; Rule #1: You must have a declarative keyword like Dim/Global/Local before the declaration unless the array is assigned a value from a functions return (Ex: StringSplit) ; Rule #2: You must declare the number of dimensions but not necessarily the size of the dimension if you are gonna assign the values at the time of declaration. #include <Array.au3> Local $aEmptyArray[0] ; Creates an Array with 0 elements (aka an Empty Array). Local $aArrayWithData[1] = ["Data"] _ArrayDisplay($aEmptyArray) _ArrayDisplay($aArrayWithData) That's it
      Resizing Arrays
      Its easy! Just like declaring an empty array! ReDim is our friend here:
      #include <Array.au3> Local $aArrayWithData[1] = ["Data1"] ReDim $aArrayWithData[2] ; Change the number of elements in the array, I have added an extra element! $aArrayWithData[1] = "Data2" _ArrayDisplay($aArrayWithData) Just make sure that you don't use ReDim too often (especially don't use it in loops!), it can slow down you program.
      Best practice of using "Enum"
      You might be wondering what they might be... Do you know the Const keyword which you use after Global/Local keyword? Global/Local are declarative keywords which are used to declare variables, of course, you would know that already by now , If you check the documentation for Global/Local there is a optional parameter called Const which willl allow you to "create a constant rather than a variable"... Enum is similar to Const, it declares Integers (ONLY Integers):
      Global Enum $ZERO, $ONE, $TWO, $THREE, $FOUR, $FIVE, $SIX, $SEVEN, $EIGHT, $NINE ; And so on... ; $ZERO will evaluate to 0 ; $ONE will evaluate to 1 ; You get the idea :P ; Enum is very useful to declare Constants each containing a number (starting from 0) This script will demonstrate the usefulness and neatness of Enums :
      ; We will create an array which will contain details of the OS Global Enum $ARCH, $TYPE, $LANG, $VERSION, $BUILD, $SERVICE_PACK Global $aOS[6] = [@OSArch, @OSType, @OSLang, @OSVersion, @OSBuild, @OSServicePack] ; Now, if you want to access anything related to the OS, you would do this: ConsoleWrite(@CRLF) ConsoleWrite('+>' & "Architecture: " & $aOS[$ARCH] & @CRLF) ConsoleWrite('+>' & "Type: " & $aOS[$TYPE] & @CRLF) ConsoleWrite('+>' & "Langauge: " & $aOS[$LANG] & @CRLF) ConsoleWrite('+>' & "Version: " & $aOS[$VERSION] & @CRLF) ConsoleWrite('+>' & "Build: " & $aOS[$BUILD] & @CRLF) ConsoleWrite('+>' & "Service Pack: " & $aOS[$SERVICE_PACK] & @CRLF) ConsoleWrite(@CRLF) ; Isn't it cool? XD You can use this in your UDF(s) or Program(s), it will look very neat!
      Looping through an Array
      Looping through an array is very easy! . There are 2 ways to loop an array in AutoIt!
      Simple Way:
      ; This is a very basic way to loop through an array ; In this way we use a For...In...Next Loop! Global $aArray[2] = ["Foo", "Bar"] ; Create an array ; This loop will loop 2 times because our $aArray contains 2 elements. For $vElement In $aArray ; $vElement will contain the value of the elements in the $aArray... one element at a time. ConsoleWrite($vElement & @CRLF) ; Prints the element out to the console Next ; And that's it! Advanced Way:
      ; This is an advanced way to loop through an array ; In this way we use a For...To...Next Loop! Global $aArray[4] = ["Foo", "Bar", "Baz", "Quack"] ; Create an array ; This loop will loop 2 times because our $aArray contains 2 elements. For $i = 0 To UBound($aArray) - 1 ; $i is automatically created and is set to zero, UBound($aArray) returns the no. of elements in the $aArray. ConsoleWrite($aArray[$i] & @CRLF) ; Prints the element out to the console. Next ; This is the advanced way, we use $i to access the elements! ; With the advanced method you can also use the Step keyword to increase the offset in each "step" of the loop: ; This will only print every 2nd element starting from 0 ConsoleWrite(@CRLF & "Every 2nd element: " & @CRLF) For $i = 0 To UBound($aArray) - 1 Step 2 ConsoleWrite($aArray[$i] & @CRLF) Next ; This will print the elements in reverse order! ConsoleWrite(@CRLF & "In reverse: " & @CRLF) For $i = UBound($aArray) - 1 To 0 Step -1 ConsoleWrite($aArray[$i] & @CRLF) Next ; And that ends this section! For some reason, many people use the advance way more than the simple way . For more examples of loops see this post by @FrancescoDiMuro!
      Interpreting Multi-Dimensional Arrays
      Yeah, its the most brain squeezing problem for newbies, Imagining an 3D Array... I will explain it in a very simple way for ya, so stop straining you brain now! . This way will work for any array regardless of its dimensions...
      Ok, Lets start... You can imagine an array as a (data) mine of information:

      ; Note that: ; Dimension = Level (except the ground level :P) ; Element in a Dimension = Path ; Level 2 ----------\ ; Level 1 -------\ | ; Level 0 ----\ | | ; v v v Local $aArray[2][2][2] ; \-----/ ; | ; v ; Ground Level ; As you can see that $aArray is the Ground Level ; All the elements start after the ground level, i.e from level 0 ; Level 0 Contains 2 different paths ; Level 1 Contains 4 different paths ; Level 2 Contains 8 different paths ; When you want too fill some data in the data mine, ; You can do that like this: $aArray[0][0][0] = 1 $aArray[0][0][1] = 2 $aArray[0][1][0] = 3 $aArray[0][1][1] = 4 $aArray[1][0][0] = 5 $aArray[1][0][1] = 6 $aArray[1][1][0] = 7 $aArray[1][1][1] = 8 ; Don't get confused with the 0s & 1s, Its just tracing the path! ; Try to trace the path of a number with the help of the image! Its super easy! :D I hope you might have understand how an array looks, Mapping your way through is the key in Multi-Dimensional arrays, You take the help of notepad if you want! Don't be shy!
      Frequently Asked Questions (FAQs) & Their answers
      Q #1. What are Arrays?
      A. An Array is an datatype of an variable (AutoIt has many datatypes of variables like "strings", "integers" etc. Array is one of them). An Array can store information in a orderly manner. An Array consist of elements, each element can be considered as a variable (and yes, each element has its own datatype!). AutoIt can handle 16,777,216 elements in an Array, If you have an Array with 16,777,217 elements then AutoIt crashes.
      Q #2. Help! I get an error while declaring an Array!?
      A. You tried to declare an array like this:
      $aArray[1] = ["Data"] That is not the right way, Array is a special datatype, since its elements can be considered as individual variables you must have an declarative keyword like Dim/Global/Local before the declaration, So this would work:
      Local $aArray[1] = ["Data"] Q #3. How can I calculate the no. of elements in an array?
      A. The UBound function is your answer, Its what exactly does! If you have an multi-dimensional Array you can calculate the total no. of elements in that dimension by specifying the dimension in the second parameter of UBound
      Q #4. Why is my For...Next loop throwing an error while processing an Array?
      A.  You might have done something like this:
      #include <MsgBoxConstants.au3> Local $aArray[10] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] Local $iMyNumber = 0 For $i = 0 To UBound($aArray) ; Concentrate here! $iMyNumber += $aArray[$i] Next MsgBox($MB_OK, "Sum of all Numbers!", $iMyNumber) Did you notice the mistake? UBound returns the no. of elements in an array with the index starting from 1! That's right, you need to remove 1 from the total no. of elements in order to process the array because the index of an array starts with 0! So append a simple - 1 to the statment:
      #include <MsgBoxConstants.au3> Local $aArray[10] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] Local $iMyNumber = 0 For $i = 0 To UBound($aArray) - 1 $iMyNumber += $aArray[$i] Next MsgBox($MB_OK, "Sum of all Numbers!", $iMyNumber) Q #5. Can an Array contain an Array? How do I access an Array within an Array?
      A. Yes! It is possible that an Array can contain another Array! Here is an example of an Array within an Array:
      ; An Array can contain another Array in one of its elements ; Let me show you an example of what I mean ;) #include <Array.au3> Global $aArray[2] $aArray[0] = "Foo" Global $aChildArray[1] = ["Bar"] $aArray[1] = $aChildArray _ArrayDisplay($aArray) ; Did you see that!? The 2nd element is an {Array} :O ; But how do we access it??? ; You almost guessed it, like this: ; Just envolope the element which contains the {Array} (as shown in _ArrayDisplay) with brackets (or parentheses)! :D ConsoleWrite(($aArray[1])[0]) ; NOTE the brackets () around $aArray[1]!!! They are required or you would get an syntax error! ; So this: $aArray[1][0] wont work!  
      More FAQs coming soon!
    • By Simpel
      When I click 'open this script' in AutoIt Help the example isn't opening. I tried this (FixHelpFileExamples.au3):
      All is set. But 'open this script' not working. I tried that (batchfile):
      This isn't working too.
      What I wonder if my mouse is over 'Copy to clipboard' my cursor is changing to a hand, showing there is a link. If I do the same over 'Open this Script' then mouse is showing the hand for very short time and then getting back to show the arrow. So if I move slowly the cursor over this link it's 'blinking' hand and arrow. What could this be?
      Regards, Conrad
    • By TheDcoder
      Hello Guys! . I have been busy with my exams... They are finished now, so summer holidays!
      I am been working very hard to bring back the reputation for AutoIt in IRC, I recently made a unofficial channel for AutoIt at freenode (freenode is a very popular IRC Network for FOSS [Free and Open Source Software]). You can check this topic if you want:

      This tutorial will guide you from start to finish covering each and every small step (no matter how small to make it more IRC newbie friendly) so that everyone can enjoy the benefits of IRC and the IRC Community. Please read the whole post for better understanding.
      Ok, lets begin our IRC adventure!
      Installing HexChat
      You might wonder why do you need HexChat, why not use the free and no installation needed online IRC client? Well, most online clients might be quick and easy to setup but don't offer much option and power, moreover they even show your IP in the public!
      For the above reason, we are using a neat desktop client called HexChat! (Its FOSS too!)
      Here are the steps you need to follow:
      1. As you might have expected, you need to download the installer first. Here is the link to the download page: http://hexchat.github.io/downloads.html. You need to select the best option for you, here are some pointers:

      2. After downloading the installer, install it... Here is a small video which I made to help you :
        Configuring HexChat
      This is the most important step in our journey, Configuration. After launching HexChat, it will prompt you to configure it, simply follow these steps:
      1. This is the initial window, find "freenode" in the "Networks" List:

      2. Select it and click "Favour" (optional but recommended).
      3. Change the values in the input boxes as you wish (I have set mine in the screenshot).
      4. Click edit and you will be prompted by a screen, click the "Autojoin channels" and add "##AutoIt" to it.

      5. Click "Close"
      6. Click "Connect" in the previous window and wait for it to automatically connect to ##AutoIt .
      7. Vola! You are done! You can now chat like blah blah blah.....

      Some extra optional work
      1. Type "/msg NickServ REGISTER <any password> <your email address>"
      2. Verify your email
      3. Open network manager by doing Ctrl + S
      4. Find freenode in the network list and click edit
      5. Enter your password and click "Close"
      6. Click on the "freenode" tab and enter this command: "/stats p". You will get a list of active staff members:

      7. Type "/query <nickname of the staff member> <message>"
      Replace <message> with a message asking for a "cloak", something like this would do the trick: "Hello, I want a cloak for account"
      8. Wait for the staff member to give you the cloak.
      That's it! You are done!
      End comments by the author of this tutorial
      I am glad that you are still reading until the end , You have just made a BIG contribution to freenode ##AutoIt IRC Community! Thank you very much for that
    • By Skysnake
      Several questions around the forum get asked repeatedly:
      How to avoid false-positive Anti-Virus detection? Answered by AutoIt god himself How to make AutoIt software safe from hacking? How to prevent AutoIt software being de-compiled? How to prevent exposure of native AutoIt code? The general answers all go in the direction of (a) can't be done or (b) make it an .a3x script.
      The Wiki contains a single entry under "compiler directives" and the Help File  contains mainly compiler info, with this note
      Also see this thread.
      So I thought I would make a little demo to actually show how it works.
      Here are the 2 scripts.  The a3x_demo.zip file contains these 2, plus the compiled .a3x file and the .EXE
      The body
      #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Outfile_type=a3x #AutoIt3Wrapper_Outfile=a3x_demo.a3x #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #cs ---------------------------------------------------------------------------- AutoIt Version: Author: Skysnake Script Function: Demonstates working of a3x Instructions Code as normal Set Compiler option to .a3x as per Help File Compile Note output is (a) .a3x file, (b) now compile wrapper to make .exe file The compiled .a3x is included inside the .exe. To demonstrate, copy .exe to any new location and run. :) #ce ---------------------------------------------------------------------------- ; Script Start #include <MsgBoxConstants.au3> MsgBox($MB_SYSTEMMODAL, "a3x demo", "This message box is called from an a3x pre-compiled script " & @CRLF & "will timeout after 10 seconds or select the OK button.", 10) ; code ends  
      The wrapper
      #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Outfile=a3x_wrapper.exe #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #cs ---------------------------------------------------------------------------- AutoIt Version: Author: Skysnake Script Function: Wrapper for .a3x demo the INCLUDE line below forces the .a3x to be included in the new .EXE other option is to use FileIsntall and then run the a3x_demo.a3x as an external file NOTE: required in order are the following steps 1. body .au3 script 2. compile body .au3 as .a3x file, include in wrapper 3. wrapper .au3 script, to become the .exe -> compile as .EXE #ce ---------------------------------------------------------------------------- ; Script Start - #include "a3x_demo.a3x" ; code ends DOWNLOAD: The ax3_demo.zip file
      2016.07.08 Fixed typos
  • Create New...