πŸš€ go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: borland.public.cppbuilder.nativeapi
Article #4578

Re: Animation with TThread in non client area (border form)

#4578
From: Remy Lebeau (TeamB)
Date: Thu, 12 Jan 2006 20:14
257 lines
8059 bytes
"Carlos" <a@a.com> wrote in message news:43c6ac4c@newsgroups.borland.com...

> I donοΏ½t understand.

Like I said earlier, the thread code you showed earlier is not safe, and
using a thread is not necessary to begin with.

> This code works

Only out of luck.  The thread code is accessing memory that is not protected
from simultaneous access from multiple threads.  You have a good chance of
corrupting memory, since you are performing operations that can alter shared
memory while the main thread is using the same memory for other things.

> How could I draw in DC of Mainform in a safe manner ?

I already told you how - you have to use the thead's Synchronize() method,
ie:

    class TAnimationThread : public TThread
    {
    private:
        int FSpeed;
        bool FProgressBarEnabled;
        HWND FMainFormWnd;
        Graphics::TBitmap *FBitmap;
        int FIndex;
        int FWidth;

    protected:
        void __fastcall Execute()

        void __fastcall ProgressBarEnabledSync();
        bool __fastcall IsProgressBarEnabled();

        void __fastcall MainFormHandleSync();
        HWND __fastcall GetMainFormHandle();

        void __fastcall ImageSync();

        void __fastcall MainFormWidthSync();
        int __fastcall GetMainFormWidth();

    public:
        __fastcall TAnimationThread(int nSpeed);
    };


    __fastcall TAnimationThread::TAnimationThread(int nSpeed)
        : TThread(true)
    {
        FreeOnTerminate = true;
        FSpeed = nSpeed;
        Priority = tpHighest;
        Resume();
    }

    void __fastcall TAnimationThread::ProgressBarEnabledSync()
    {
        FProgressBarEnabled = FormMain->TimerProgressBar->Enabled;
    }

    bool __fastcall TAnimationThread::IsProgressBarEnabled()
    {
        Synchronize(ProgressBarEnabledSync);
        return FProgressBarEnabled;
    }

    void __fastcall TAnimationThread::MainFormHandleSync()
    {
        FMainFormWnd = FormMain->Handle;
    }

    HWND __fastcall TAnimationThread::GetMainFormHandle()
    {
        Synchronize(MainFormHandleSync);
        return FMainFormWnd;
    }

    void __fastcall TAnimationThread::ImageSync()
    {
        FormMain->ImageListAnimate->GetBitmap(FIndex, FBitmap);
    }

    void __fastcall TAnimationThread::MainFormWidthSync()
    {
        FWidth = FormMain->Width;;
    }

    int __fastcall TAnimationThread::GetMainFormWidth()
    {
        Synchronize(MainFormWidthSync);
        return FWidth;
    }

    void __fastcall TAnimationThread::Execute()
    {
        FIndex = 0;
        int nDir;

        FBitmap = new Graphics::TBitmap;
        try
        {
            TCanvas *pCanvas = new TCanvas;
            try
            {
                while( !Terminated )
                {
                    if( !IsProgressBarEnabled() )
                        FIndex = 0;

                    HWND hWnd = GetMainFormHandle();
                    HDC Dc = GetWindowDC(hWnd);
                    try
                    {
                        pCanvas->Handle = Dc;
                        try
                        {
                            int pMode = SetBkMode(Dc, TRANSPARENT);
                            try
                            {
                                Synchronize(ImageSync);
                                pCanvas->Draw(GetMainFormWidth() -
FBitmap->Width - 2, 2, FBitmap);
                            }
                            __finally {
                                SetBkMode(Dc, pMode);
                            }
                        }
                        __finally {
                            pCanvas->Handle = NULL;
                        }
                    }
                    __finally {
                        ReleaseDC(hWnd, Dc);
                    }

                    if( FIndex == 8 )
                        nDir = -1;
                    else if( FIndex == 0 )
                        nDir = 1;

                    FIndex += nDir;

                    Sleep(FSpeed);

                    if ( !IsProgressBarEnabled() )
                    {
                        FIndex = 0;
                        Terminate();
                    }
                }
            }
            __finally {
                delete pCanvas;
            }
        }
        __finally {
            delete FBitmap;
        }
    }


