DiscGolferPro

[RESOLVED] I am running out of [something] as I get closer to creating 10,000 labels. Is this separate from the 65,535 objects allowed limit?

16 posts in this topic

#1 ·  Posted (edited)

[RESOLVED] There is a limit of 9999 ControlIDs, summed across all the controls that have been created, that can be created at any one time within a single script.

Mods can probably go ahead and lock this up.

Thanks everyone for looking into this! I went with the solution that only calls GUICtrlCreateLabel() half as often. This allowed me to keep a main grid of 48 rows by 80 columns while preserving the color highlights of the _CreateBorderLabel() function.

I have (sort of) cleaned up the 90° rotation of the first row (attached label_limit_10k_final.au3 below). The call to _WinAPI_CreateFont() within _GuiCtrlSetFont() rotates the text within the bounding box of a label. The final position of the text will depend on the width of the label containing the text, the length of the string, the font size, and the alignment assigned with $SS_% styles. When the length of your text string changes it makes the text "slide around" the limits of its displayed boundaries. See the function by funkey for a great visual:

Here is a final version of the file with the 90°CCW labels setup, albeit with identical and fixed-length strings in each column of row 1. Please modify and use to your heart's content.

DiscGolferPro

Original post follows:

_____________________________________________

Hi all! I have been an avid reader and have always found what I needed in the forums but this time I'm stumped.

I have created a GUI that sort of mimics the "Freeze Panes" functionality of Excel. Every 60 seconds, I will be tracking from 150 to 160 different interrelated elements (columns) that will change the values of each 30-minute interval slice (48 rows) remaining in the workday. These values will be sourced from another process that populates a SQLite database maintained by another script.

While I was tidying up the 90°CCW rotation of the first row I noticed that as I added more and more columns the script was starting to act strangely. When I went from 49 columns to 50 columns the secondary GUI was not being created, and as I tweaked the number of labels up and down I noticed that the script would stop at different points depending on [something] that seemed to have exhausted itself. The Menu>View>Docking would stop working in one instance, or the Stamp Log button would not respond in another, for example.

I have stripped out unneeded stuff and sprinkled the code with debug labels on the first two tabs. Each label needs 4x GUICtrlCreateLabel() calls so it currently is topping off at between approximately 9061 and 10043 labels.

My question is: Am I running out of [something] and have to re-design, or is there something I can modify to get to the approximately 31,000+ labels I will ultimately need?

To replicate the problem,

  • Run the script as it is and note that everything appears normally. The $skillsetColumnCount count is set at 45 in the variable declarations,
  • Toggle all folds closed (in SciTE) and open Func _tempOperationsLabels(), or navigate there manually,
  • Uncomment this part, which will increase columns to 50 and create a couple more labels to test with,
;~ ;;; Uncomment this and increase the number of $skillsetColumnCount to 50 to exhaust resources
;~ $skillsetColumnCount = 50
;~ $widthFlexScrollbar = $skillsetColumnCount * ($cellWidth + 8)
;~ ReDim $gridCellsContent[$intervalRowCount][$skillsetColumnCount]
;~ GUICtrlCreateLabel("Extra Label", 30, 640, 100, 20)
;~ $tempExtraLabel1 = GUICtrlCreateLabel("", 120, 640, 100, 20)
;~ $countExtraLabel1 += 2
;~ GUICtrlSetData($tempExtraLabel1, $countExtraLabel1)
;~ ;;; Uncomment this to increase the number of columns to 50 to exhaust resources
  • Re-run the script and notice the missing elements, no Destination GUI, Menu>View>Docking doesn't respond, column creation stops at column 33...
label_limit_10k.au3

Let me know if there are any questions I can clarify and thanks for the help!

JP

*Edit: Found the Edit button!

Here are Before and After shots that show how increasing the column count to 50 "stops" the _CreateSkillsetRow() function after creating only 33 column labels. The 'S33' label is placeholder text WITHIN the inner for loop and although the nested for loop DOES complete all iterations, it's as if the _CreateBorderLabel() function does not get called anymore after the 'S33' threshold is reached.

Before: 48 rows x 45 columns

Posted Image

After: 48 rows x 50 columns

Posted Image

label_limit_10k_final.au3

Edited by DiscGolferPro

Share this post


Link to post
Share on other sites

Links to Includes (I don't see an Edit button...)

Scrollbars:

String Size:

Share this post


Link to post
Share on other sites

I didn't look at your entire script, but how big a number is stored in $intervalRowCount?

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

I didn't look at your entire script, but how big a number is stored in $intervalRowCount?

The $intervalRowCount is 48 and will not change. It will represent the 48 slices of 30 minutes for every 24-hr day.

Global $intervalRowCount = 48, $intervalColumnCount = 1, $skillsetRowCount = 1, $skillsetColumnCount = 45

At 4 times GUICtrlCreateLabel() for EACH Formatted Label as created by the_CreateBorderLabel() call, that gives about:

Columns: 1*45 (x4 to format borders) = 180

Rows: 48*1 (x4 to format borders) = 192

Grid: 45*48 (x4 to format borders) = 8640

Debugging labels: about 50 calls

...for just over 9000 labels, everything works and responds correctly for these values.

Increasing the column count to 50*48 (x4) this bumps up the totals to just over 10000, and the application does not build out entirely.

Edited by DiscGolferPro

Share this post


Link to post
Share on other sites

DiscGolferPro,

I agree with your diagniosis - the maximum number of controls I can create is 9999. This means you can have 49 columns (9827 ControlIDs) but not 50 (10023 required and only 9999 created). I must say I have never seen a script with so many controls - you may well be the first ever to bump into this apparently undocumented limit! :o

As there seems no short-term fix to AutoIt itself that will solve your problem, it looks as if reducing the number of controls is your only recourse. You add 2400 labels to the total by creating 2 labels for each datapoint - for the "border" and the "data". Playing with your _CreateBorderLabel function to set the "data" label background colour to the "border" colour and not creating an additional "border" label allows the script to run with 50 columns - although it does mess up some of the other labels.

I will keep playing with the script during the day as time allows to see if I can come up with any other solutions. :)

M23

1 person likes this

Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

@DiscGolferPro

Since you're not listening for an event with the labels (as I've seen in your snippet), I suggest you to draw them with the GDI+ library.

It should be faster and take less CPU.

Br, FireFox.

2 people like this

 

OS : Win XP SP2 (32 bits) / Win 7 SP1 (64 bits) / Win 8 (64 bits) | Autoit version: latest stable / beta.
Hardware : Intel(R) Core(TM) i5-2400 CPU @ 3.10Ghz / 8 GiB RAM DDR3.

My UDFs : Skype UDF | TrayIconEx UDF | GUI Panel UDF | Excel XML UDF | Is_Pressed_UDF

My Projects : YouTube Multi-downloader | FTP Easy-UP | Lock'n | WinKill | AVICapture | Skype TM | Tap Maker | ShellNew | Scriptner | Const Replacer | FT_Pocket | Chrome theme maker

My Examples : Capture toolIP Camera | Crosshair | Draw Captured Region | Picture Screensaver | Jscreenfix | Drivetemp | Picture viewer

My Snippets : Basic TCP | Systray_GetIconIndex | Intercept End task | Winpcap various | Advanced HotKeySet | Transparent Edit control

 

Share this post


Link to post
Share on other sites

DiscGolferPro,

I agree with your diagniosis - the maximum number of controls I can create is 9999. This means you can have 49 columns (9827 ControlIDs) but not 50 (10023 required and only 9999 created). I must say I have never seen a script with so many controls - you may well be the first ever to bump into this apparently undocumented limit! :o

As there seems no short-term fix to AutoIt itself that will solve your problem, it looks as if reducing the number of controls is your only recourse. You add 2400 labels to the total by creating 2 labels for each datapoint - for the "border" and the "data". Playing with your _CreateBorderLabel function to set the "data" label background colour to the "border" colour and not creating an additional "border" label allows the script to run with 50 columns - although it does mess up some of the other labels.

I will keep playing with the script during the day as time allows to see if I can come up with any other solutions. :)

M23

Thanks for taking the time, M23. I will start to redesign a bit to maybe re-distribute the elements into the first 45 columns. Ideally though I'd love for all 160 columns to be available so the user can scroll the "aperture" through the much larger GUI field of 160x48 so the whole day's "hot spots" can be seen.

Either way, I'll be watching this thread. Thanks again!

Share this post


