Sign in to follow this  
Followers 0
jimg

Confusion over GUICtrlDelete

9 posts in this topic

I have a simple GUI application where I have a little "speedometer" with some extra text, and despite calling GUICtrlDelete of the control that is the actual "dial", the individual GUICtrlSetGraphic commands seem to accumulate over time. I assume I just skipped an important chapter in the manual. Here's the essence of the code:

#include <INet.au3>

#include <GuiConstantsEx.au3>

#include <GDIPlus.au3>

#include <WindowsConstants.au3>

#Include <WinAPI.au3>

#include <StaticConstants.au3>

Opt("GUIOnEventMode", 1)

$meter=0

$dir=0

$label_speed = 0

$pi = 3.14159

$font = "Tahoma"

; Create GUI & label controls

$hGUI = GUICreate("GUIone", 100, 120,-1,-1,$WS_CAPTION,$WS_EX_TOOLWINDOW)

$label_date = GUICtrlCreateLabel ( "", 10, 0 ,80,14,$SS_Center)

$label_time = GUICtrlCreateLabel ( "", 10, 15 ,80,14,$SS_Center)

GUIRegisterMsg($WM_PAINT, "Paint")

GUISetOnEvent($GUI_EVENT_RESTORE, "Paint")

GUISetOnEvent($GUI_EVENT_CLOSE, "Finish")

while 1

paint()

; run every ten minutes

; sleep(10*60*1000)

sleep(1000)

WEnd

Func Paint()

$radius = 40

; stuff to generate data goes here, but isn't included

$date = "Aug 8, 2008"

$time = "17:30pm"

$speed = 13.7

$dir = $dir+1

if $dir = 360 then $dir = 0

; delete controls if they exist

if $meter <> 0 then GUICtrlDelete($meter)

if $label_speed <> 0 then GUICtrlDelete($label_speed)

$meter = GUICtrlCreateGraphic(5, 30, 90, 90)

GUICtrlSetGraphic(-1, $GUI_GR_PENSIZE,2)

GUICtrlSetGraphic(-1, $GUI_GR_COLOR, 0x000000, 0x888888)

GUICtrlSetGraphic(-1, $GUI_GR_ELLIPSE, 5, 5, 80, 80)

GUICtrlSetGraphic(-1, $GUI_GR_COLOR, 0x000000, 0xcccccc)

; tick marks on dial

for $index = 0 to 16

$xsp = $radius*sin($pi*$index/8)

$ysp = -1*$radius*cos($pi*$index/8)

$xep = 1.15*$radius*sin($pi*$index/8)

$yep = -1.15*$radius*cos($pi*$index/8)

GUICtrlSetGraphic(-1, $GUI_GR_MOVE, $xsp+45, $ysp+45)

GUICtrlSetGraphic(-1, $GUI_GR_LINE, $xep+45, $yep+45)

Next

$xpos = 35*sin($pi*$dir/180)

$ypos = -35*cos($pi*$dir/180)

GUICtrlSetGraphic(-1, $GUI_GR_MOVE, 45, 45)

GUICtrlSetGraphic(-1, $GUI_GR_LINE, $xpos+45, $ypos+45)

$label_speed = GUICtrlCreateLabel("", 35,67,30,16,$SS_RIGHT)

GUICtrlSetData ( $label_date, $date)

GUICtrlSetData ( $label_time, $time)

GUICtrlSetFont ($label_speed, 10,800)

GUICtrlSetData ( $label_speed, $speed)

GUISetState(@SW_SHOW)

EndFunc

Func Finish()

Exit

EndFunc

Share this post


Link to post
Share on other sites



What do you mean by the commands seeming to accumulate?


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.

Share this post


Link to post
Share on other sites

If you run the script, you'll find that "old" needle positions are visible during the update. I thought that the elements were children of the control, but deleting the control doesn't seem to delete the elements. As time goes by, the update takes longer and longer, and the Task Manager shows more and more memory being used. You can see pixels flashing by of the prior needle positions dueing the redraw.

I've added msgbox's in the delete control conditional, and they seem to be happening.

What do you mean by the commands seeming to accumulate?

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

If you run the script, you'll find that "old" needle positions are visible during the update. I thought that the elements were children of the control, but deleting the control doesn't seem to delete the elements. As time goes by, the update takes longer and longer, and the Task Manager shows more and more memory being used. You can see pixels flashing by of the prior needle positions dueing the redraw.

