Sign in to follow this  
Followers 0
jezzzzy

GUICtrlSetImage Flicker

16 posts in this topic

#1 ·  Posted (edited)

I am creating an image view to view security cam images. They need to be viewed rapidly one after the other. I'm using GUICtrlSetImage in the code below but it displays substantial flicker during the image display. I searched the forums for this problem and have tried deleting the $pic instance and recreating it in the loop, however, this creates a very consistent flicker while the $pic control is being deleted and the background of the GUI shows through before the new $pic control is created. Not sure how to fix this.

Case $msg = $pic
            ;find files from Feb 6, 2007 - 10th hour - only
            $search = FileFindFirstFile($imagePath & $filePrefix & "070206_10*.jpg")
                GUICtrlSetImage($pic,$imagePath & $search) ;show first image
            While 1
                $msg = GUIGetMsg()
                Select
                    Case $msg = $pic
                        ExitLoop
                EndSelect
                
                $file = FileFindNextFile($search)
                If @error then ExitLoop
                GUICtrlSetImage($pic,$imagePath & $file) 
                ;Sleep(100)
            WEnd
            FileClose($search)

Edit: typo

Edited by jezzzzy

Share this post


Link to post
Share on other sites

#2 ·  Posted (edited)

Use two controls....draw the next pic before removing the old one?

Edited by Blue_Drache

Lofting the cyberwinds on teknoleather wings, I am...The Blue Drache

Share this post


Link to post
Share on other sites

Good Idea. I'll try that now.

Use two controls....draw the next pic before removing the old one?

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

Ok. Tried Blue_Drache's double picture box idea and unless I'm doing it wrong, it still flickers significantly. Almost as if the new picture isn't being drawn before the old one is deleted. I even added a little pause before the old image was deleted. It almost looks like the old image isn't being deleted at all. Here's the code:

Case $msg = $button
            $count = 0
            ;find images from Feb 6, 2007 - 10th hour - only for testing
            $search = FileFindFirstFile($imagePath & $filePrefix & "070206_10*.jpg")
                GUICtrlSetImage($pic1,$imagePath & $search) ;show first image
            While 1
                $msg = GUIGetMsg()
                Select
                    Case $msg = $button
                        ExitLoop
                EndSelect
                
                    If $count = 0 Then
                        $file = FileFindNextFile($search)
                        If @error then ExitLoop
                        $pic2 = GUICtrlCreatePic($imagePath & $file,10,10,352,240,-1,$WS_EX_CLIENTEDGE)
                        Sleep(100)
                        GUICtrlDelete($pic1)
                        $count = $count + 1
                    EndIf

                    If $count = 1 Then
                        $file = FileFindNextFile($search)
                        If @error then ExitLoop
                        $pic1 = GUICtrlCreatePic($imagePath & $file,10,10,352,240,-1,$WS_EX_CLIENTEDGE)
                        Sleep(100)
                        GUICtrlDelete($pic2)
                        $count = $count - 1
                    EndIf
            WEnd
            FileClose($search)

Edit: Code edit

Edited by jezzzzy

Share this post


Link to post
Share on other sites

Bump

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

Bump

Well, it looks to me like you're updating these pics as FAST as the computer can go. I had a similar problem with my GUI when I had it check the state of some windows and then update a picture and label on my custom GUI. It updates no matter what, and at several times a second ... it will flicker.

My solution? Build an if/then that only checks once every X seconds:

While 1
    Sleep(10)
    If Mod(@SEC, 4) = 0 Then ; Check the status of the buttons and lamps once every 4 seconds.  Change if required.
        If $i_ModFlag = 0 Then
            _LoliCheck()
            $i_ModFlag = 1
        EndIf
    Else
        $i_ModFlag = 0
    EndIf
; More stuff ...
Exit

#region Function: Lollipop check
Func _LoliCheck()
     ; Do what you need to do here when it fires.
EndFunc   ;==>_LoliCheck
#endregion
Edited by Blue_Drache

Lofting the cyberwinds on teknoleather wings, I am...The Blue Drache

Share this post


Link to post
Share on other sites

Look here and here

Read all posts in these topics, the most important is this one --> (double rendering of image after GUICtrlSetImage - first at original size second in resized size).

Also look here at my Delphi antiflicker project.

Also look at Blackjack where are done some Autoit antiflicker methods

More peoples have the same problem as you and me :) see here

unfortunatelly developers didn't solved it yet (double rendering of image after GUICtrlSetImage - first at original size second in resized size).

Now there are some chances to make some workaround with GUIRegisterMsg or Direct3D plugin but I didn't try to go make one yet.

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

Here's a ruff example of using A2D1.1 old plugin by chris95219 to show pictures quickly without the flicker.

The example is looking for *.jpg in Windows\Web\Wallpaper directory. (change path to suite yourself)

It is just looping the found pictures until escape it pressed.

For the example to work you'll need the most current directx 9c updates (April 2007 is the most current dx atm)

Info about the old A2D 1.1 plugin Here

Info about latest A2D 2.0 plugin Here

Example: Removed (later post in this thread has updated example).

Cheers

Edit: I've only tried this in Windows XP

Edited by smashly

Share this post


Link to post
Share on other sites

#10 ·  Posted

I have flicker problem in my Radar project (see my signature).