Link to post
Share on other sites

DiscGolferPro,

Just for completeness here is the modified function I used:

Func _CreateBorderLabel($sText, $iX, $iY, $iW, $iH, $iColor, $iPenSize = 1, $iStyle = -1, $iStyleEx = 0, $iType = 0)
    Switch $iType
        Case 0
            $internalLabelID1 = GUICtrlCreateLabel("", $iX - $iPenSize, $iY - $iPenSize, $iW + 2 * $iPenSize, $iH + 2 * $iPenSize, BitOR($SS_CENTER, $SS_CENTERIMAGE))
            GUICtrlSetBkColor(-1, $iColor)
            $internalLabelID2 = GUICtrlCreateLabel($sText, $iX, $iY, $iW, $iH, BitOR($SS_CENTER, $SS_CENTERIMAGE), $iStyleEx)
            GUICtrlSetBkColor(-1, $COLOR_WHITE)
        Case 1
            $internalLabelID2 = GUICtrlCreateLabel($sText, $iX, $iY, $iW, $iH, BitOR($SS_CENTER, $SS_CENTERIMAGE), $iStyleEx)
            GUICtrlSetBkColor(-1, $iColor)
    EndSwitch
    Return $internalLabelID2
EndFunc   ;==>_CreateBorderLabel

And I amended the calls in _InitializeIntervalGrid as follows:

_CreateBorderLabel($gridCellsContent[$r - 1][$c - 1], _
        (($c - 1) * ($cellWidth + $cellLeftOffset)) + $cellLeftOffset - 2, _
        (($r - 1) * ($cellHeight + $cellTopOffset)) + $cellTopOffset - 2, _
        $cellWidth + 4, $cellHeight + 4, $COLOR_MEDGRAY, 1, BitOR($SS_CENTER, $SS_CENTERIMAGE), 0, 1) ; <<<<<<<
$countGridLabels += 2
_CreateBorderLabel($gridCellsContent[$r - 1][$c - 1], _
        (($c - 1) * ($cellWidth + $cellLeftOffset)) + $cellLeftOffset, _
        (($r - 1) * ($cellHeight + $cellTopOffset)) + $cellTopOffset, _
        $cellWidth, $cellHeight, $penColor, $penWeight, BitOR($SS_CENTER, $SS_CENTERIMAGE), 0, 1) ; <<<<<<<
$countGridLabels += 2

This way I only create 5223 controls and the whole grid appears. :)

M23

1 person likes this

Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

@DiscGolferPro

Since you're not listening for an event with the labels (as I've seen in your snippet), I suggest you to draw them with the GDI+ library.

It should be faster and take less CPU.

Br, FireFox.

Yes, I think I will need go this route to recuperate some of the underutilized $COLOR_MEDGRAY border labels. I will in fact need the other fully-fledged labels to generate events to drive stats in the DestinationGUI (on the right) so the user can determine why that particular interval/skillset cell is not conforming to pre-established thresholds. Each square will reach into the database and pull all the relevant data which is why the entire grid should be a visual (in addition to a quantitative) trigger system to tell them something is out of compliance.

I might need your expertise soon too! Thanks!

:construction:

Share this post


Link to post
Share on other sites

@DiscGolferPro

Since you're not listening for an event with the labels (as I've seen in your snippet), I suggest you to draw them with the GDI+ library.

It should be faster and take less CPU.

Br, FireFox.

Smart workaround there FireFox =D

1 person likes this

Spoiler

“Hello, ladies, look at your man, now back to me, now back at your man, now back to me. Sadly, he isn’t me, but if he stopped using ladies scented body wash and switched to Old Spice, he could smell like he’s me. Look down, back up, where are you? You’re on a boat with the man your man could smell like. What’s in your hand, back at me. I have it, it’s an oyster with two tickets to that thing you love. Look again, the tickets are now diamonds. Anything is possible when your man smells like Old Spice and not a lady. I’m on a horse.”

 

Share this post


Link to post
Share on other sites

I wonder if using edit controls, created using _GUICtrlEdit_Create, rather than native label controls would affect anything? This way you're not using AutoIt control ids, but using Window's handles for the controls.

I know that when _ArrayDisplay went from using the UDF listview control, to a native AutoIt control, the function stopped displaying any array elements over 65,000 or so because you run out of control IDs at that point.

1 person likes this

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Share this post


Link to post
Share on other sites

Here is attached a fast-made edit with GDIPlus. I don't know how to prevent the graphic from being erased on scroll, I let the others to take a look at it.

label_limit_10k.au3

1 person likes this

 

OS : Win XP SP2 (32 bits) / Win 7 SP1 (64 bits) / Win 8 (64 bits) | Autoit version: latest stable / beta.
Hardware : Intel(R) Core(TM) i5-2400 CPU @ 3.10Ghz / 8 GiB RAM DDR3.

My UDFs : Skype UDF | TrayIconEx UDF | GUI Panel UDF | Excel XML UDF | Is_Pressed_UDF

My Projects : YouTube Multi-downloader | FTP Easy-UP | Lock'n | WinKill | AVICapture | Skype TM | Tap Maker | ShellNew | Scriptner | Const Replacer | FT_Pocket | Chrome theme maker

My Examples : Capture toolIP Camera | Crosshair | Draw Captured Region | Picture Screensaver | Jscreenfix | Drivetemp | Picture viewer

My Snippets : Basic TCP | Systray_GetIconIndex | Intercept End task | Winpcap various | Advanced HotKeySet | Transparent Edit control

 

Share this post


Link to post
Share on other sites

I appreciate the attention that is being brought to bear on my little problem! I posted here in the hopes that someone would look at it by the time I get back home next Tuesday and now I have a bounty of ideas to look through just a day later.

I am out of town for a few days so if you don't get any news from me for a few days you can still be sure that I'm looking at these answers from a public internet and I can't wait to try out the ideas!

Thanks!

Disc

Share this post


Link to post
Share on other sites

#14 ·  Posted (edited)

I wonder if using edit controls, created using _GUICtrlEdit_Create, rather than native label controls would affect anything? This way you're not using AutoIt control ids, but using Window's handles for the controls.

I know that when _ArrayDisplay went from using the UDF listview control, to a native AutoIt control, the function stopped displaying any array elements over 65,000 or so because you run out of control IDs at that point.

I will have to look at this also.

The initial appeal of the _CreateBorderLabel function was the visual queues I could incorporate (heavy green, light green, neutral, light red, heavy red) into the borders. In addition to the background color changes to the cell itself (red fill and green fill with white text for the font) I was hoping to get 7 levels of "information" for how each specific interval/skillet was doing. I will try to preserve this level of information as we develop the final GUI.

Disc

*Edit: I can write up a brief description of how I'm using this grid if it will help but, in a nutshell, this will help me manage how closely our Workforce Management forecasts are coming to the staffing requirements for every inbound customer service phone skillset we have at every interval during the current day.

Edited by DiscGolferPro

Share this post


Link to post
Share on other sites

Well, here's something anyway. You need to redraw everything on WM_PAINT. I've added some things too, like double buffering. But the biggest thing is to only actually draw what is visible. You'll need to determine that for real, as mine is only an example.

Scrolling still kinda sucks though... you might be better served trying to create the grid in a ListView, and using some custom color UDFs to color the cells.

; ==============================================================================================================================
;
; Program Name: OMNiViewer
;
; AutoIt Version:  3.3.8.1
; Language:        English
; Platform:        Win9x/NT
; Author:          JP Spampinato (jpspampinato@yahoo.com)
;
$version = "OMNiViewer 0.2a"
; ==============================================================================================================================

#region Includes, Variables
#include <Date.au3>
#include <GuiTab.au3>
#include <Timers.au3>
#include <Excel.au3>
#include <GuiScrollBars.au3>
#include <GUIScrollbars_Ex.au3>
#include <ScrollBarConstants.au3>
#include <Constants.au3>
#include <EditConstants.au3>
#include <WindowsConstants.au3>
#include <WinAPI.au3>
#include <GUIConstantsEx.au3>
#include <ColorConstants.au3>
#include <StaticConstants.au3>
#include <StringSize.au3>

#include <GDIPlus.au3>

Opt('MustDeclareVars', 1)
Opt("GUICloseOnEsc", 0)
OnAutoItExitRegister("_FontCleanUp")

