🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: borland.public.cppbuilder.nativeapi
3 messages
3 total messages Started by Phuoc Can HUA Tue, 04 Mar 2003 00:26
OnPaint with Semaphore seems not working...
#17730
Author: Phuoc Can HUA
Date: Tue, 04 Mar 2003 00:26
25 lines
2137 bytes
I've posted a problem with Canvas->CopyRect sometime ago. It seems I found
the reason of that problem. But still can't solve it  :-(

In my program, I'm using a WorkSpace (Bitmap) to apply all the graphic
operations (e.g. CopyRect). Then I use CopyRect to copy the updated area
from WorkSpace to a PaintBox (visible Bitmap). At the same time, I'm using a
OnPaint procedure which is copying the entire WorkSpace into PaintBox.
Everything seems OK when I was using TTimer to draw my WorkSpace.

Now I changed my program to use TThread to draw on the WorkSpace.
Unfortunately, it could happen that while the thread is drawing the OnPaint
procedure is called, i.e. the PaintBox is restored with an unfinished image.

Now I'm trying to use Semaphore (max value= 1) to fix it. I use
WaitForSingleObject() and ReleaseSemaphore() to enclose the codes of
modifying the WorkSpace and also enclose the OnPaint codes. I hope if
OnPaint is called and WorkSpace is busy OnPaint will wait until WorkSpace
Semaphore is released. But it seems there's no effect at all :-(

What did I do wrong? I also read something about EnterCriticalSection(), I
thought I don't need it because I'm usig only one flag, do I need it?
Any better solution?

Thanks
Phuoc Can HUA
Re: OnPaint with Semaphore seems not working...
#17754
Author: Phuoc Can HUA
Date: Tue, 04 Mar 2003 22:03
60 lines
3678 bytes
Oliver,
You are ABSOLUTELY right. Canvas is a pain in thread  :-(
I just found out that it wasn't the (only) problem that the unfinished image
is copied. It's simply the CopyRect gets crazy. Before, I was moving some
windows around while my program was running. Therefore I assumed that the
OnPaint came in place. But then I found out that also happens even I just
move the mouse pointer around, which is not triggering the OnPaint event at
all. The funny thing is if I leave my program running without any movement
the graphic is fine. Luckily, I found someone has experienced the same thing
:-)

I used to use WinAPI to draw. But then I thought that's the time of Win3.x
and it's no long up-to-date :-) So, I tried the BCB lib.
Can you give me any advice to convert my CopyRect to WinAPI? Is there a
similar function and with binary operation (CopyMode)?
Since I also plan to compile my program with Kylix for Linux (maybe one day)
:-)  shouldn't I avoid to use too many WinAPI's, what do you think?
Should I have a look in SDL (www.libsdl.org)? Will I have the same problem
with SDL?


Vielen Dank
Phuoc Can HUA


"Oliver Rutsch" <nospam@sympatec.com> wrote in message
news:1046770772.980524@post.sympatec.net...
> Hi Phuoc,
> [...]
> >
>
> Normally you should use the Canvas->Lock(), Canvas->Unlock() and
> Canvas->TryLock() for this purpose. If you don't trust it, you can also
> use a TCriticalSection (i think the VCL locking functions are using
> critical sections internally, too) for your locking mechanism. Although
> you can use a semaphore for this purpose, it is more likely designed for
> instance or resource counters from different processes (global sync
> object like a named mutex).
> But as I wrote before I don't think that it will help to solve your
> problem. I tried every known locking mechanism in the Paint() function
> of my component and nothing helped. The Canvas->Handle sometimes got
> invalid (the VCL throws NO exception in that case, it just does
> something stupid...) and then you're lost. Using the Win32 API functions
> for drawing looks like a bad idea, but once started it is not too much
> work, because you have a lot of functions you can use nearly in the same
> way as the Canvas does.
> Again, the GUI functions of the VCL are not designed for multithreading,
> so I would check if it is really neccessary to use multithreaded visual
> components. Keep your main thread free to update your user interface and
> start some worker threads for the rest.
>
> Hope that helps.
>
> Bye,
>
> --
> Dipl. Ing. Oliver Rutsch
> EMail: orutsch at sympatec.com
> Sympatec GmbH Germany
>
Re: OnPaint with Semaphore seems not working...
#17675
Author: Oliver Rutsch
Date: Wed, 05 Mar 2003 08:28
108 lines
5034 bytes
Hi Phuoc,
[...]
> all. The funny thing is if I leave my program running without any movement
> the graphic is fine. Luckily, I found someone has experienced the same thing
> :-)