Or else get rid of the thread altogether and use a timer in the main thread
instead since your code is not benefitting from being threaded in the first
place:

    class TFormMain : public TForm
    {
    __published:
        TTimer *AnimationTimer;
        TImageList *ImageListAnimate;
        TProgressBar *TimerProgressBar;
        //...
        void __fastcall FormPaint(TObject *Sender);
        void __fastcall AnimationTimerTimer(TObject *Sender);
        //...
    private
        Graphics::TBitmap *FAnimationBitmap;
        int FAnimationIndex;
        //...
        void __fastcall AnimationBitmapChanged(TObject *Sender);
        //...
    public:
        __fastcall TFormMain(TComponent *Owner);
        __fastcall ~TFormMain();
        //...
        void __fastcall StartAnimation();
        void __fastcall StopAnimation();
    };


    __fastcall TFormMain::TFormMain(TComponent *Owner)
        : TForm(Owner)
    {
        FAnimationBitmap = Graphics::TBitmap;
        FAnimationBitmap->OnChange = AnimationBitmapChanged;
    }

    __fastcall TFormMain::~TFormMain()
    {
        delete FAnimationBitmap;
    }

    void __fastcall TFormMain::FormPaint(TObject *Sender)
    {
        if( !FAnimationBitmap->Empty )
        {
            // output the caption string
            int OldMode = SetBkMode(Canvas->Handle, TRANSPARENT);
            try {
                Canvas->Draw(Width - FAnimationBitmap->Width - 2, 2,
FAnimationBitmap);
            }
            __finally {
                SetBkMode(Canvas->Handle, OldMode);
            }
        }
    }

    void __fastcall TFormMain::AnimationTimerTimer(TObject *Sender)
    {
        if( !TimerProgressBar->Enabled )
            FAnimationIndex = 0;

        ImageListAnimate->GetBitmap(FAnimationIndex, FAnimationBitmap);

        if( FAnimationIndex == 8 )
            --FAnimationIndex;
        else if( FAnimationIndex == 0 )
            ++FAnimationIndex;

        if( !TimerProgressBar->Enabled )
            FAnimationIndex = 0;
    }

    void __fastcall TFormMain::AnimationBitmapChanged(TObject *Sender)
    {
        Invalidate();
    }

    void __fastcall TFormMain::StartAnimation()
    {
        AnimationTimer->Interval = 1000; // <-- use whatever interval you
want
        AnimationTimer->Enabled = true;
    }

    void __fastcall TFormMain::StopAnimation()
    {
        AnimationTimer->Enabled = false;
        FAnimationBitmap->Assign(NULL);
    }


Gambit
Technical Details
Message-ID: <43c6b80f$1@newsgroups.borland.com>
Path: arc1-ca.pugleaf.net!g2news1.google.com!news1.google.com!news3.google.com!border1.nntp.dca.giganews.com!nntp.giganews.com!newshub.sdsu.edu!logbridge.uoregon.edu!newsfeeds.ihug.co.nz!ihug.co.nz!newsgroups.borland.com!not-for-mail
References: <43c29a01@newsgroups.borland.com> <43c2b613$1@newsgroups.borland.com> <43c6ac4c@newsgroups.borland.com>

Show Full Headers
Complete Article Headers
X-Google-Thread: 10cc67,7abd13b8dc24dd8a
X-Google-Attributes: gid10cc67,public
X-Google-Language: ENGLISH,ASCII
From: "Remy Lebeau \(TeamB\)" <no.spam@no.spam.com>
Newsgroups: borland.public.cppbuilder.nativeapi
References: <43c29a01@newsgroups.borland.com> <43c2b613$1@newsgroups.borland.com> <43c6ac4c@newsgroups.borland.com>
Subject: Re: Animation with TThread in non client area (border form)
Date: Thu, 12 Jan 2006 12:14:31 -0800
Lines: 259
X-Priority: 3
X-MSMail-Priority: Normal
X-Newsreader: Microsoft Outlook Express 6.00.2800.1409
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1409
NNTP-Posting-Host: 68.69.17.41
Message-ID: <43c6b80f$1@newsgroups.borland.com>
X-Trace: newsgroups.borland.com 1137096719 68.69.17.41 (12 Jan 2006 12:11:59 -0700)
Path: arc1-ca.pugleaf.net!g2news1.google.com!news1.google.com!news3.google.com!border1.nntp.dca.giganews.com!nntp.giganews.com!newshub.sdsu.edu!logbridge.uoregon.edu!newsfeeds.ihug.co.nz!ihug.co.nz!newsgroups.borland.com!not-for-mail