Jump to content

GUI performance


Recommended Posts

Context

Lately I have been experimenting with the creation of a GUI with AutoIt.

In my last test I created some code to draw a grid of labels on a window.

When I update the grid the GUI seems very slow to me.

I actually have to wait a few seconds till the grid is updated.

Request

I would really appreciate some help on speeding up the painting of the GUI.

GUI

The following example consists of a simple window.

The window contains a grid of colored labels.

By pressing the button the colors of the labels are inverted.

Posted Image

Source code

; --------
; includes
; --------

#include <GUIConstantsEx.au3>


; ---------
; variables
; ---------

Global $varWindow
Global $varButton
Global $varGrid[21][21]
Global $varIsFirstBoxDark = True


; -------------
; gui functions
; -------------

Func _CreateWindow()
    Opt("GUIOnEventMode", 1)
    $varWindow = GuiCreate("Grid", 440, 480)
    GUISetOnEvent($GUI_EVENT_CLOSE, "_Close")
EndFunc


Func _CreateButton()
    $varButton = GUICtrlCreateButton("Invert", 10, 10)
    GUICtrlSetOnEvent($varButton, "_Invert")
EndFunc
    

Func _CreateGrid()
    Local $varIsCurrentBoxDark = $varIsFirstBoxDark
    
    For $x = 0 To 20
        For $y = 0 To 20
            Local $varLabel = GUICtrlCreateLabel("", 10 + (20 * $x), 50 + (20 * $y), 20, 20)
            If $varIsCurrentBoxDark Then
                GUICtrlSetBkColor($varLabel, 0xAAAAAA)
            Else
                GUICtrlSetBkColor($varLabel, 0xBBBBBB)
            EndIf
            
            $varGrid[$x][$y] = $varLabel
            $varIsCurrentBoxDark = Not $varIsCurrentBoxDark
        Next
    Next
EndFunc


Func _ShowWindow()
    GUISetState(@SW_SHOW)
    While True
        Sleep(1000)
    WEnd
EndFunc


; ------
; events
; ------

Func _Close()
    Exit
EndFunc

Func _Invert()
    $varIsFirstBoxDark = Not $varIsFirstBoxDark
    
    Local $varIsCurrentBoxDark = $varIsFirstBoxDark
    For $x = 0 To 20
        For $y = 0 To 20
            Local $varOldLabel = $varGrid[$x][$y]
            GUICtrlDelete($varOldLabel)
            
            Local $varNewLabel = GUICtrlCreateLabel("", 10 + (20 * $x), 50 + (20 * $y), 20, 20)
            If $varIsCurrentBoxDark Then
                GUICtrlSetBkColor($varNewLabel, 0xAAAAAA)
            Else
                GUICtrlSetBkColor($varNewLabel, 0xBBBBBB)
            EndIf
            
            $varGrid[$x][$y] = $varNewLabel
            $varIsCurrentBoxDark = Not $varIsCurrentBoxDark
        Next
    Next
EndFunc


; -------
; runtime
; -------

_CreateWindow()
_CreateButton()
_CreateGrid()
_ShowWindow()

Problem

When pressing the button, the colors of the labels are inverted.

The problem is the time it takes to refresh the grid: a bit less then 3 seconds.

I believe this should be done almost instantly.

Is there a way to speedup this process?

Edit: Changed the type of <code snippet> to <autoit> for colored source code

Edited by Psychoman
Link to comment
Share on other sites

The labels are updated quite slowly

This might be quicker

#include <GUIConstantsEx.au3>


; ---------
; variables
; ---------

Global $varWindow
Global $varButton
Global $varGrid[21][21]
Global $varIsFirstBoxDark = True


; -------------
; gui functions
; -------------

Func _CreateWindow()
    Opt("GUIOnEventMode", 1)
    $varWindow = GuiCreate("Grid", 440, 480)
    GUISetOnEvent($GUI_EVENT_CLOSE, "_Close")
EndFunc


Func _CreateButton()
    $varButton = GUICtrlCreateButton("Invert", 10, 10)
    GUICtrlSetOnEvent($varButton, "_Invert")
EndFunc


Func _CreateGrid()
    Local $varIsCurrentBoxDark = $varIsFirstBoxDark

    For $x = 0 To 20
        For $y = 0 To 20
            $varGrid[$x][$y] = GUICtrlCreateLabel("", 10 + (20 * $x), 50 + (20 * $y), 20, 20)
            If $varIsCurrentBoxDark Then
                GUICtrlSetBkColor(-1, 0xAAAAAA)
            Else
                GUICtrlSetBkColor(-1, 0xBBBBBB)
            EndIf

            $varIsCurrentBoxDark = Not $varIsCurrentBoxDark
        Next
    Next