Yes, unfortunately that is exactly what I found.

> 
> I used to use WinAPI to draw. But then I thought that's the time of Win3.x
> and it's no long up-to-date :-) So, I tried the BCB lib.
> Can you give me any advice to convert my CopyRect to WinAPI? Is there a
> similar function and with binary operation (CopyMode)?

O.K. Here's some example code from one of my components. It is derived 
from TCustomControl and does nothing else but painting some rotating 
gears out of a resource. Paint() is called from the thread because I 
want that it looks smooth, even if the main thread has some work to do. 
Looks cool ;-) Do you have access to the MSDN? There is a lot of 
information to all the commands I used. Too much to mention here ;-)

void __fastcall TWxGears::Paint()
{
   // Don't do anything if your component is not visible
   if (!Visible)
     return;
   // Stop drawing if the component gets destroyed
   if (ComponentState.Contains(csDestroying))
     return;
   // PaintLock is a TCriticalSection, Lock the section
   PaintLock->Acquire();
   HDC MyDC;
   HDC hdcCompatible;
   DWORD Index;
   String ResName;
   HBITMAP MyBitmap;
   try
   {
     // Get the device context of the components window handle
     // Don't cache this, because the handle to the DC can only
     // be used by a single thread at any one time.

     MyDC=GetDC(Handle);
     // throws are just for testing purpose
     if (!MyDC)
       throw 0;
     // Load a bitmap out of a resource
     Index=PicCounter%NumBitmaps;
     ResName="GEAR"+String(Index+1)+"_"+String(EnumToSize(Size));
     MyBitmap=LoadBitmap((void*)HInstance,ResName.c_str());
     if (!MyBitmap)
       throw 1;
     // Create a memory device context
     hdcCompatible = CreateCompatibleDC(MyDC);
     if (!hdcCompatible)
       throw 2;
     // ...and select the bitmap into the dc
     if (!SelectObject(hdcCompatible, MyBitmap))
       throw 3;
     DWORD Offset=FRaised ? 3 : 0;
     // Gr��e ge�ndert ?
     ClientHeight=EnumToSize(Size)+Offset*2;
     ClientWidth=EnumToSize(Size)+Offset*2;
     // blit the bitmap into the components surface
     // have a look at the last parameter, it defines the
     // copy mode
     if (!BitBlt(MyDC,Offset,Offset,ClientWidth,ClientHeight, 
hdcCompatible,0,0,SRCCOPY))
       throw 4;
     if (FRaised)
     {
       RECT MyRect;
       MyRect.left=0;
       MyRect.top=0;
       MyRect.right=ClientWidth;
       MyRect.bottom=ClientHeight;
       // Draw a nice border if raised 	
       if (!DrawEdge(MyDC,&MyRect,EDGE_RAISED,BF_RECT))
         throw 5;
     }
   }
   catch(...){}
   // free resources
   ReleaseDC(Handle,MyDC);
   DeleteDC(hdcCompatible);
   DeleteObject(MyBitmap);
   PaintLock->Release();
}


> Since I also plan to compile my program with Kylix for Linux (maybe one day)
> :-)  shouldn't I avoid to use too many WinAPI's, what do you think?
> Should I have a look in SDL (www.libsdl.org)? Will I have the same problem
> with SDL?
> 
If you plan multiplatform developing then I would avoid multithreaded 
visual components. For multithreading I would look at some multiplatform 
frameworks like ACE (has some very nice multithreading classes, but it 
is NOT a GUI framework!) and avoid pure Win32 API.
Hmm, as far as I know SDL is for developing games and not a 
GUI-Framework like the VCL. I don't know more about this library, sorry.

Bye,

-- 
Dipl. Ing. Oliver Rutsch
EMail: orutsch at sympatec.com
Sympatec GmbH Germany
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads