Solved

TCanvas question

Posted on 2004-08-19
6
419 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
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
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
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

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
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…
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…

705 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

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now