I've added msgbox's in the delete control conditional, and they seem to be happening.

Maybe this is better

#include <INet.au3>
#include <GuiConstantsEx.au3>
#include <GDIPlus.au3>
#include <WindowsConstants.au3>
#Include <WinAPI.au3>
#include <StaticConstants.au3>
Global Const $WS_EX_COMPOSITED = 0x2000000
Opt("GUIOnEventMode", 1)
global $meter = 0,$lock = false
$dir = 0
global $label_speed = 0
$pi = 3.14159
$font = "Tahoma"
; Create GUI & label controls
$hGUI = GUICreate("GUIone", 100, 120, -1, -1, $WS_CAPTION, BitOr($WS_EX_COMPOSITED,$WS_EX_TOOLWINDOW))
$label_date = GUICtrlCreateLabel("", 10, 0, 80, 14, $SS_Center)
$label_time = GUICtrlCreateLabel("", 10, 15, 80, 14, $SS_Center)
Global $inpaint = false
GUIRegisterMsg($WM_PAINT, "Paint")
GUISetOnEvent($GUI_EVENT_RESTORE, "Paint")
GUISetOnEvent($GUI_EVENT_CLOSE, "Finish")
GUISetState()
paint()
adlibenable("paint1",1000);allow clock to keep going when gui is being moved
While 1
    
    Sleep(100)
WEnd


Func paint1()
    $dir += 2;increment here otherwise if paint is called by WM_PAINT then the value 
;of dir is incremented when it shouldn't be and causes the flickering lines in wrong place
    paint()
EndFunc


Func Paint()
    $radius = 40
    

; stuff to generate data goes here, but isn't included
    $date = "Aug 8, 2008"
    $time = "17:30pm"
    $speed = 13.7
    
; delete controls if they exist
    If $meter <> 0 Then GUICtrlDelete($meter)
    
    If $label_speed <> 0 Then GUICtrlDelete($label_speed)

    $meter = GUICtrlCreateGraphic(5, 30, 90, 90)
    GUICtrlSetGraphic(-1, $GUI_GR_PENSIZE, 2)
    GUICtrlSetGraphic(-1, $GUI_GR_COLOR, 0x000000, 0x888888)
    GUICtrlSetGraphic(-1, $GUI_GR_ELLIPSE, 5, 5, 80, 80)
    GUICtrlSetGraphic(-1, $GUI_GR_COLOR, 0x000000, 0xcccccc)
; tick marks on dial
    For $index = 0 To 16
        $xsp = $radius * Sin($pi * $index / 8)
        $ysp = -1 * $radius * Cos($pi * $index / 8)
        $xep = 1.15 * $radius * Sin($pi * $index / 8)
        $yep = -1.15 * $radius * Cos($pi * $index / 8)
        GUICtrlSetGraphic(-1, $GUI_GR_MOVE, $xsp + 45, $ysp + 45)
        GUICtrlSetGraphic(-1, $GUI_GR_LINE, $xep + 45, $yep + 45)
    Next
    $xpos = 35 * Sin($pi * $dir / 180)
    $ypos = -35 * Cos($pi * $dir / 180)
    GUICtrlSetGraphic(-1, $GUI_GR_MOVE, 45, 45)
    GUICtrlSetGraphic(-1, $GUI_GR_LINE, $xpos + 45, $ypos + 45)
    $label_speed = GUICtrlCreateLabel("", 35, 67, 30, 16, $SS_RIGHT)

    GUICtrlSetData($label_date, $date)
    GUICtrlSetData($label_time, $time)
    GUICtrlSetFont($label_speed, 10, 800)
    GUICtrlSetData($label_speed, $speed)
;GUISetState(@SW_SHOW)
EndFunc  ;==>Paint

Func Finish()
    Exit
EndFunc  ;==>Finish
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.

Share this post


Link to post
Share on other sites

It does work better. It's not the paint1() issue, though, since my $dir value is actually extracted from an RSS feed, and isn't very dynamic. The "accumulation" only shows up after days of execution. It must have to do with the other changes you made, which I'll scratch my head over.

Maybe this is better