EndFunc


Func _ShowWindow()
    GUISetState(@SW_SHOW)
    While True
        Sleep(1000)
    WEnd
EndFunc


; ------
; events
; ------

Func _Close()
    Exit
EndFunc

Func _Invert()
    $varIsFirstBoxDark = Not $varIsFirstBoxDark

    Local $varIsCurrentBoxDark = $varIsFirstBoxDark
    For $x = 0 To 20
        For $y = 0 To 20
            If $varIsCurrentBoxDark Then
                GUICtrlSetBkColor($varGrid[$x][$y], 0xAAAAAA)
            Else
                GUICtrlSetBkColor($varGrid[$x][$y], 0xBBBBBB)
            EndIf

            $varIsCurrentBoxDark = Not $varIsCurrentBoxDark
        Next
    Next
EndFunc


; -------
; runtime
; -------

_CreateWindow()
_CreateButton()
_CreateGrid()
_ShowWindow()

You could do it like this if you just want to chnage the appearance.which is probably faster

#include <GUIConstantsEx.au3>
#include <windowsconstants.au3>

; ---------
; variables
; ---------

Global $varWindow, $varChild, $varGchild
Global $varButton
Global $varGrid[21][23]
Global $varIsFirstBoxDark = True


; -------------
; gui functions
; -------------

Func _CreateWindow()
    Opt("GUIOnEventMode", 1)
    $varWindow = GUICreate("Grid", 440, 480)
    GUISetOnEvent($GUI_EVENT_CLOSE, "_Close")
    GUISetState()
EndFunc   ;==>_CreateWindow


Func _CreateButton()
    $varButton = GUICtrlCreateButton("Invert", 10, 10)
    GUICtrlSetOnEvent($varButton, "_Invert")
EndFunc   ;==>_CreateButton


Func _CreateGrid()
    Local $varIsCurrentBoxDark = $varIsFirstBoxDark
    $varChild = GUICreate("child", 440, 400, 10, 50, $WS_CHILD, -1, $varWindow)
    GUISetState()
    $varGchild = GUICreate("grandchild", 440, 500, 0, 0, $WS_CHILD, -1, $varChild)
    GUISetState()
    For $x = 0 To 20
        For $y = 0 To 22
            Local $varLabel = GUICtrlCreateLabel("", (20 * $x), (20 * $y), 20, 20)
            If $varIsCurrentBoxDark Then
                GUICtrlSetBkColor($varLabel, 0xAAAAAA)
            Else
                GUICtrlSetBkColor($varLabel, 0xBBBBBB)
            EndIf

            $varGrid[$x][$y] = $varLabel
            $varIsCurrentBoxDark = Not $varIsCurrentBoxDark
        Next
    Next
EndFunc   ;==>_CreateGrid


Func _ShowWindow()
    ;GUISetState(@SW_SHOW)
    While True
        Sleep(1000)
    WEnd
EndFunc   ;==>_ShowWindow

; ------
; events
; ------

Func _Close()
    Exit
EndFunc   ;==>_Close

Func _Invert()
    $varIsFirstBoxDark = Not $varIsFirstBoxDark
    If $varIsFirstBoxDark Then
        WinMove($varGchild, "", 0, 0)
    Else
        WinMove($varGchild, "", 0, -20)
    EndIf
    Return

EndFunc   ;==>_Invert


; -------
; runtime
; -------

_CreateWindow()
_CreateButton()
_CreateGrid()
_ShowWindow()

Or you could draw the grid using GDI+.

EDIT: interesting effect of the second version which is quite fast for me, if you click the invert button repeatedly then the squares around the edge appear to move in different directions depending on which corner you look at. (Or is it the mushrooms I had for breakfast?)

Edited by martin
Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

Maybe a little faster haven't tested but this is more optimised. Also don't declare variables in Loops as this slows the Loop down, trick I learnt from Melba23 ;)

#include <GUIConstantsEx.au3>

Opt("GUIOnEventMode", 1)

Global $aArray[21][21], $hGUI, $iButton, $iIsFirstDark = 0

_CreateWindow()

