 |
BorlandTalk.com Borland discussion newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Analian Guest
|
Posted: Sun May 22, 2005 8:27 am Post subject: Prevent refreshing of a TImage? |
|
|
I've got a TImage component on which I draw lines. I'm performing lots of
calculations which take for about 2 minutes. At certain states of these 2
minutes I draw I single line on the Image and call
Application->ProcessMessages() to make sure that the line is drawn
immediately or else all the lines would be drawn at the end when the calcs
finish. But I want to preserve this dynamic displaying of the lines and the
problem is that everytime a single line is drawn and then
Application->ProcessMessages() i called the Image seems to repaint _all_ of
its surface and thus drawing 2000 single lines in 2 minutes results in a lot
of flicker. Well I don't want the Image to refresh at all until all the
calculations are done so I would avoid the flicker. How can I accomplish
this? Thank you.
|
|
| Back to top |
|
 |
JD Guest
|
Posted: Sun May 22, 2005 9:42 am Post subject: Re: Prevent refreshing of a TImage? |
|
|
"Analian" <analian (AT) mail (DOT) bg> wrote:
| Quote: |
[...] I don't want the Image to refresh at all until all the
calculations are done [...]
|
Use the win32 API SendMesssage to disable and reenable an
objects refresh. When finished, manually refresh to show your
work:
::SendMessage( Image1->Handle, WM_SETREDRAW, FALSE, 0 );
// your drawing code
::SendMessage( Image1->Handle, WM_SETREDRAW, TRUE, 0 );
Image1->Refresh();
~ JD
|
|
| Back to top |
|
 |
Analian Guest
|
Posted: Sun May 22, 2005 10:30 am Post subject: Re: Prevent refreshing of a TImage? |
|
|
| Quote: | ::SendMessage( Image1->Handle, WM_SETREDRAW, FALSE, 0 );
// your drawing code
::SendMessage( Image1->Handle, WM_SETREDRAW, TRUE, 0 );
Image1->Refresh();
|
Umm.. Handle is not a member of the TImage component. Then how do I get the
handle needed?
|
|
| Back to top |
|
 |
JD Guest
|
Posted: Sun May 22, 2005 10:55 am Post subject: Re: Prevent refreshing of a TImage? |
|
|
"Analian" <analian (AT) mail (DOT) bg> wrote:
| Quote: | ::SendMessage( Image1->Handle, WM_SETREDRAW, FALSE, 0 );
// your drawing code
::SendMessage( Image1->Handle, WM_SETREDRAW, TRUE, 0 );
Image1->Refresh();
Umm.. Handle is not a member of the TImage component. Then how do I get the
handle needed?
|
Sorry about that. You can use the Image->Canvas->Handle but
that will throw if the underlying image is not a TBitmap.
~ JD
|
|
| Back to top |
|
 |
Analian Guest
|
Posted: Sun May 22, 2005 11:32 am Post subject: Re: Prevent refreshing of a TImage? |
|
|
"JD" <nospam (AT) nospam (DOT) com> wrote
| Quote: |
"Analian" <analian (AT) mail (DOT) bg> wrote:
::SendMessage( Image1->Handle, WM_SETREDRAW, FALSE, 0 );
// your drawing code
::SendMessage( Image1->Handle, WM_SETREDRAW, TRUE, 0 );
Image1->Refresh();
Umm.. Handle is not a member of the TImage component. Then how do I get
the
handle needed?
Sorry about that. You can use the Image->Canvas->Handle but
that will throw if the underlying image is not a TBitmap.
~ JD
|
::SendMessage(Form1->Image1->Canvas->Handle, WM_SETREDRAW, FALSE, 0);
Application->ProcessMessages();
// do calcs and single line drawals
::SendMessage(Form1->Image1->Canvas->Handle, WM_SETREDRAW, TRUE, 0);
Form1->MyImage1->Refresh();
Application->ProcessMessages();
and yet no effect.. The image continues to refresh after every line is
drawn. Any other suggestions?
|
|
| Back to top |
|
 |
JD Guest
|
Posted: Sun May 22, 2005 1:11 pm Post subject: Re: Prevent refreshing of a TImage? |
|
|
"Analian" <analian (AT) mail (DOT) bg> wrote:
| Quote: |
::SendMessage(Form1->Image1->Canvas->Handle, WM_SETREDRAW, FALSE, 0);
Application->ProcessMessages();
|
You don't need to process message here. SendMessage waits for
it to be executed.
| Quote: | Any other suggestions?
|
I don't have a compiler on this machine so I can't test it for you. Try using the Bitmap's handle.
~ JD
|
|
| Back to top |
|
 |