#include <INet.au3>
#include <GuiConstantsEx.au3>
#include <GDIPlus.au3>
#include <WindowsConstants.au3>
#Include <WinAPI.au3>
#include <StaticConstants.au3>
Global Const $WS_EX_COMPOSITED = 0x2000000
Opt("GUIOnEventMode", 1)
global $meter = 0,$lock = false
$dir = 0
global $label_speed = 0
$pi = 3.14159
$font = "Tahoma"
; Create GUI & label controls
$hGUI = GUICreate("GUIone", 100, 120, -1, -1, $WS_CAPTION, BitOr($WS_EX_COMPOSITED,$WS_EX_TOOLWINDOW))
$label_date = GUICtrlCreateLabel("", 10, 0, 80, 14, $SS_Center)
$label_time = GUICtrlCreateLabel("", 10, 15, 80, 14, $SS_Center)
Global $inpaint = false
GUIRegisterMsg($WM_PAINT, "Paint")
GUISetOnEvent($GUI_EVENT_RESTORE, "Paint")
GUISetOnEvent($GUI_EVENT_CLOSE, "Finish")
GUISetState()
paint()
adlibenable("paint1",1000);allow clock to keep going when gui is being moved
While 1
    
    Sleep(100)
WEnd


Func paint1()
    $dir += 2;increment here otherwise if paint is called by WM_PAINT then the value 
;of dir is incremented when it shouldn't be and causes the flickering lines in wrong place
    paint()
EndFunc


Func Paint()
    $radius = 40
    

; stuff to generate data goes here, but isn't included
    $date = "Aug 8, 2008"
    $time = "17:30pm"
    $speed = 13.7
    
; delete controls if they exist
    If $meter <> 0 Then GUICtrlDelete($meter)
    
    If $label_speed <> 0 Then GUICtrlDelete($label_speed)

    $meter = GUICtrlCreateGraphic(5, 30, 90, 90)
    GUICtrlSetGraphic(-1, $GUI_GR_PENSIZE, 2)
    GUICtrlSetGraphic(-1, $GUI_GR_COLOR, 0x000000, 0x888888)
    GUICtrlSetGraphic(-1, $GUI_GR_ELLIPSE, 5, 5, 80, 80)
    GUICtrlSetGraphic(-1, $GUI_GR_COLOR, 0x000000, 0xcccccc)
; tick marks on dial
    For $index = 0 To 16
        $xsp = $radius * Sin($pi * $index / 8)
        $ysp = -1 * $radius * Cos($pi * $index / 8)
        $xep = 1.15 * $radius * Sin($pi * $index / 8)
        $yep = -1.15 * $radius * Cos($pi * $index / 8)
        GUICtrlSetGraphic(-1, $GUI_GR_MOVE, $xsp + 45, $ysp + 45)
        GUICtrlSetGraphic(-1, $GUI_GR_LINE, $xep + 45, $yep + 45)
    Next
    $xpos = 35 * Sin($pi * $dir / 180)
    $ypos = -35 * Cos($pi * $dir / 180)
    GUICtrlSetGraphic(-1, $GUI_GR_MOVE, 45, 45)
    GUICtrlSetGraphic(-1, $GUI_GR_LINE, $xpos + 45, $ypos + 45)
    $label_speed = GUICtrlCreateLabel("", 35, 67, 30, 16, $SS_RIGHT)

    GUICtrlSetData($label_date, $date)
    GUICtrlSetData($label_time, $time)
    GUICtrlSetFont($label_speed, 10, 800)
    GUICtrlSetData($label_speed, $speed)
;GUISetState(@SW_SHOW)
EndFunc ;==>Paint

Func Finish()
    Exit
EndFunc ;==>Finish

Share this post


Link to post
Share on other sites

I'm still confused. The "fix" for the appearance seems to be the $WS_EX_COMPOSITED = 0x2000000 parameter, but it also causes a constant update, burning 20% of one of my processors. I looked in WindowsConstants.au3 and that bit appears to be $WS_CLIPCHILDREN, which makes no sense to me at all (neither the fixing the problem part nor the constant refresh).

It does work better. It's not the paint1() issue, though, since my $dir value is actually extracted from an RSS feed, and isn't very dynamic. The "accumulation" only shows up after days of execution. It must have to do with the other changes you made, which I'll scratch my head over.

Share this post


Link to post
Share on other sites