Because Autoit render picture twice after GUICtrlSetImage (by me it's bug)

I think best universal solution/workaround would be something like this:

- hide your picture control (GUICtrlSetImage stay as it is)

- trap WM_PAINT message with GUIRegisterMsg and

in this function make BitBlt() from hidden picture control's DC (device context) to GUI main window DC

I will try this method some day.

Share this post


Link to post
Share on other sites

#11 ·  Posted (edited)

I have flicker problem in my Radar project (see my signature).

Because Autoit render picture twice after GUICtrlSetImage (by me it's bug)

I think best universal solution/workaround would be something like this:

- hide your picture control (GUICtrlSetImage stay as it is)

- trap WM_PAINT message with GUIRegisterMsg and

in this function make BitBlt() from hidden picture control's DC (device context) to GUI main window DC

I will try this method some day.

I meant something like this but it's not working (nothing is painted on the form)

#include <GUIConstants.au3>

Opt("GUICloseOnESC",1)

Global $WM_PAINT = 0x000F
Global $hdc, $pic_hdc, $gui, $pic_hWnd

$gui = GUICreate("Test",1000,700)
$hdc = DllCall("user32.dll", "int", "GetDC", "hwnd", $gui)
$hdc = $hdc[0]

; picture size is 400x300 (resized to 800x600)
$pic = GUICtrlCreatePic('1.gif',0,0,800,600)
$pic_hWnd = ControlGetHandle("Test","",$pic)
$pic_hdc = DLLCall("user32.dll","int","GetDC","hwnd",$pic_hWnd)
$pic_hdc = $pic_hdc[0]

GUICtrlSetState($pic,$GUI_HIDE)
GUISetState (@SW_SHOW)

GUIRegisterMsg($WM_PAINT, 'MY_WM_PAINT')

While 1
    If GUIGetMsg() = $GUI_EVENT_CLOSE Then Exit
    
    For $i = 1 To 6
        GUICtrlSetImage ($pic, @Scriptdir & '\' & $i & '.gif')
        ; explicitly call this function because picture is hidden so WM_PAINT is not fired
        MY_WM_PAINT()
;~      Sleep(750)
    Next
;~  Sleep(3000)
Wend

Func OnAutoItExit()
    DLLCall("user32.dll","int","ReleaseDC","hwnd",$gui,"int",$hdc)
    DLLCall("user32.dll","int","ReleaseDC","hwnd",$pic_hWnd,"int",$pic_hdc)
EndFunc

Func MY_WM_PAINT()
    ; copy content of picture DC to main form DC
    _BitBlt($hdc, 0, 0, 800, 600, $pic_hdc, 0, 0)
    
    Return $GUI_RUNDEFMSG
EndFunc

Func _BitBlt($destination_hdc, $destination_x, $destination_y, $destination_width, $destination_height, _
        $source_hdc, $source_x, $source_y, $code = 0xCC0020, $dll_h = 'Gdi32.dll')
;~  Const $SRCCOPY = 0xCC0020
;~  [url=http://msdn.microsoft.com/library/en-us/gdi/bitmaps_0fzo.asp]http://msdn.microsoft.com/library/en-us/gdi/bitmaps_0fzo.asp[/url]
    Local $ret = DllCall($dll_h, 'int', 'BitBlt', _
            'ptr', $destination_hdc, _
            'int', $destination_x, _
            'int', $destination_y, _
            'int', $destination_width, _
            'int', $destination_height, _
            'ptr', $source_hdc, _
            'int', $source_x, _
            'int', $source_y, _
            'int', $code)
    Return $ret[0]
EndFunc   ;==>_BitBlt
Edited by Zedna

Share this post


Link to post
Share on other sites

#12 ·  Posted

Should this

$hdc = DllCall("user32.dll", "int", "GetDC", "hwnd", $gui)

be

$hdc = DllCall("user32.dll", "int", "GetDC", "hwnd", WinGetHandle($gui))

??


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

#13 ·  Posted

Should this

$hdc = DllCall("user32.dll", "int", "GetDC", "hwnd", $gui)

be

$hdc = DllCall("user32.dll", "int", "GetDC", "hwnd", WinGetHandle($gui))

??

No. It isn't neccessary. GUICreate() returns a windows handle - see helpfile

Share this post


Link to post
Share on other sites

#14 ·  Posted

My idea why it's not working:

GUICtrlSetImage() internal Autoit code maybe will not do paint to picture control's DC when it's state is $GUI_HIDE

It would be helpfull to see some related piece of Autoit source code for GUICtrlSetImage() and maybe also for main form WM_PAINT.

Share this post


Link to post
Share on other sites

This is perfect. No flicker. You're a gentleman and a scholar.

Here's a ruff example of using A2D1.1 old plugin by chris95219 to show pictures quickly without the flicker.

The example is looking for *.jpg in Windows\Web\Wallpaper directory. (change path to suite yourself)

It is just looping the found pictures until escape it pressed.

For the example to work you'll need the most current directx 9c updates (April 2007 is the most current dx atm)

Info about the old A2D 1.1 plugin Here

Info about latest A2D 2.0 plugin Here

Example:

Cheers

Edit: I've only tried this in Windows XP

Share this post


Link to post
Share on other sites

here's another rough unfinished example.

Just this example has added controls, so you can get an idea of how to use the a2d screen in your gui with controls.

Keyboard Keys:

UP, Down arrow to Auto loop through pictures forwards and backwards

Left, Right arrow while pressed will loop through pictures.

PageUp, PageDown will set the delay for how long a picture is displayed before moving onto the next picture.

Alt + Enter to toggle fullscreen/normal screen

Supports Drag & Drop of folder or Browse for folder.

Slider to scan through images quickly (reads while being slid)

Deley Time (combobox with preset increments)

picture formats supported are DDS, BMP, JPG, PNG (one format viewable at a time).

Cheers

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