Solved

TCanvas question

Posted on 2004-08-19
6
433 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
Industry Leaders: 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: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

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

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Nobody understands Phishing better than an anti-spam company. That’s why we are providing Phishing Awareness Training to our customers. According to a report by Verizon, only 3% of targeted users report malicious emails to management. With compan…

735 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