Solved

TCanvas question

Posted on 2004-08-19
6
434 Views
Last Modified: 2010-04-05
Hi!

I'm drawing on the Canvas property of a StringGrid (well, in fact its the 3rd party TStringAlignGrid object which is pretty much like TStringGrid).  I need to draw some shapes on the canvas and, after a while, erase them.  Nothing complicated.

The thing is that if I call the refresh (or repaint or invalidate) method of the grid THE WHOLE grid gets repainted which make my screen flick like hell.

Is there anyway I can make some region (TRect) or cells to get repainted without getting the whole component refreshed ?  I know that the internal code of the component does that.  For example, After I draw a shape on the canvas, if I select the cell behind it the selected cell gets repainted and the rest of the grid remains ok.  

Any hint ?
0
Comment
Question by:qas
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
6 Comments
 
LVL 2

Expert Comment

by:beermequik
ID: 11845058
The OnDrawCell event may work for you....

Set the DefaultDrawing property to false, and define that event.

I have code for this, I just have to dig it up (Its at home, so I wont be able to get to it till later today)

I will post the code later tonight.
0
 

Author Comment

by:qas
ID: 11845161
Sorry I dont understand...

I believe that the OnDraCell event will triggered whenever a cell needs to be painted, right ?  What I need is the other way around: not only  I want to trigger this event, I need the grid to actually paint the specified cells when I want it to.

Let me be clearer.  I got a rectangle drawn over multiple cells (lets call it R1) and another rectangle draw over some other cells (R2).  I want to erase R1 without having to erease R2.  

Is this possible ?
0
 
LVL 3

Accepted Solution

by:
Tyrsis earned 100 total points
ID: 11845258
You can do this by clipping the region of the canvas you want to repaint and calling Invalidate.  There is an example of how to do this in the Delphi Help file - TCanvas,ClipRect

Here is a copy of that example:

This example creates a region and selects this region as the clipping rectangle for the Image component's canvas. It then sets the canvas's brush color to red and calls FillRect using the ClipRect as the area to fill. Lastly, the ClipRect is reset to the original value that it contained by calling SelectClipRect with nil as the second parameter and deletes the region.

procedure Form1.Button1Click(Sender: TObject);
var
    MyRgn: HRGN ;
begin

    MyRgn := CreateRectRgn(100,100,200,200);
    SelectClipRgn(Image1.Canvas.Handle,MyRgn);
    Image1.Canvas.Brush.Color := clRed;
    Image1.Canvas.FillRect(Image1.Canvas.ClipRect);
    Image1.Invalidate;
    SelectClipRgn(Image1.Canvas.Handle,nil);
    DeleteObject(MyRgn);
end;

Hope this helps!

Tyrsis
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 6

Expert Comment

by:gwalkeriq
ID: 11846761
It's just a simple hack, but this might all you need.

Look at the windows API call LockWindowUpdate. It has a serious restriction that you can lock a single windows (which lock child windows recursively to)

Then in repaint event your could might look like:

LockWindowUpdate(Grid.Handle); // Grab the lock

Grid.Paint() // to force repaint of the grid itself
... // your code that draws to the canvas

LockWindowUpdate(0); // finish the update

You did not mention whether repainting without you drawing on the canvas causes massive flicker. If so, you may not get a big advantage

0
 
LVL 2

Expert Comment

by:Molando
ID: 11846834
other option is to do a form1.doublebuffered := true. Though the lockwindowupdate will probably work much better.
0
 

Expert Comment

by:krio
ID: 11910623
Try the InvalidateRect API function. I've used it with a TDrawGrid and it worked fine (haven't tried it with a StringGrid).
Example:
rc:=StringGrid1.CellRect(1, 2); // Get the rectangle of cell 1,2
Windows.InvalidateRect(StringGrid1.Handle, @rc, false);

The function takes three parameters, the first one is the handle of the window, the second is a pointer to a rect (the area that should be repainted) and the last one is a bool that specifies if the background should be erased. Check the Win32 help for information on the InvalidateRect function.
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…
Are you ready to implement Active Directory best practices without reading 300+ pages? You're in luck. In this webinar hosted by Skyport Systems, you gain insight into Microsoft's latest comprehensive guide, with tips on the best and easiest way…

738 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question