Global $ahFontEx[1] = [0]
Global $TabMainControl, $TabOperations, $TabTriggers, $TabReporting, $sTabNowDisplaying
Global $MenuFile, $MenuFileOpen, $MenuFileLoadLoginIDs, $MenuFileLoadSave, $MenuFileExit
Global $MenuView, $MenuViewDocking, $MenuViewDockingDocked, $MenuViewDockingSideSide, $MenuViewDockingTopBot, $MenuViewStatusbar
Global $MenuHelp, $MenuHelpAbout, $MenuHelpOMNi, $MenuHelpReleaseNotes
Global $EditLogWindow
Global $ButtonStampLog
Global $LabelStatusMain, $LabelStatusDest
Global $sStatusMessageMain = " Ready", $sStatusMessageDest = " Ready"
Global $stylesStatusbar = BitOR($SS_SIMPLE, $SS_SUNKEN), $stylesDestinationWindow = BitOR($WS_POPUP, $WS_CAPTION)
Global $Run = 0, $Dock = 1, $Dock_Location = 1, $msg, $x1, $x2, $y1, $y2 ; for the Docking() group of functions
Global $internalLabelID1, $internalLabelID2
Global $oExcel = 0, $sFile
Global $sSourceDirecory = "\\Desktop\OMNi\"

; why are we running out of resources? can't create the logging GUI if we add too many Skillsets ?
Global $dIntervalDateSetup = _NowCalcDate() & " 00:00:00"
Global $hMainWindow, $hDestinationWindow, $hFlexGrid, $hIntervalsColumn, $hSkillsetsRow
Global $intervalRowCount = 48, $intervalColumnCount = 1, $skillsetRowCount = 1, $skillsetColumnCount = 45
Global $countGridLabels = 0, $countIntervalLabels = 0, $countSkillsetLabels = 0, $countOtherLabels = 0, $totalLabels = 0, $countExtraLabel1 = 0
Global $cellWidth = 30, $cellHeight = 20, $penWeight = 1, $penColor
Global $cellLeftOffset = 8, $cellTopOffset = 8, $barThickness = 20
Global $heightMain = 720, $widthMain = 1280
Global $mainLeftOffset = 100, $mainTopOffset = 100
Global $heightDest = 720, $widthDest = 320
Global $heightFlexGrid = 560, $widthFlexGrid = 1000
Global $flexLeftOffset = $widthMain - $widthFlexGrid - $barThickness + 8, $flexTopOffset = $heightMain - $heightFlexGrid - ($barThickness * 2) - 8
Global $heightIntervals = $heightFlexGrid, $widthIntervals = ($cellWidth * 2) + 2
Global $intervalsLeftOffset = $flexLeftOffset - ($barThickness * 2) - 2, $intervalsTopOffset = $flexTopOffset
Global $heightSkillsets = $cellHeight * 5, $widthSkillsets = $widthFlexGrid
Global $skillsetsLeftOffset = $flexLeftOffset, $skillsetsTopOffset = $flexTopOffset - ($barThickness * 4) - 2
Global $heightFlexScrollbar = $intervalRowCount * ($cellHeight + 8), $widthFlexScrollbar = $skillsetColumnCount * ($cellWidth + 8)
Global $gridCellsContent[$intervalRowCount][$skillsetColumnCount], $tempGrid[1][1], $tempSkillsetContent[1][1]
Global $otherLabel1, $otherLabel2, $otherLabel3, $otherLabel4, $otherLabel5, $otherLabel6, $tempScroll1, $tempScroll2
Global $tempLabel1, $tempLabel2, $tempLabel3, $tempLabel4, $tempLabel5, $tempLabel6, $tempExtraLabel1
Global $tempMeasurements1, $tempMeasurements2, $tempMeasurements3, $tempMeasurements4
Global $tempMeasurements5, $tempMeasurements6, $tempMeasurements7, $tempMeasurements8
Global $tempMeasurements9, $tempMeasurements10, $tempMeasurements11, $tempMeasurements12
; why are we running out of resources? can't create the logging GUI if we add too many Skillsets ?
#endregion Includes, Variables

#region Setup GUI, Menus, Tabs, and Grid Definitions
$hMainWindow = GUICreate($version, $widthMain, $heightMain, $mainLeftOffset, $mainTopOffset)

#region Setup Menus
$MenuFile = GUICtrlCreateMenu("&File")
$MenuFileOpen = GUICtrlCreateMenuItem("Open...", $MenuFile)
GUICtrlSetState(-1, $GUI_DEFBUTTON)
GUICtrlCreateMenuItem("", $MenuFile)
$MenuFileLoadLoginIDs = GUICtrlCreateMenuItem("Load LoginID data for all agents", $MenuFile)
GUICtrlCreateMenuItem("", $MenuFile)
$MenuFileLoadSave = GUICtrlCreateMenuItem("Save", $MenuFile)
GUICtrlSetState(-1, $GUI_DISABLE)
$MenuFileExit = GUICtrlCreateMenuItem("Exit", $MenuFile)

$MenuView = GUICtrlCreateMenu("&View")
$MenuViewDocking = GUICtrlCreateMenu("Docking", $MenuView)
$MenuViewDockingDocked = GUICtrlCreateMenuItem("Docked", $MenuViewDocking)
GUICtrlCreateMenuItem("", $MenuViewDocking)
$MenuViewDockingSideSide = GUICtrlCreateMenuItem("Side By Side", $MenuViewDocking)
$MenuViewDockingTopBot = GUICtrlCreateMenuItem("Top And Bottom", $MenuViewDocking)
GUICtrlSetState($MenuViewDockingDocked, $GUI_CHECKED)
GUICtrlSetState($MenuViewDockingSideSide, $GUI_CHECKED)
GUICtrlCreateMenuItem("", $MenuView)
$MenuViewStatusbar = GUICtrlCreateMenuItem("Statusbar", $MenuView)
GUICtrlSetState(-1, $GUI_CHECKED)

$MenuHelp = GUICtrlCreateMenu("&Help")
$MenuHelpOMNi = GUICtrlCreateMenuItem("Usage", $MenuHelp)
$MenuHelpReleaseNotes = GUICtrlCreateMenuItem("Release Notes", $MenuHelp)
GUICtrlCreateMenuItem("", $MenuHelp)
$MenuHelpAbout = GUICtrlCreateMenuItem("About " & $version, $MenuHelp)
$LabelStatusMain = GUICtrlCreateLabel($sStatusMessageMain, 0, $heightMain - 36, $widthMain, 16, $stylesStatusbar)
GUICtrlSetBkColor(-1, 0x80ff80)
GUICtrlSetState($LabelStatusMain, $GUI_SHOW)
#endregion Setup Menus

#region Setup Tabs
$TabMainControl = GUICtrlCreateTab(2, 2, $widthMain - 4, $heightMain - 20 - 20)

$TabOperations = GUICtrlCreateTabItem("Operational Grid")
_tempOperationsLabels()

$TabTriggers = GUICtrlCreateTabItem("Triggers")
_tempTriggersLabels()

$TabReporting = GUICtrlCreateTabItem("Reporting")
GUICtrlCreateTabItem("")

GUISetState(@SW_SHOW, $hMainWindow)
#endregion Setup Tabs

#region GDIPlus
_GDIPlus_Startup()
#endregion

#region Setup Flex Grid
GUISwitch($hMainWindow, $TabOperations)
$hFlexGrid = GUICreate("", $widthFlexGrid, $heightFlexGrid, $flexLeftOffset, $flexTopOffset, $WS_POPUP, $WS_EX_MDICHILD, $hMainWindow)
GUISetBkColor($COLOR_SILVER, $hFlexGrid)

_GUIScrollbars_Generate($hFlexGrid, $widthFlexScrollbar + $barThickness + $skillsetColumnCount, $heightFlexScrollbar + $barThickness + $intervalRowCount, True)
GUISetState(@SW_SHOW, $hFlexGrid)

Global Const $hPen_COLORRED = _GDIPlus_PenCreate(BitOR(0xFF000000, $COLOR_RED))
Global Const $hPen_COLORWHITE = _GDIPlus_PenCreate(BitOR(0xFF000000, $COLOR_WHITE))
Global Const $hPen_COLORGREEN = _GDIPlus_PenCreate(BitOR(0xFF000000, $COLOR_GREEN))
Global Const $hPen_COLORMEDGRAY = _GDIPlus_PenCreate(BitOR(0xFF000000, $COLOR_MEDGRAY))