I see I confused Styles with Extended_Styles. Regardless, the $WS_EX_COMPOSITED forces constant redraws (and a constant increase in memory usage), so I'm thinking the orphaned stuff is still around, but just not being seen due to the double buffering.

I'm still confused. The "fix" for the appearance seems to be the $WS_EX_COMPOSITED = 0x2000000 parameter, but it also causes a constant update, burning 20% of one of my processors. I looked in WindowsConstants.au3 and that bit appears to be $WS_CLIPCHILDREN, which makes no sense to me at all (neither the fixing the problem part nor the constant refresh).

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

I see I confused Styles with Extended_Styles. Regardless, the $WS_EX_COMPOSITED forces constant redraws (and a constant increase in memory usage), so I'm thinking the orphaned stuff is still around, but just not being seen due to the double buffering.

I think the problem is having controls created and destroyed in the function called by WM_PAINT. When a visible control is created or destroyed inside a function called by WM_PAINT I imagine it causes problems with the function being called again while the function is still being executed.

If you make 2 separate functions so that WM_PAINT doesn't destroy or create controls which have to be drawn then I think the problem will go away, something like this

#include <INet.au3>
#include <GuiConstantsEx.au3>
#include <GDIPlus.au3>
#include <WindowsConstants.au3>
#Include <WinAPI.au3>
#include <StaticConstants.au3>

Global Const $WS_EX_COMPOSITED = 0x2000000
Opt("GUIOnEventMode", 1)

Global $label_speed = 0, $meter = 0, $dir = 0, $radius = 40
; stuff to generate data goes here, but isn't included
Global $date = "Aug 8, 2008", $time = "17:30pm", $speed = 13.7, $pi = 3.14159, $font = "Tahoma"

; Create GUI & label controls
$hGUI = GUICreate("GUIone", 100, 120, -1, -1, $WS_CAPTION, $WS_EX_TOOLWINDOW); BitOr($WS_EX_COMPOSITED,$WS_EX_TOOLWINDOW))
$label_date = GUICtrlCreateLabel("", 10, 0, 80, 14, $SS_Center)
$label_time = GUICtrlCreateLabel("", 10, 15, 80, 14, $SS_Center)
GUIRegisterMsg($WM_PAINT, "RePaint")
GUISetOnEvent($GUI_EVENT_RESTORE, "RePaint")
GUISetOnEvent($GUI_EVENT_CLOSE, "Finish")
GUISetState()
$label_speed = GUICtrlCreateLabel("", 35, 67, 30, 16, $SS_RIGHT)
Paint()
AdlibEnable("paint", 1000)
While 1
    Sleep(100)
WEnd


Func RePaint()
    
    GUICtrlSetGraphic($meter, $GUI_GR_PENSIZE, 2)
    GUICtrlSetGraphic($meter, $GUI_GR_COLOR, 0x000000, 0x888888)
    GUICtrlSetGraphic($meter, $GUI_GR_ELLIPSE, 5, 5, 80, 80)
    GUICtrlSetGraphic($meter, $GUI_GR_COLOR, 0x000000, 0xcccccc)
    
; tick marks on dial
    For $index = 0 To 16
        $xsp = $radius * Sin($pi * $index / 8)
        $ysp = -1 * $radius * Cos($pi * $index / 8)
        $xep = 1.15 * $radius * Sin($pi * $index / 8)
        $yep = -1.15 * $radius * Cos($pi * $index / 8)
        GUICtrlSetGraphic($meter, $GUI_GR_MOVE, $xsp + 45, $ysp + 45)
        GUICtrlSetGraphic($meter, $GUI_GR_LINE, $xep + 45, $yep + 45)
    Next
    $xpos = 35 * Sin($pi * $dir / 180)
    $ypos = -35 * Cos($pi * $dir / 180)
    GUICtrlSetGraphic($meter, $GUI_GR_MOVE, 45, 45)
    GUICtrlSetGraphic($meter, $GUI_GR_LINE, $xpos + 45, $ypos + 45)

    GUICtrlSetData($label_date, $date)
    GUICtrlSetData($label_time, $time)
    If $label_speed <> 0 Then GUICtrlSetFont($label_speed, 10, 800)
    GUICtrlSetData($label_speed, $speed)
    
EndFunc  ;==>RePaint

Func Paint()
    
    $dir += 2
    