Func _CreateWindow()
    $hGUI = GUICreate("Grid", 440, 480)
    GUISetOnEvent($GUI_EVENT_CLOSE, "_Close")

    $iButton = GUICtrlCreateButton("Invert", 10, 10, 65, 22.5)
    GUICtrlSetOnEvent(-1, "_Invert")

    GUISetState(@SW_SHOW, $hGUI)

    _Grid()
    While 1
        Sleep(100)
    WEnd
EndFunc   ;==>_CreateWindow

Func _Grid()
    For $A = 0 To 20
        For $B = 0 To 20
            GUICtrlDelete($aArray[$A][$B])

            $aArray[$A][$B] = GUICtrlCreateLabel("", 10 + (20 * $A), 50 + (20 * $B), 20, 20)
            If $iIsFirstDark Then
                GUICtrlSetBkColor($aArray[$A][$B], 0xAAAAAA)
                $iIsFirstDark = 0
            Else
                GUICtrlSetBkColor($aArray[$A][$B], 0xBBBBBB)
                $iIsFirstDark = 1
            EndIf
        Next
    Next
EndFunc   ;==>_Grid

Func _Close()
    Exit
EndFunc   ;==>_Close

martin just saw your update with the WinMove(), nice and I see that too, perhaps my cheerios weren't cheerios :huh2:

Edited by guinness

UDF List:

 
_AdapterConnections()_AlwaysRun()_AppMon()_AppMonEx()_ArrayFilter/_ArrayReduce_BinaryBin()_CheckMsgBox()_CmdLineRaw()_ContextMenu()_ConvertLHWebColor()/_ConvertSHWebColor()_DesktopDimensions()_DisplayPassword()_DotNet_Load()/_DotNet_Unload()_Fibonacci()_FileCompare()_FileCompareContents()_FileNameByHandle()_FilePrefix/SRE()_FindInFile()_GetBackgroundColor()/_SetBackgroundColor()_GetConrolID()_GetCtrlClass()_GetDirectoryFormat()_GetDriveMediaType()_GetFilename()/_GetFilenameExt()_GetHardwareID()_GetIP()_GetIP_Country()_GetOSLanguage()_GetSavedSource()_GetStringSize()_GetSystemPaths()_GetURLImage()_GIFImage()_GoogleWeather()_GUICtrlCreateGroup()_GUICtrlListBox_CreateArray()_GUICtrlListView_CreateArray()_GUICtrlListView_SaveCSV()_GUICtrlListView_SaveHTML()_GUICtrlListView_SaveTxt()_GUICtrlListView_SaveXML()_GUICtrlMenu_Recent()_GUICtrlMenu_SetItemImage()_GUICtrlTreeView_CreateArray()_GUIDisable()_GUIImageList_SetIconFromHandle()_GUIRegisterMsg()_GUISetIcon()_Icon_Clear()/_Icon_Set()_IdleTime()_InetGet()_InetGetGUI()_InetGetProgress()_IPDetails()_IsFileOlder()_IsGUID()_IsHex()_IsPalindrome()_IsRegKey()_IsStringRegExp()_IsSystemDrive()_IsUPX()_IsValidType()_IsWebColor()_Language()_Log()_MicrosoftInternetConnectivity()_MSDNDataType()_PathFull/GetRelative/Split()_PathSplitEx()_PrintFromArray()_ProgressSetMarquee()_ReDim()_RockPaperScissors()/_RockPaperScissorsLizardSpock()_ScrollingCredits_SelfDelete()_SelfRename()_SelfUpdate()_SendTo()_ShellAll()_ShellFile()_ShellFolder()_SingletonHWID()_SingletonPID()_Startup()_StringCompact()_StringIsValid()_StringRegExpMetaCharacters()_StringReplaceWholeWord()_StringStripChars()_Temperature()_TrialPeriod()_UKToUSDate()/_USToUKDate()_WinAPI_Create_CTL_CODE()_WinAPI_CreateGUID()_WMIDateStringToDate()/_DateToWMIDateString()Au3 script parsingAutoIt SearchAutoIt3 PortableAutoIt3WrapperToPragmaAutoItWinGetTitle()/AutoItWinSetTitle()CodingDirToHTML5FileInstallrFileReadLastChars()GeoIP databaseGUI - Only Close ButtonGUI ExamplesGUICtrlDeleteImage()GUICtrlGetBkColor()GUICtrlGetStyle()GUIEventsGUIGetBkColor()Int_Parse() & Int_TryParse()IsISBN()LockFile()Mapping CtrlIDsOOP in AutoItParseHeadersToSciTE()PasswordValidPasteBinPosts Per DayPreExpandProtect GlobalsQueue()Resource UpdateResourcesExSciTE JumpSettings INISHELLHOOKShunting-YardSignature CreatorStack()Stopwatch()StringAddLF()/StringStripLF()StringEOLToCRLF()VSCROLLWM_COPYDATAMore Examples...