Global Const $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hFlexGrid)
; double buffer
Global $hBMP = _WinAPI_CreateBitmap($widthFlexGrid, $heightFlexGrid, 1, 32)
Global $hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBMP)
Global $hGraphics2 = _GDIPlus_ImageGetGraphicsContext($hImage)

_InitializeIntervalGrid()

$hIntervalsColumn = GUICreate("", $widthIntervals, $heightIntervals, $intervalsLeftOffset, $intervalsTopOffset, $WS_POPUP, $WS_EX_MDICHILD, $hMainWindow)
_GUIScrollbars_Generate($hIntervalsColumn, 0, $heightFlexScrollbar + $barThickness + $intervalRowCount, True)
;~ _CreateIntervalColumn()
GUISetBkColor($COLOR_SILVER, $hIntervalsColumn)
GUISetState(@SW_SHOW, $hIntervalsColumn)

$hSkillsetsRow = GUICreate("", $widthSkillsets, $heightSkillsets, $skillsetsLeftOffset, $skillsetsTopOffset, $WS_POPUP, $WS_EX_MDICHILD, $hMainWindow)
_GUIScrollbars_Generate($hSkillsetsRow, $widthFlexScrollbar + $barThickness + $skillsetColumnCount, 0, True)
;~ _CreateSkillsetRow()
GUISetBkColor($COLOR_SILVER, $hSkillsetsRow)
GUISetState(@SW_SHOW, $hSkillsetsRow)
#endregion Setup Flex Grid

#region Setup Destination GUI
$hDestinationWindow = GUICreate("", $widthDest, $heightDest, $widthMain + $mainLeftOffset, $mainTopOffset, $stylesDestinationWindow)
$EditLogWindow = GUICtrlCreateEdit("", 2, 42, ($widthDest) - 6, $heightDest - 112, BitOR($WS_HSCROLL, $WS_VSCROLL))
$ButtonStampLog = GUICtrlCreateButton("Stamp Log", 70, $heightDest - 50, 100, 25)
$LabelStatusDest = GUICtrlCreateLabel($sStatusMessageDest, 0, $heightDest - 16, $widthDest, 16, $stylesStatusbar)
GUISetState(@SW_SHOW, $hDestinationWindow)
#endregion Setup Destination GUI
#endregion Setup GUI, Menus, Tabs, and Grid Definitions

#region Message Handlers
;~ GUIRegisterMsg($WM_COMMAND, "_WM_COMMAND") ; Declare Command message handler
GUIRegisterMsg($WM_MOVE, "_WM_MOVE") ; Declare WindowIsMoving message handler
GUIRegisterMsg($WM_NOTIFY, "_WM_NOTIFY") ; Declare Notify message handler
GUIRegisterMsg($WM_VSCROLL, "WM_VSCROLL")
GUIRegisterMsg($WM_HSCROLL, "WM_HSCROLL")
GUIRegisterMsg($WM_PAINT, "WM_PAINT")
#endregion Message Handlers

#region Timers
_Timer_SetTimer($hMainWindow, 1000, "_UpdateStatusBarClock")
#endregion Timers

#region MAIN
; ==============================================================================================================================
;~ _LocateEveryTrackingWindow()
;~ _OpenDatabase()
;~ _LoadRulesets()
;~ _TestUpdateSpeed()
$Run = 1 ; Ready to run

While 1
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; How many labels are we going through? ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    If $countGridLabels + $countSkillsetLabels + $countIntervalLabels + $countOtherLabels + $countExtraLabel1 <> $totalLabels Then
        GUICtrlSetData($tempLabel2, $countGridLabels)
        GUICtrlSetData($tempLabel3, $countSkillsetLabels)
        GUICtrlSetData($tempLabel4, $countIntervalLabels)
        GUICtrlSetData($tempLabel5, $countOtherLabels)
        $totalLabels = $countGridLabels + $countSkillsetLabels + $countIntervalLabels + $countOtherLabels + $countExtraLabel1
        GUICtrlSetData($tempLabel6, $totalLabels)
        GUICtrlSetData($tempExtraLabel1, $countExtraLabel1)
    EndIf
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; How many labels are we going through? ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    $msg = GUIGetMsg()
    Select
;~      Case $msg = $MenuFileLoadLoginIDs
;~          _LoadLoginIDs()
        Case $msg = $ButtonStampLog
            _WriteToLogWindow("(" & @HOUR & ":" & @MIN & ":" & @SEC & ") " & "Sample: Process Update123 completed")
        Case $msg = $TabMainControl
            $sTabNowDisplaying = _TabIsNowDisplaying()
            If ($sTabNowDisplaying = "Triggers" Or $sTabNowDisplaying = "Reporting") Then
                GUISetState(@SW_HIDE, $hFlexGrid)
                GUISetState(@SW_HIDE, $hIntervalsColumn)
                GUISetState(@SW_HIDE, $hSkillsetsRow)
            Else
                GUISetState(@SW_SHOW, $hFlexGrid)
                GUISetState(@SW_SHOW, $hIntervalsColumn)
                GUISetState(@SW_SHOW, $hSkillsetsRow)
            EndIf
        Case $msg = $MenuViewStatusbar
            _ToggleStatus()
        Case $msg = $MenuViewDockingDocked
            _SetDocking()
        Case $msg = $MenuViewDockingSideSide
            _SetDockSideBySide()
        Case $msg = $MenuViewDockingTopBot
            _SetDockTopAndBottom()
            ;       Case $msg = $MenuHelpAbout
            ;           _HelpAboutOMNiMonitor()
        Case $msg = $GUI_EVENT_CLOSE Or $msg = $MenuFileExit
            ExitLoop
    EndSelect
    _WinAPI_SetWindowPos($hFlexGrid, $HWND_TOP, 0, 0, 0, 0, BitOR($SWP_NOMOVE, $SWP_NOSIZE, $SWP_NOACTIVATE))
WEnd

GUIDelete()
_SaveAndExit()
#endregion MAIN

; ==============================================================================================================================
Func _InitializeIntervalGrid()
    _GDIPlus_GraphicsClear($hGraphics2, BitOR(0xFF000000, $COLOR_MEDGRAY))

;~     For $c = 1 To $skillsetColumnCount
;~      For $r = 1 To $intervalRowCount

    ; only draw visible cells
    ; this is an example, but you need to determine what exactly is visible
    Local $rows = Ceiling($widthFlexGrid / ($cellWidth + $cellLeftOffset))
    Local $columns = Ceiling($heightFlexGrid / ($cellHeight + $cellTopOffset))

    For $c = 1 To $rows
        For $r = 1 To $columns
            $penWeight = Random(1, 2, 1)
            If Random() < 0.5 Then ; Format cells placeholders randomly distributed
                $penColor = $hPen_COLORRED
                If $penWeight = 1 Then
                    If Random() < 0.5 Then
                        $penColor = $hPen_COLORWHITE
                    EndIf
                EndIf
            Else
                $penColor = $hPen_COLORGREEN
                If $penWeight = 1 Then
                    If Random() < 0.5 Then
                        $penColor = $hPen_COLORWHITE
                    EndIf
                EndIf
            EndIf
;~          ; Uncomment one of these to fill up the cells with placeholders
;~          $gridCellsContent[$r - 1][$c - 1] = Random(-9, 9, 1) & " " & Random(-9, 9, 1) ; actuals and deltas placeholder
;~          $gridCellsContent[$r - 1][$c - 1] = $c & " " & Random(-9, 9, 1) ; enumerate columns
;~          $gridCellsContent[$r - 1][$c - 1] = Random(-9, 9, 1) & " " & $r ; enumerate rows
            $gridCellsContent[$r - 1][$c - 1] = $r & " " & $c ; enumerate rows + columns
            _CreateBorderLabel2($gridCellsContent[$r - 1][$c - 1], _
                    (($c - 1) * ($cellWidth + $cellLeftOffset)) + $cellLeftOffset - 2, _
                    (($r - 1) * ($cellHeight + $cellTopOffset)) + $cellTopOffset - 2, _
                    $cellWidth + 4, $cellHeight + 4, $hPen_COLORMEDGRAY, 1)
            _CreateBorderLabel2("", _
                    (($c - 1) * ($cellWidth + $cellLeftOffset)) + $cellLeftOffset, _
                    (($r - 1) * ($cellHeight + $cellTopOffset)) + $cellTopOffset, _
                    $cellWidth, $cellHeight, $penColor, $penWeight)
        Next
    Next

    ; draw buffered image to GUI
    _GDIPlus_GraphicsDrawImage($hGraphics, $hImage, 0, 0)