Analian Guest
|
Posted: Sun May 22, 2005 2:38 pm Post subject: Re: Prevent refreshing of a TImage? |
|
|
| Quote: | You don't need to process message here. SendMessage waits for
it to be executed.
Nice. I'll have that in mind in the future. |
| Quote: | I don't have a compiler on this machine so I can't test it for you. Try
using the Bitmap's handle.
|
The Bitmap handle doesn't work also. The Image->Picture property doesn't
have a handle and so again I'm stuck.
|
|
| Back to top |
|
 |
JD Guest
|
Posted: Sun May 22, 2005 7:27 pm Post subject: Re: Prevent refreshing of a TImage? |
|
|
"Analian" <analian (AT) mail (DOT) bg> wrote:
| Quote: |
[...] so again I'm stuck.
|
Then you have 2 choices:
Try putting the Image on a Panel and use the SendMessage with
the Panel's Handle.
The other is to use a second in-memory bitmap. When you begin
your drawing, first Assign the TImage::Bitmap to the TBitmap.
When finished drawing, Assign the TBitmap to the
TImage::Bitmap.
~ JD
|
|
| Back to top |
|
 |
Remy Lebeau (TeamB) Guest
|
Posted: Sun May 22, 2005 7:30 pm Post subject: Re: Prevent refreshing of a TImage? |
|
|
"JD" <nospam (AT) nospam (DOT) com> wrote
| Quote: | ::SendMessage( Image1->Handle, WM_SETREDRAW, FALSE, 0 );
// your drawing code
::SendMessage( Image1->Handle, WM_SETREDRAW, TRUE, 0 );
|
That won't work. TImage is a TGraphicControl descendant. It doesn't have a
window handle at all.
Gambit
|
|
| Back to top |
|
 |
Remy Lebeau (TeamB) Guest
|
Posted: Sun May 22, 2005 7:31 pm Post subject: Re: Prevent refreshing of a TImage? |
|
|
"JD" <nospam (AT) nospam (DOT) com> wrote
| Quote: | Sorry about that. You can use the Image->Canvas->Handle
|
A Canvas Handle is not a Window Handle. You cannot send messages to a
Canvas Handle.
Gambit
|
|
| Back to top |
|
 |
Analian Guest
|
Posted: Sun May 22, 2005 9:38 pm Post subject: Re: Prevent refreshing of a TImage? |
|
|
I put the Image into a ScrollBox and used the ScrollBox handle to prevent
redrawal but
now even the single lines aren't displayed when needed but all at the end.
Hm. What to do now?
|
|
| Back to top |
|
 |
JD Guest
|
Posted: Mon May 23, 2005 5:04 am Post subject: Re: Prevent refreshing of a TImage? |
|
|
"Analian" <analian (AT) mail (DOT) bg> wrote:
| Quote: |
[...] What to do now?
|
I would suggest using a TPaintBox instead of a TScrollBox ...
unless the image is larger than the screen height and/or
width. Then I would suggest putting the TPaintBox inside the
TScrollBox which is what I've done for a print preview.
Dynamically allocate a TBitmap that you do all of the drawing
on (all of you drawing code will be the same - just remove
the 'Image1->' part).
Add a definition for a TBitmap and a destructor to the header:
private: // User declarations
Graphics::TBitmap *pBitmap;
public: // User declarations
__fastcall ~TForm1();
Allocate the TBitmap in the constructor:
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
{
pBitmap = NULL;
pBitmap = new Graphics::TBitmap();
pBitmap->PixelFormat = pf24bit;
// Make sure that bitmap is usable when the
// TPaintBox tries to use it
pBitmap->Width = SomeWidth;
pBitmap->Height = SomeHeight;
// set the bitmap background
pBitmap->Canvas->Brush->Color = clFuchsia;
pBitmap->Canvas->FillRect( Rect(0, 0, SomeWidth, SomeHeight) );
// This can be done in the IDE
PaintBox1->SetBounds( PaintBox1->Left, PaintBox1->Top, PaintBox1->Left + SomeWidth, PaintBox1->Top + SomeHeight );
}
Delete the TBitmap in the destructor:
__fastcall TForm1::~TForm1()
{
delete pBitmap;
}
Add an OnPaint event to the TPaintBox. That's where the
TBitmap gets rendered to the screen:
void __fastcall TForm1::PaintBox1Paint(TObject *Sender)
{
PaintBox1->Canvas->CopyRect( R, pBitmap->Canvas, R );
}
The above assumes that the TRect R is the same dimensions for
the source and target TRect's. If you want to make it appear
larger or smaller, use 2 differently sized TRects and use
StretchDraw instead. If you're going to use StretchDraw, I
would suggest using an additional TBitmap that you StretchDraw
onto once and use only CopyRect to get the image to the screen
because it's much much faster.
If you put the TPainBox in a TScrollBox:
::SendMessage( ScrollBox1->Handle, WM_SETREDRAW, FALSE, 0 );
// drawing code goes here
::SendMessage( ScrollBox1->Handle, WM_SETREDRAW, TRUE, 0 );
ScrollBox1->Refresh();
other wise just add a bool flag that is set to true when
drawing and check that flag in the OnPaint event before you
render to the screen. When done drawing, you'll need to explicitly cause the TPaintBox to be repainted:
PaintBox1Paint( PaintBox1 );
or
PaintBox1Paint( this );
or
PaintBox1Paint( NULL );
it really doesn't matter what parameter you pass (as long as
the compiler doesn't complain) because the OnPaint event is
not using the Sender.
~ JD
|
|
| Back to top |
|
 |