Updated: 22/04/2018

Link to comment
Share on other sites

Is this fast enough?

;coded by UEZ 2011-06-06
#include <GUIConstantsEx.au3>
#include <GDIPlus.au3>
Opt("GUIOnEventMode", 1)
Opt("MustDeclareVars", 1)

Global $hGUI
Global $idExitButton, $idInvertButton, $idPic, $w, $h, $hImage1, $hImage2, $c = 1
Global Const $STM_SETIMAGE = 0x0172

_GDIPlus_Startup()

$w = 440
$h = 480
$hGUI = GuiCreate("Checkerboard Pattern", $w, $h)
GUISetOnEvent($GUI_EVENT_CLOSE, "_Close")
$idPic = GUICtrlCreatePic("", 10, 50, $w - 20, $h - 60)
GUICtrlSetState(-1, $GUI_DISABLE)
$idInvertButton = GUICtrlCreateButton("Invert", 10, 10)
GUICtrlSetOnEvent($idInvertButton, "_Invert")
$idExitButton = GUICtrlCreateButton("Exit", $w - 35, 10)
GUICtrlSetOnEvent($idExitButton, "_Close")

$hImage1 = _CreateGrid(20, 21, 21, 0xFFAAAAAA, 0xFFBBBBBB)
$hImage2 = _CreateGrid(20, 21, 21, 0xFFBBBBBB, 0xFFAAAAAA)
GUISetState(@SW_SHOW)

_Invert()

While Sleep(1000)
WEnd

Func _Close()
    _WinAPI_DeleteObject($hImage1)
    _WinAPI_DeleteObject($hImage2)
    _GDIPlus_Shutdown()
    GUIDelete($hGUI)
    Exit
EndFunc

Func _Invert()
    Local $hImage
    If Mod($c, 2) Then
        _WinAPI_DeleteObject(GUICtrlSendMsg($idPic, $STM_SETIMAGE, 0, $hImage1))
    Else
        _WinAPI_DeleteObject(GUICtrlSendMsg($idPic, $STM_SETIMAGE, 0, $hImage2))
    EndIf
    $c += 1
    Return 1
EndFunc

Func _CreateGrid($squaresize = 20, $amountx = 21, $amounty = 21, $color1 = 0xFFAAAAAA, $color2 = 0xFFBBBBBB)
    Local $x, $y, $z = 1
    Local $bmpw = $squaresize * $amountx
    Local $bmph = $squaresize * $amounty
    Local $hBrush1 = _GDIPlus_BrushCreateSolid($color1)
    Local $hBrush2 = _GDIPlus_BrushCreateSolid($color2)
    Local $hBitmap = DllCall($ghGDIPDll, "uint", "GdipCreateBitmapFromScan0", "int", $bmpw, "int", $bmph, "int", 0, "int",  0x0026200A, "ptr", 0, "int*", 0)

    $hBitmap = $hBitmap[6]
    Local $hGfxContext = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    For $y = 0 To $squaresize * $amounty Step $squaresize
        For $x = 0 To $squaresize * $amountx Step $squaresize
            If Mod($z, 2) Then
                _GDIPlus_GraphicsFillRect($hGfxContext, $x, $y, $squaresize, $squaresize, $hBrush1)
            Else
                _GDIPlus_GraphicsFillRect($hGfxContext, $x, $y, $squaresize, $squaresize, $hBrush2)
            EndIf
            $z += 1
        Next
        $z += 1
    Next
    _GDIPlus_BrushDispose($hBrush1)
    _GDIPlus_BrushDispose($hBrush2)
    _GDIPlus_GraphicsDispose($hGfxContext)
    Local $hHBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap)
    _GDIPlus_BitmapDispose($hBitmap)
    Return $hHBitmap
EndFunc

Br,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

Is this fast enough?

..

Br,

UEZ

Much slower than the WInMove method if my tests are believable. It doesn't look any slower to me but then I can't think that quickly.

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

To be honest I just overseen your code from above :huh2: because I was in a hurry.

It might be that your method is faster than what I did which I update again.