EndFunc   ;==>_InitializeIntervalGrid

; ==============================================================================================================================
Func _CreateIntervalColumn()
    Local $tempRC = $intervalRowCount
    Local $tempCC = $intervalColumnCount
    ReDim $tempGrid[$tempRC][$tempCC]

    $penColor = $COLOR_BLACK
    $penWeight = 2

    For $c = 1 To $intervalColumnCount
        For $r = 1 To $intervalRowCount
            $tempGrid[$r - 1][$c - 1] = _DateTimeFormat($dIntervalDateSetup, 4) ; Interval placeholder
            $dIntervalDateSetup = _DateAdd('n', 30, $dIntervalDateSetup)
            _CreateBorderLabel($tempGrid[$r - 1][$c - 1], _
                    (($c - 1) * ($cellWidth + $cellLeftOffset)) + $cellLeftOffset - 2, _
                    (($r - 1) * ($cellHeight + $cellTopOffset)) + $cellTopOffset - 2, _
                    $cellWidth + 4, ($cellHeight - 1) + 4, $COLOR_MEDGRAY, 1, BitOR($SS_CENTER, $SS_CENTERIMAGE))
            $countIntervalLabels += 2
            _CreateBorderLabel($tempGrid[$r - 1][$c - 1], _
                    (($c - 1) * ($cellWidth + $cellLeftOffset)) + $cellLeftOffset, _
                    (($r - 1) * ($cellHeight + $cellTopOffset)) + $cellTopOffset, _
                    $cellWidth, ($cellHeight - 1), $penColor, $penWeight, BitOR($SS_CENTER, $SS_CENTERIMAGE))
            $countIntervalLabels += 2
        Next
    Next
EndFunc   ;==>_CreateIntervalColumn

; ==============================================================================================================================
Func _CreateSkillsetRow()
    Local $tempRC = $skillsetRowCount
    Local $tempCC = $skillsetColumnCount
    ReDim $tempGrid[$tempRC][$tempCC]
    ReDim $tempSkillsetContent[$tempRC][$tempCC]
    $penColor = $COLOR_BLACK
    $penWeight = 2
    Local $tempSizeSkillset1 = "Skillset1", $aSizeSkillset
    $aSizeSkillset = _StringSize($tempSizeSkillset1, Default, Default, Default, Default, 200)

    ______DebugPrint______("W: " & $cellWidth & " H: " & (($cellHeight - 3) * 4) & " L: " & $cellLeftOffset & " T: " & $cellTopOffset & " --- " & _
            "array0:" & $aSizeSkillset[0] & " array1:" & $aSizeSkillset[1] & " array2:" & $aSizeSkillset[2] & " array3:" & $aSizeSkillset[3])
    For $c = 1 To $skillsetColumnCount
        For $r = 1 To $skillsetRowCount
            $tempGrid[$r - 1][$c - 1] = "S" & $c
            _CreateBorderLabel($tempGrid[$r - 1][$c - 1], _
                    (($c - 1) * ($cellWidth + $cellLeftOffset)) + $cellLeftOffset - 2, _
                    (($r - 1) * ($cellHeight + $cellTopOffset)) + $cellTopOffset - 2, _
                    $cellWidth + 4, (($cellHeight - 3) * 4) + 4, $COLOR_MEDGRAY, 1, BitOR($SS_CENTER, $SS_CENTERIMAGE))
            $countSkillsetLabels += 2
            $tempSkillsetContent[$r - 1][$c - 1] = _CreateBorderLabel($tempGrid[$r - 1][$c - 1], _
                    (($c - 1) * ($cellWidth + $cellLeftOffset)) + $cellLeftOffset, _
                    (($r - 1) * ($cellHeight + $cellTopOffset)) + $cellTopOffset, _
                    $cellWidth, (($cellHeight - 3) * 4), $penColor, $penWeight, BitOR($SS_CENTER, $SS_CENTERIMAGE))
            $countSkillsetLabels += 2
            GUICtrlSetData($tempSkillsetContent[$r - 1][$c - 1], "AB1234")
            _GuiCtrlSetFont($tempSkillsetContent[$r - 1][$c - 1], 15, 400, 0, ($c * 2))
        Next
    Next
EndFunc   ;==>_CreateSkillsetRow

; ==============================================================================================================================
Func _tempTriggersLabels()
    $otherLabel1 = _CreateBorderLabel("LABEL1", 30, 400, 100, 200, $COLOR_RED, 2)
    $countOtherLabels += 2
    $otherLabel2 = _CreateBorderLabel("LABEL2", 30, 550, 80, 20, $COLOR_BLUE, 2, BitOR($SS_CENTER, $SS_CENTERIMAGE))
    $countOtherLabels += 2
    GUICtrlSetData($otherLabel1, "Label11")
    _GuiCtrlSetFont($otherLabel1, 15, 400, 0, 90)
    $otherLabel3 = GUICtrlCreateLabel("LABEL3", 30, 150, 80, 20, BitOR($SS_CENTER, $SS_CENTERIMAGE, $SS_SUNKEN))
    $countOtherLabels += 2
    ;;;                                         Left - Top - Width - Height
    $otherLabel4 = GUICtrlCreateLabel("1234567890", 30, 250, 140, 140, BitOR($WS_BORDER, $SS_RIGHT, $SS_CENTERIMAGE))
    GUICtrlSetData($otherLabel4, "abcdefghij")
    _GuiCtrlSetFont($otherLabel4, 15, 400, 0, 90)
    $otherLabel5 = GUICtrlCreateLabel("1234567890", 230, 250, 100, 100, BitOR($WS_BORDER, $SS_RIGHT, $SS_CENTERIMAGE))
    GUICtrlSetData($otherLabel5, "abcdefghij")
    _GuiCtrlSetFont($otherLabel5, 15, 400, 0, 90)
    $otherLabel6 = GUICtrlCreateLabel("12345", 430, 250, 100, 100, BitOR($WS_BORDER, $SS_RIGHT, $SS_CENTERIMAGE))
    GUICtrlSetData($otherLabel6, "abcde")
    _GuiCtrlSetFont($otherLabel6, 15, 400, 0, 90)
    $countOtherLabels += 2
EndFunc   ;==>_tempTriggersLabels

