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...
Author: Phuoc Can HUA
Date: Tue, 04 Mar 2003 00:26
Date: Tue, 04 Mar 2003 00:26
25 lines
2137 bytes
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...
Author: Phuoc Can HUA
Date: Tue, 04 Mar 2003 22:03
Date: Tue, 04 Mar 2003 22:03
60 lines
3678 bytes
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...
Author: Oliver Rutsch
Date: Wed, 05 Mar 2003 08:28
Date: Wed, 05 Mar 2003 08:28
108 lines
5034 bytes
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