JD Guest
|
Posted: Mon May 23, 2005 5:12 am Post subject: Re: Prevent refreshing of a TImage? |
|
|
"Remy Lebeau (TeamB)" <no.spam (AT) no (DOT) spam.com> wrote:
| Quote: |
[...] TImage is a TGraphicControl descendant. It doesn't
have a window handle at all.
|
I learned the hard way that TGraphicControl descendants don't
have window handles but for the hierarchy, I still depend
heavily on the docs and they simply weren't available for me.
~ JD
|
|
| Back to top |
|
 |
Analian Guest
|
Posted: Thu May 26, 2005 5:37 pm Post subject: Re: Prevent refreshing of a TImage? |
|
|
Isn't there a more direct way to prevent refreshing than using an other
component's (the paintbox) properties?
I guess this is a solution but I'd like to know why the other proposition
doesn't work?
Also: when a line is drawn to an image's canvas, can it be displayed without
explicitly repainting all the surface of the image?
I mean when a line draw is requested, is the line simply drawn on the
drawing area and then independently a repaint is requested by something or
the line is put in some sort of a buffer and when the repaint is requested,
then the actual drawing is performed?
|
|
| Back to top |
|
 |
JD Guest
|
Posted: Thu May 26, 2005 10:11 pm Post subject: Re: Prevent refreshing of a TImage? |
|
|
"Analian" <analian (AT) mail (DOT) bg> wrote:
| Quote: |
Isn't there a more direct way to prevent refreshing than
using an other component's (the paintbox) properties?
|
Yes. However, they all involve *not* using a TImage.
| Quote: | I guess this is a solution but I'd like to know why the
other proposition doesn't work?
|
Read Gambit's post for an explaination as to why you can't
manipulate a TImage that way.
| Quote: | Also: when a line is drawn to an image's canvas, can it be
displayed without explicitly repainting all the surface of
the image?
|
Not using a TImage. If you were to subclass a TPanel so
that you could gain access to it's Canvas property so that
you could draw on it, you could use the WM_SETREDRAW message
as previousely shown *and* you could use the win32 API
InvalidateRect to cause only the specified RECT to be
repainted.
| Quote: | [...] or the line is put in some sort of a buffer and when
the repaint is requested, then the actual drawing is
performed?
|
There is no buffering unless you explicitly cause it to happen.
You can't use DoubleBuffered (well you can but it won't help)
because TImage is not a TWinControl decendent. Besides, it's a
memory hog. Implementing it manually requires an in-memory
TBitmap that you would do your drawing on and then Assign the
TBitmap to the TImage ... or (more efficiently) use CopyRect
to copy only the changed portion of the bitmap to the TImage.
You can accomplish what you want equally as well (in terms of
speed) using a TPaintBox, TPanel or a TImage/TBitmap combo but
of the 3, a TPaintBox is easiest to implement because that's
what it's designed to do.
~ JD
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|