; ==============================================================================================================================
Func _tempOperationsLabels()
    GUICtrlCreateLabel("Grid GUI", 30, 80, 100, 20)
    GUICtrlCreateLabel("Width", 30, 100, 100, 20)
    $tempMeasurements1 = GUICtrlCreateLabel("", 120, 100, 100, 20)
    GUICtrlSetData($tempMeasurements1, $widthFlexGrid)
    GUICtrlCreateLabel("Height", 30, 115, 100, 20)
    $tempMeasurements2 = GUICtrlCreateLabel("", 120, 115, 100, 20)
    GUICtrlSetData($tempMeasurements2, $heightFlexGrid)
    GUICtrlCreateLabel("Top offset", 30, 130, 100, 20)
    $tempMeasurements3 = GUICtrlCreateLabel("", 120, 130, 100, 20)
    GUICtrlSetData($tempMeasurements3, $flexTopOffset)
    GUICtrlCreateLabel("Left offset", 30, 145, 100, 20)
    $tempMeasurements4 = GUICtrlCreateLabel("", 120, 145, 100, 20)
    GUICtrlSetData($tempMeasurements4, $flexLeftOffset)

    GUICtrlCreateLabel("Interval GUI", 30, 180, 100, 20)
    GUICtrlCreateLabel("Width", 30, 200, 100, 20)
    $tempMeasurements5 = GUICtrlCreateLabel("", 120, 200, 100, 20)
    GUICtrlSetData($tempMeasurements5, $widthIntervals)
    GUICtrlCreateLabel("Height", 30, 215, 100, 20)
    $tempMeasurements6 = GUICtrlCreateLabel("", 120, 215, 100, 20)
    GUICtrlSetData($tempMeasurements6, $heightIntervals)
    GUICtrlCreateLabel("Top offset", 30, 230, 100, 20)
    $tempMeasurements7 = GUICtrlCreateLabel("", 120, 230, 100, 20)
    GUICtrlSetData($tempMeasurements7, $intervalsTopOffset)
    GUICtrlCreateLabel("Left offset", 30, 245, 100, 20)
    $tempMeasurements8 = GUICtrlCreateLabel("", 120, 245, 100, 20)
    GUICtrlSetData($tempMeasurements8, $intervalsLeftOffset)

    GUICtrlCreateLabel("Skillset GUI", 30, 280, 100, 20)
    GUICtrlCreateLabel("Width", 30, 300, 100, 20)
    $tempMeasurements9 = GUICtrlCreateLabel("", 120, 300, 100, 20)
    GUICtrlSetData($tempMeasurements9, $widthSkillsets)
    GUICtrlCreateLabel("Height", 30, 315, 100, 20)
    $tempMeasurements10 = GUICtrlCreateLabel("", 120, 315, 100, 20)
    GUICtrlSetData($tempMeasurements10, $heightSkillsets)
    GUICtrlCreateLabel("Top offset", 30, 330, 100, 20)
    $tempMeasurements11 = GUICtrlCreateLabel("", 120, 330, 100, 20)
    GUICtrlSetData($tempMeasurements11, $skillsetsTopOffset)
    GUICtrlCreateLabel("Left offset", 30, 345, 100, 20)
    $tempMeasurements12 = GUICtrlCreateLabel("", 120, 345, 100, 20)
    GUICtrlSetData($tempMeasurements12, $skillsetsLeftOffset)

    GUICtrlCreateLabel("H-Scroll position", 30, 460, 100, 20)
    $tempScroll1 = GUICtrlCreateLabel("", 120, 460, 100, 20)
    GUICtrlCreateLabel("V-Scroll position", 30, 480, 100, 20)
    $tempScroll2 = GUICtrlCreateLabel("", 120, 480, 100, 20)
    GUICtrlCreateLabel("gridLabels", 30, 520, 100, 20)
    $tempLabel2 = GUICtrlCreateLabel("", 120, 520, 50, 20)
    GUICtrlCreateLabel("skillsetLabels", 30, 540, 100, 20)
    $tempLabel3 = GUICtrlCreateLabel("", 120, 540, 50, 20)
    GUICtrlCreateLabel("intervalLabels", 30, 560, 100, 20)
    $tempLabel4 = GUICtrlCreateLabel("", 120, 560, 50, 20)
    GUICtrlCreateLabel("otherLabels", 30, 580, 100, 20)
    $tempLabel5 = GUICtrlCreateLabel("", 120, 580, 50, 20)
    GUICtrlCreateLabel("totalLabels", 30, 600, 100, 20)
    $tempLabel6 = GUICtrlCreateLabel("", 120, 600, 50, 20)
    $countOtherLabels += 41

;~  ;;; Uncomment this and increase the number of $skillsetColumnCount to 50 to exhaust resources
;~  $skillsetColumnCount = 50
;~  $widthFlexScrollbar = $skillsetColumnCount * ($cellWidth + 8)
;~  ReDim $gridCellsContent[$intervalRowCount][$skillsetColumnCount]
;~  GUICtrlCreateLabel("Extra Label", 30, 640, 100, 20)
;~  $tempExtraLabel1 = GUICtrlCreateLabel("", 120, 640, 100, 20)
;~  $countExtraLabel1 += 2
;~  GUICtrlSetData($tempExtraLabel1, $countExtraLabel1)
;~  ;;; Uncomment this to increase the number of columns to 50 to exhaust resources

EndFunc   ;==>_tempOperationsLabels

; ==============================================================================================================================
Func _GuiCtrlSetFont($controlID, $size, $weight = 400, $attribute = 0, $rotation = 0, $fontname = "", $quality = 2)
    Local $fdwItalic = BitAND($attribute, 1)
    Local $fdwUnderline = BitAND($attribute, 2)
    Local $fdwStrikeOut = BitAND($attribute, 4)
    ReDim $ahFontEx[UBound($ahFontEx) + 1]

    $ahFontEx[0] += 1
    $ahFontEx[$ahFontEx[0]] = _WinAPI_CreateFont($size, 0, $rotation * 10, $rotation, $weight, _
            $fdwItalic, $fdwUnderline, $fdwStrikeOut, -1, 0, 0, $quality, 0, $fontname)
    GUICtrlSendMsg($controlID, 48, $ahFontEx[$ahFontEx[0]], 1)
EndFunc   ;==>_GuiCtrlSetFont

; ==============================================================================================================================
Func _FontCleanUp()
    For $i = 1 To $ahFontEx[0]
        _WinAPI_DeleteObject($ahFontEx[$i])
    Next

    _GDIPlus_PenDispose($hPen_COLORRED)
    _GDIPlus_PenDispose($hPen_COLORWHITE)
    _GDIPlus_PenDispose($hPen_COLORGREEN)
    _GDIPlus_PenDispose($hPen_COLORMEDGRAY)

    _GDIPlus_GraphicsDispose($hGraphics)

    _GDIPlus_GraphicsDispose($hGraphics2)
    _GDIPlus_ImageDispose($hImage)
    _WinAPI_DeleteObject($hBMP)

    _GDIPlus_Shutdown()
EndFunc   ;==>_FontCleanUp

; ==============================================================================================================================
Func _CreateBorderLabel($sText, $iX, $iY, $iW, $iH, $iColor, $iPenSize = 1, $iStyle = -1, $iStyleEx = 0)
    $internalLabelID1 = GUICtrlCreateLabel("", $iX - $iPenSize, $iY - $iPenSize, $iW + 2 * $iPenSize, $iH + 2 * $iPenSize, BitOR($SS_CENTER, $SS_CENTERIMAGE))
    GUICtrlSetBkColor(-1, $iColor)
    GUICtrlSetState(-1, $GUI_SHOW)

    $internalLabelID2 = GUICtrlCreateLabel($sText, $iX, $iY, $iW, $iH, BitOR($SS_CENTER, $SS_CENTERIMAGE), $iStyleEx)
    GUICtrlSetBkColor(-1, $COLOR_WHITE)
    GUICtrlSetState(-1, $GUI_SHOW)

    Return $internalLabelID2
EndFunc   ;==>_CreateBorderLabel

Func _CreateBorderLabel2($sText, $iX, $iY, $iW, $iH, $iColor, $iPenSize = 1)
    _GDIPlus_GraphicsDrawRect($hGraphics2, $iX - $iPenSize, $iY - $iPenSize, $iW + 2 * $iPenSize, $iH + 2 * $iPenSize, $iColor)
    If $sText Then _GDIPlus_GraphicsDrawString($hGraphics2, $sText, $iX, $iY, "Arial", 9)
EndFunc   ;==>_CreateBorderLabel

; ==============================================================================================================================
Func _TabIsNowDisplaying()
    Local $sTabSelected
    $sTabSelected = _GUICtrlTab_GetItemText($TabMainControl, _GUICtrlTab_GetCurSel($TabMainControl))
    ;______DebugPrint______("Tab is now = " & $sTabSelected)
    Return $sTabSelected
EndFunc   ;==>_TabIsNowDisplaying

; ==============================================================================================================================
Func _TabSelectionIsChanging($sTabSelected)
    Sleep(0)
    ;______DebugPrint______("Tab was = " & $sTabSelected)
EndFunc   ;==>_TabSelectionIsChanging

; ==============================================================================================================================
Func _WriteToLogWindow($sMessage)
    GUICtrlSetData($EditLogWindow, $sMessage & @CRLF, 1)
EndFunc   ;==>_WriteToLogWindow

; ==============================================================================================================================
Func ______DebugPrint______($s_text, $line = @ScriptLineNumber)
    ; Usage:
    ;______DebugPrint______("$variable= " & $variable)
    ConsoleWrite( _
            "-->Line(" & StringFormat("%04d", $line) & "):" & @TAB & $s_text & @LF & _
            "+======================================================" & @LF)
EndFunc   ;==>______DebugPrint______

; ==============================================================================================================================
Func _OpenFile()
    $sFile = FileOpenDialog("Choose file...", $sSourceDirecory, "All (*.*)")
    $oExcel = _ExcelBookOpen($sFile, 1)
    If @error = 1 Then
        MsgBox(0, "Error!", "Unable to Create the Excel Object")
        Exit
    ElseIf @error = 2 Then
        MsgBox(0, "Error!", "Unable to open the RollCall tracker!" & @CRLF & @CRLF & _
                "1. Close RollCall" & @CRLF & _
                "2. Save any open spreadsheets" & @CRLF & _
                "3. Restart RollCall")
        Exit
    EndIf
    GUICtrlSetState($MenuFileLoadSave, $GUI_DISABLE)