; delete control if it exists
    
    If $meter <> 0 Then
        GUICtrlDelete($meter)
        $meter = 0
    EndIf

    $meter = GUICtrlCreateGraphic(5, 30, 90, 90)
    repaint()
    
    
EndFunc  ;==>Paint

Func Finish()
    Exit
EndFunc  ;==>Finish
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.

Share this post


Link to post
Share on other sites

Thanks a heap! That seems to do just what I was looking for - good diagnosis!

I think the problem is having controls created and destroyed in the function called by WM_PAINT. When a visible control is created or destroyed inside a function called by WM_PAINT I imagine it causes problems with the function being called again while the function is still being executed.

If you make 2 separate functions so that WM_PAINT doesn't destroy or create controls which have to be drawn then I think the problem will go away, something like this

#include <INet.au3>
#include <GuiConstantsEx.au3>
#include <GDIPlus.au3>
#include <WindowsConstants.au3>
#Include <WinAPI.au3>
#include <StaticConstants.au3>

Global Const $WS_EX_COMPOSITED = 0x2000000
Opt("GUIOnEventMode", 1)

Global $label_speed = 0, $meter = 0, $dir = 0, $radius = 40
; stuff to generate data goes here, but isn't included
Global $date = "Aug 8, 2008", $time = "17:30pm", $speed = 13.7, $pi = 3.14159, $font = "Tahoma"

; Create GUI & label controls
$hGUI = GUICreate("GUIone", 100, 120, -1, -1, $WS_CAPTION, $WS_EX_TOOLWINDOW); BitOr($WS_EX_COMPOSITED,$WS_EX_TOOLWINDOW))
$label_date = GUICtrlCreateLabel("", 10, 0, 80, 14, $SS_Center)
$label_time = GUICtrlCreateLabel("", 10, 15, 80, 14, $SS_Center)
GUIRegisterMsg($WM_PAINT, "RePaint")
GUISetOnEvent($GUI_EVENT_RESTORE, "RePaint")
GUISetOnEvent($GUI_EVENT_CLOSE, "Finish")
GUISetState()
$label_speed = GUICtrlCreateLabel("", 35, 67, 30, 16, $SS_RIGHT)
Paint()
AdlibEnable("paint", 1000)
While 1
    Sleep(100)
WEnd


Func RePaint()
    
    GUICtrlSetGraphic($meter, $GUI_GR_PENSIZE, 2)
    GUICtrlSetGraphic($meter, $GUI_GR_COLOR, 0x000000, 0x888888)
    GUICtrlSetGraphic($meter, $GUI_GR_ELLIPSE, 5, 5, 80, 80)
    GUICtrlSetGraphic($meter, $GUI_GR_COLOR, 0x000000, 0xcccccc)
    
; tick marks on dial
    For $index = 0 To 16
        $xsp = $radius * Sin($pi * $index / 8)
        $ysp = -1 * $radius * Cos($pi * $index / 8)
        $xep = 1.15 * $radius * Sin($pi * $index / 8)
        $yep = -1.15 * $radius * Cos($pi * $index / 8)
        GUICtrlSetGraphic($meter, $GUI_GR_MOVE, $xsp + 45, $ysp + 45)
        GUICtrlSetGraphic($meter, $GUI_GR_LINE, $xep + 45, $yep + 45)
    Next
    $xpos = 35 * Sin($pi * $dir / 180)
    $ypos = -35 * Cos($pi * $dir / 180)
    GUICtrlSetGraphic($meter, $GUI_GR_MOVE, 45, 45)
    GUICtrlSetGraphic($meter, $GUI_GR_LINE, $xpos + 45, $ypos + 45)

    GUICtrlSetData($label_date, $date)
    GUICtrlSetData($label_time, $time)
    If $label_speed <> 0 Then GUICtrlSetFont($label_speed, 10, 800)
    GUICtrlSetData($label_speed, $speed)
    
EndFunc ;==>RePaint

Func Paint()
    
    $dir += 2
    
; delete control if it exists
    
    If $meter <> 0 Then
        GUICtrlDelete($meter)
        $meter = 0
    EndIf

    $meter = GUICtrlCreateGraphic(5, 30, 90, 90)
    repaint()
    
    
EndFunc ;==>Paint

Func Finish()
    Exit
EndFunc ;==>Finish

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
Sign in to follow this  
Followers 0