Br,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

UEZ almost all your visual examples are that of GDI+ :huh2: just saying its kinda funny

good examples though they may be i'm beginning to wonder if you married the _GDIPlus funcs.... haha

EDIT typo

Edited by CodyBarrett
Link to comment
Share on other sites

This is one of the things why I appreciate AutoIt: the excellent community.

Thanks a lot for the fast and constructive replies.

Again, I learned a lot thanks to you guys.

During the thread I noticed the description of my problem might not be as precise as it needs to be.

While all of the given solutions are applicable on my example, some might not exactly resolve my issue.

Please endure with me and let me rephrase my problem :huh2:

New Context

The tool I'm actually writing helps to locate some pixels on the screen.

Extended GUI

The idea is that the user inputs a pixel color.

The user moves the mouse to a location on the screen and presses the F10 button.

A grid is created which represents the pixels around the mouse.

The grid is created using a combination of colored labels and buttons.

The buttons represent pixels which have the exact same color as the one given.

Posted Image

Source code

The model view controller pattern has been applied.

The view handles the GUI (PixelLocator/View/PixelLocator.au3)

The model handles the state and the calculations (PixelLocator/Model/PixelLocator.au3)

The controller is the link between the view and the model (PixelLocator/Controller/PixelLocator.au3)

The application is launched by running PixelLocator/Application.au3

Please note I have attached the source code in this post.

Problem

Although the application of the winmove did work quite fast in previous example, it doesn't seem to be helpful in this context.

The application of the performance tricks makes the GUI faster but the result is still a little slow.

Question

From what I read I believe the usage of GDI+ might provide the solution I need.

The reason why I am a little bit reticent about using GDI+ is because of Windows it self.

A while ago I used a DLL found on these forums to locate an image on the screen.

It worked perfectly till Microsoft updated Windows XP.

I believe the DLL used a function in the user32.dll which has been updated since.

So I am a little bit worried the GDI+ libraries might get broken with a Windows update.

Is this something to worry about or am I being a fool?

PixelLocator.zip

Link to comment
Share on other sites

You can use the part of my code which I used in to display an area of the destop in a window.

Br,

UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

Let's say I go with the GDI solution from UEZ.

What I'm worried about is following lines of code

GUICtrlSendMsg($idPic, 0x0172, 0, $hImage1)
DllCall($ghGDIPDll, "uint", "GdipCreateBitmapFromScan0", "int", $bmpw, "int", $bmph, "int", 0, "int",  0x0026200A, "ptr", 0, "int*", 0)

What happens when Microsoft updates it's system which makes the API's of the called DLLs incompatible?

(This has happened to me before so it's a real concern)

How am I supposed to get the script working if I don't have access to Microsofts documentation?

Let me rephrase that:

Aren't there any build-in functions in Autoit that can handle previous lines of code?

I really don't like calling a dll or sending a message with obscure codes to a control.

If the API of the DLL is updated then Autoit should handle this (probably with an update), not me or the code I write.

See what I mean?

Link to comment
Share on other sites

If the API of the DLL is updated then Autoit should handle this (probably with an update), not me or the code I write.

See what I mean?

It most certainly is up to you to update your code if things in Windows change, just like it's up to you to change your code if things in AutoIt change. If you compile a script, no amount of updating to AutoIT is going to fix your compiled code, you're going to need to update it to match the changes to Windows, just like when Vista/Win7 was released.

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

Link to comment
Share on other sites

If I'm insisting it's because I'm considering filling in a feature request.

The function calls I mentioned before (used by the example of UEZ) look to me like a some base function taht has been skipped from some UDF.

Call me a purist if you want but I'd rather rely on the Autoit framework then on the MSDN library.

Although I really appreciate the constructive replies I've gotten so far

and thumbs up to all of those authors

I don't quite understand your hostile attitude AdmiralAlkex.

Link to comment
Share on other sites

Psychoman, the AutoIt 'framework' is built upon the same API calls you will find on MSDN. Microsoft is pretty keen on keeping backwards compatibility in their operating systems. Stuff that runs in Windows 2000 will run in Windows 7, and so on into the future. Rarely, functions are declared obsolete by Microsoft, and even then still continue to be supported. This is one reason the O/S is bloated. The only buggers you need to worry about are undocumented functions. Once it hits MSDN and gets documented, however, its pretty much a good bet it will be supported well into the future.

Alkex should try articulating a point rather than disparaging others.

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...