EndFunc   ;==>_OpenFile

; ==============================================================================================================================
Func _Save()
    _SetMainStatusBusyMessage("Saving...")
    _ExcelBookSave($oExcel) ; This method will Save without any prompts
    GUICtrlSetState($MenuFileLoadSave, $GUI_DISABLE)
    _SetMainStatusReadyMessage("Saved")
EndFunc   ;==>_Save

; ==============================================================================================================================
Func _SaveAndExit()
    _ExcelBookClose($oExcel, 1, 0) ; This method will Save and Exit without any prompts
EndFunc   ;==>_SaveAndExit

; ==============================================================================================================================
Func _SetDocking()
    If BitAND(GUICtrlRead($MenuViewDockingDocked), $GUI_CHECKED) = $GUI_CHECKED Then
        GUICtrlSetState($MenuViewDockingDocked, $GUI_UNCHECKED)
        $Dock = 0
    Else
        GUICtrlSetState($MenuViewDockingDocked, $GUI_CHECKED)
        $Dock = 2
    EndIf
    If $Dock Then _KeepWindowsDocked()
EndFunc   ;==>_SetDocking

; ==============================================================================================================================
Func _SetDockSideBySide()
    If BitAND(GUICtrlRead($MenuViewDockingSideSide), $GUI_CHECKED) = $GUI_CHECKED Then
        GUICtrlSetState($MenuViewDockingSideSide, $GUI_UNCHECKED)
        GUICtrlSetState($MenuViewDockingTopBot, $GUI_CHECKED)
        $Dock_Location = 2
    Else
        GUICtrlSetState($MenuViewDockingSideSide, $GUI_CHECKED)
        GUICtrlSetState($MenuViewDockingTopBot, $GUI_UNCHECKED)
        $Dock_Location = 1
        If $Dock Then $Dock = 2
    EndIf
    If $Dock Then _KeepWindowsDocked()
EndFunc   ;==>_SetDockSideBySide

; ==============================================================================================================================
Func _SetDockTopAndBottom()
    If BitAND(GUICtrlRead($MenuViewDockingTopBot), $GUI_CHECKED) = $GUI_CHECKED Then
        GUICtrlSetState($MenuViewDockingTopBot, $GUI_UNCHECKED)
        GUICtrlSetState($MenuViewDockingSideSide, $GUI_CHECKED)
        $Dock_Location = 1
    Else
        GUICtrlSetState($MenuViewDockingTopBot, $GUI_CHECKED)
        GUICtrlSetState($MenuViewDockingSideSide, $GUI_UNCHECKED)
        $Dock_Location = 2
        If $Dock Then $Dock = 2
    EndIf
    If $Dock Then _KeepWindowsDocked()
EndFunc   ;==>_SetDockTopAndBottom

; ==============================================================================================================================
Func _KeepWindowsDocked()
    Local $p_win1 = WinGetPos($hMainWindow)
    Local $p_win2 = WinGetPos($hDestinationWindow)
    If $Dock_Location == 1 Then
        If (($p_win1[0] <> $x1 Or $p_win1[1] <> $y1) And BitAND(WinGetState($hMainWindow), 8) Or $Dock = 2) Then
            $x1 = $p_win1[0]
            $y1 = $p_win1[1]
            $x2 = $p_win1[2] + $x1
            $y2 = $y1
            WinMove($hDestinationWindow, "", $x2, $y2)
            $Dock = 1
        ElseIf (($p_win2[0] <> $x2 Or $p_win2[1] <> $y2) And BitAND(WinGetState($hDestinationWindow), 8)) Then
            $x2 = $p_win2[0]
            $y2 = $p_win2[1]
            $x1 = $p_win2[0] - $p_win1[2]
            $y1 = $y2
            WinMove($hMainWindow, "", $x1, $y1)
        EndIf
    Else
        If (($p_win1[0] <> $x1 Or $p_win1[1] <> $y1) And BitAND(WinGetState($hMainWindow), 8) Or $Dock = 2) Then
            $x1 = $p_win1[0]
            $y1 = $p_win1[1]
            $x2 = $x1
            $y2 = $p_win1[3] + $y1
            WinMove($hDestinationWindow, "", $x2, $y2)
            $Dock = 1
        ElseIf (($p_win2[0] <> $x2 Or $p_win2[1] <> $y2) And BitAND(WinGetState($hDestinationWindow), 8)) Then
            $x2 = $p_win2[0]
            $y2 = $p_win2[1]
            $x1 = $x2
            $y1 = $p_win2[1] - $p_win1[3]
            WinMove($hMainWindow, "", $x1, $y1)
        EndIf
    EndIf
EndFunc   ;==>_KeepWindowsDocked

; ==============================================================================================================================
Func _ToggleStatus()
    If BitAND(GUICtrlRead($MenuViewStatusbar), $GUI_CHECKED) = $GUI_CHECKED Then
        GUICtrlSetState($MenuViewStatusbar, $GUI_UNCHECKED)
        GUICtrlSetState($LabelStatusMain, $GUI_HIDE)
    Else
        GUICtrlSetState($MenuViewStatusbar, $GUI_CHECKED)
        GUICtrlSetState($LabelStatusMain, $GUI_SHOW)
    EndIf
EndFunc   ;==>_ToggleStatus

; ==============================================================================================================================
Func _SetMainStatusBusyMessage($tStatusMessageMain)
    GUICtrlSetData($LabelStatusMain, $tStatusMessageMain)
    GUICtrlSetBkColor($LabelStatusMain, 0xff0000)
    Return $sStatusMessageMain
EndFunc   ;==>_SetMainStatusBusyMessage

; ==============================================================================================================================
Func _SetDestStatusBusyMessage($tStatusMessageDest)
    GUICtrlSetData($LabelStatusDest, $tStatusMessageDest)
    GUICtrlSetBkColor($LabelStatusMain, 0xff0000)
    Return $sStatusMessageDest
EndFunc   ;==>_SetDestStatusBusyMessage

; ==============================================================================================================================
Func _SetMainStatusReadyMessage($tStatusMessageMain)
    GUICtrlSetData($LabelStatusMain, $tStatusMessageMain)
    GUICtrlSetBkColor($LabelStatusMain, 0x80ff80)
    Return $sStatusMessageMain
EndFunc   ;==>_SetMainStatusReadyMessage

; ==============================================================================================================================
Func _SetDestStatusReadyMessage($tStatusMessageDest)
    GUICtrlSetData($LabelStatusDest, $tStatusMessageDest)
    GUICtrlSetBkColor($LabelStatusDest, 0x80ff80)
    Return $sStatusMessageDest
EndFunc   ;==>_SetDestStatusReadyMessage

; ==============================================================================================================================
Func _WM_MOVE($hWnd, $iMsg, $iwParam, $ilParam)
    If ($hWnd = $hMainWindow Or $hWnd = $hDestinationWindow) Then
        If $Run = 1 And $Dock Then _KeepWindowsDocked()
    EndIf
EndFunc   ;==>_WM_MOVE

; ==============================================================================================================================
Func _WM_COMMAND($hWnd, $iMsg, $iwParam, $ilParam)
    Local $nNotifyCode, $nID
    $nNotifyCode = BitShift($iwParam, 16)
    $nID = BitAND($iwParam, 0xFFFF)
    Switch $nID
        Case 1 = 1
;~      Case $InputLogin, $InputName, $ComboStatus, $InputShift, $EditNotes
;~          ;Turns on the button if any of the fields change
;~          ;If $nNotifyCode = $EN_CHANGE Then GUICtrlSetData($nID, StringReplace(GUICtrlRead($nID), ".", ","))
;~          If $nNotifyCode = $EN_CHANGE Then GUICtrlSetState($ButtonEnterAgent, $GUI_ENABLE)
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>_WM_COMMAND

; ==============================================================================================================================
Func _WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    #forceref $hWnd, $iMsg, $iwParam
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $hWndTabControl, $tInfo
    $hWndTabControl = $TabMainControl
    If Not IsHWnd($TabMainControl) Then $hWndTabControl = GUICtrlGetHandle($TabMainControl)

    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $hWndFrom
        Case $hWndTabControl
            Switch $iCode
                Case $NM_CLICK
                    $tInfo = DllStructCreate($tagNMITEMACTIVATE, $ilParam)
                    ;______DebugPrint______("$NM_CLICK" & @TAB & _
                    ;       "IDFrom: " & $iIDFrom & @TAB & "Index: " & DllStructGetData($tInfo, "Index") & @TAB & _
                    ;       "SubItem: " & DllStructGetData($tInfo, "SubItem"))
                Case $TCN_SELCHANGING
                    $tInfo = DllStructCreate($tagNMITEMACTIVATE, $ilParam)
                    _TabSelectionIsChanging(_GUICtrlTab_GetItemText($hWndTabControl, _GUICtrlTab_GetCurSel($hWndTabControl)))
                    ;______DebugPrint______("$TCN_SELCHANGING" & @TAB & _
                    ;       "IDFrom: " & $iIDFrom & @TAB & "Index: " & DllStructGetData($tInfo, "Index") & @TAB & _
                    ;       "SubItem: " & DllStructGetData($tInfo, "SubItem"))
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>_WM_NOTIFY

; ==============================================================================================================================
Func WM_VSCROLL($hWnd, $msg, $wParam, $lParam)
    #forceref $Msg, $wParam, $lParam
    Local $nScrollCode = BitAND($wParam, 0x0000FFFF)
    Local $index = -1, $yChar, $yPos
    Local $Min, $Max, $Page, $Pos, $TrackPos

    For $x = 0 To UBound($aSB_WindowInfo) - 1
        If $aSB_WindowInfo[$x][0] = $hWnd Then
            $index = $x
            $yChar = $aSB_WindowInfo[$index][3]
            ExitLoop
        EndIf
    Next
    If $index = -1 Then Return 0

    ; Get all the vertial scroll bar information
    Local $tSCROLLINFO = _GUIScrollBars_GetScrollInfoEx($hWnd, $SB_VERT)
    $Min = DllStructGetData($tSCROLLINFO, "nMin")
    $Max = DllStructGetData($tSCROLLINFO, "nMax")
    $Page = DllStructGetData($tSCROLLINFO, "nPage")
    ; Save the position for comparison later on
    $yPos = DllStructGetData($tSCROLLINFO, "nPos")
    $Pos = $yPos
    $TrackPos = DllStructGetData($tSCROLLINFO, "nTrackPos")

    Switch $nScrollCode
        Case $SB_TOP ; user clicked the HOME keyboard key
            DllStructSetData($tSCROLLINFO, "nPos", $Min)

        Case $SB_BOTTOM ; user clicked the END keyboard key
            DllStructSetData($tSCROLLINFO, "nPos", $Max)

        Case $SB_LINEUP ; user clicked the top arrow
            DllStructSetData($tSCROLLINFO, "nPos", $Pos - 1)

        Case $SB_LINEDOWN ; user clicked the bottom arrow
            DllStructSetData($tSCROLLINFO, "nPos", $Pos + 1)

        Case $SB_PAGEUP ; user clicked the scroll bar shaft above the scroll box
            DllStructSetData($tSCROLLINFO, "nPos", $Pos - $Page)

        Case $SB_PAGEDOWN ; user clicked the scroll bar shaft below the scroll box
            DllStructSetData($tSCROLLINFO, "nPos", $Pos + $Page)

        Case $SB_THUMBTRACK ; user dragged the scroll box
            DllStructSetData($tSCROLLINFO, "nPos", $TrackPos)
    EndSwitch

;~    // Set the position and then retrieve it.  Due to adjustments
;~    //   by Windows it may not be the same as the value set.

    DllStructSetData($tSCROLLINFO, "fMask", $SIF_POS)
    _GUIScrollBars_SetScrollInfo($hWnd, $SB_VERT, $tSCROLLINFO)
    _GUIScrollBars_GetScrollInfo($hWnd, $SB_VERT, $tSCROLLINFO)
    ;// If the position has changed, scroll the window and update it
    $Pos = DllStructGetData($tSCROLLINFO, "nPos")

    If ($Pos <> $yPos) Then
        _GUIScrollBars_ScrollWindow($hWnd, 0, $yChar * ($yPos - $Pos))
        $yPos = $Pos
        GUICtrlSetData($tempScroll2, $Pos)
        _GUIScrollBars_SetScrollInfoPos($hIntervalsColumn, $SB_VERT, $Pos)
        ;______DebugPrint______("V-scroll pos: " & $Pos)
    EndIf

    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_VSCROLL

; ==============================================================================================================================
Func WM_HSCROLL($hWnd, $msg, $wParam, $lParam)
    #forceref $Msg, $lParam
    Local $nScrollCode = BitAND($wParam, 0x0000FFFF)

    Local $index = -1, $xChar, $xPos
    Local $Min, $Max, $Page, $Pos, $TrackPos

    For $x = 0 To UBound($aSB_WindowInfo) - 1
        If $aSB_WindowInfo[$x][0] = $hWnd Then
            $index = $x
            $xChar = $aSB_WindowInfo[$index][2]
            ExitLoop
        EndIf
    Next
    If $index = -1 Then Return 0

;~  ; Get all the horizontal scroll bar information
    Local $tSCROLLINFO = _GUIScrollBars_GetScrollInfoEx($hWnd, $SB_HORZ)
    $Min = DllStructGetData($tSCROLLINFO, "nMin")
    $Max = DllStructGetData($tSCROLLINFO, "nMax")
    $Page = DllStructGetData($tSCROLLINFO, "nPage")
    ; Save the position for comparison later on
    $xPos = DllStructGetData($tSCROLLINFO, "nPos")
    $Pos = $xPos
    $TrackPos = DllStructGetData($tSCROLLINFO, "nTrackPos")
    #forceref $Min, $Max
    Switch $nScrollCode

        Case $SB_LINELEFT ; user clicked left arrow
            DllStructSetData($tSCROLLINFO, "nPos", $Pos - 1)

        Case $SB_LINERIGHT ; user clicked right arrow
            DllStructSetData($tSCROLLINFO, "nPos", $Pos + 1)

        Case $SB_PAGELEFT ; user clicked the scroll bar shaft left of the scroll box
            DllStructSetData($tSCROLLINFO, "nPos", $Pos - $Page)

        Case $SB_PAGERIGHT ; user clicked the scroll bar shaft right of the scroll box
            DllStructSetData($tSCROLLINFO, "nPos", $Pos + $Page)

        Case $SB_THUMBTRACK ; user dragged the scroll box
            DllStructSetData($tSCROLLINFO, "nPos", $TrackPos)
    EndSwitch

;~    // Set the position and then retrieve it.  Due to adjustments
;~    //   by Windows it may not be the same as the value set.

    DllStructSetData($tSCROLLINFO, "fMask", $SIF_POS)
    _GUIScrollBars_SetScrollInfo($hWnd, $SB_HORZ, $tSCROLLINFO)
    _GUIScrollBars_GetScrollInfo($hWnd, $SB_HORZ, $tSCROLLINFO)
    ;// If the position has changed, scroll the window and update it
    $Pos = DllStructGetData($tSCROLLINFO, "nPos")

    If ($Pos <> $xPos) Then
        _GUIScrollBars_ScrollWindow($hWnd, $xChar * ($xPos - $Pos), 0)
        GUICtrlSetData($tempScroll1, $Pos)
        _GUIScrollBars_SetScrollInfoPos($hSkillsetsRow, $SB_HORZ, $Pos)
        ;______DebugPrint______("H-scroll pos: " & $Pos)
    EndIf

    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_HSCROLL

Func WM_PAINT($hWnd, $msg, $wParam, $lParam)
    #forceref $hWnd, $Msg, $wParam, $lParam
    Switch $hWnd
        Case $hFlexGrid
            _WinAPI_RedrawWindow($hFlexGrid, 0, 0, $RDW_UPDATENOW)
            _InitializeIntervalGrid()
            _WinAPI_RedrawWindow($hFlexGrid, 0, 0, $RDW_VALIDATE)
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>MY_WM_PAINT
2 people like this

Share this post


Link to post
Share on other sites

Excellent! I removed the first call to the $COLOR_MEDGRAY border label entirely since this was a remnant of when I was building the grid out the first time. I recuperated half the calls and can now create 100 columns comfortably.

I think I will be able to redesign it so the "Top-100" skillsets that need the most attention get resorted into the left-most columns as each interval gets stamped.

I will keep refining it and report back.

Thanks everyone!

Disc

DiscGolferPro,

Just for completeness here is the modified function I used:

Modified code above

This way I only create 5223 controls and the whole grid appears. :)

M23

Share this post


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