Board index » delphi » Get access to Canvas.Handle just before it being destroyed

Get access to Canvas.Handle just before it being destroyed


2004-01-18 08:54:26 AM
delphi153
Hi,
I have a component (that inherits from TCustomPanel) that needs access to
Canvas.Handle just before it is being destroyed.
To override "Destroy" is not good enough, so I throught I'd try to
handle WM_DESTROY, since it is called *before* "Destroy". Still, that
doesn't work, since it seems that Canvas.Handle is already not available at
this stage...
Any idea?
Cheers, Alan.
 
 

Re:Get access to Canvas.Handle just before it being destroyed

"Alan Garny" <XXXX@XXXXX.COM>writes:
Quote
I have a component (that inherits from TCustomPanel) that needs access to
Canvas.Handle just before it is being destroyed.

To override "Destroy" is not good enough, so I throught I'd try to
handle WM_DESTROY, since it is called *before* "Destroy". Still, that
doesn't work, since it seems that Canvas.Handle is already not available at
this stage...
It might be a good idea for you to explain what you intend to do with
the handle at that point. There's no information (properties and such)
associated with the handle that would be useful to you at that point,
and you can't use it for any drawing. So if you tell us what you
want to do with the handle, we may be able to make some suggestions.
If all you want is to capture some display characteristics, GetDC(0)
will return a DC for that.
Good luck.
Kurt
 

Re:Get access to Canvas.Handle just before it being destroyed

In article <XXXX@XXXXX.COM>, Alan Garny writes:
Quote
I have a component (that inherits from TCustomPanel) that needs access to
Canvas.Handle just before it is being destroyed.

To override "Destroy" is not good enough, so I throught I'd try to
handle WM_DESTROY, since it is called *before* "Destroy". Still, that
doesn't work, since it seems that Canvas.Handle is already not available at
this stage...

Any idea?
Yes, change your design. Surely it makes no sense to *paint* on a control
that is about to die, and if you need to save whatever it shows you can do
that simply by storing this information elsewhere. The control needs to be
able to repaint itself at any time on request, so you need that info anyway.
Peter Below (TeamB)
Use the newsgroup archives :
www.mers.com/searchsite.html
www.tamaracka.com/search.htm
groups.google.com
www.prolix.be
 

Re:Get access to Canvas.Handle just before it being destroyed

"Peter Below (TeamB)" <XXXX@XXXXX.COM>writes
Quote
In article <XXXX@XXXXX.COM>, Alan Garny writes:
>I have a component (that inherits from TCustomPanel) that needs access
to
>Canvas.Handle just before it is being destroyed.
>
>To override "Destroy" is not good enough, so I throught I'd try to
>handle WM_DESTROY, since it is called *before* "Destroy". Still, that
>doesn't work, since it seems that Canvas.Handle is already not available
at
>this stage...
>
>Any idea?
Yes, change your design. Surely it makes no sense to *paint* on a control
that is about to die, and if you need to save whatever it shows you can do
that simply by storing this information elsewhere. The control needs to be
able to repaint itself at any time on request, so you need that info
anyway.
Argh, I knew I'd get that kind of comment... Ok, here is the reason
then...
My component is an OpenGL component... Amongst other things, I handle both
the WM_CREATE and WM_DESTROY messages. The reason is that I want to create
some 2D and 3D fonts that can be used by the component, using
"wglUseFontBitmaps" and "wglUseFontOutlines" respectively. It all works
fine, no problem there (i.e. I can use those fonts in my OpenGL scenes).
My problem, however, is when I have to destroy my component. I obviously
have to destroy my 2D and 3D fonts. To do so I need to call "glDeleteLists"
for both types of font. But before doing that, I need to ensure that the
rendering context associated to the instance of my component is activated.
For that, I have to make a call to "ActivateRenderingContext", which is a
function that comes from the OpenGL12 unit by Mike Lischke.
As I am sure you have guessed by then, that is where the problem is, since
"ActivateRenderingContext" makes a call to both "GetPixelFormat" and
"wglMakeCurrent", with both of those functions needing a device context
(namely "Canvas.Handle"), which is not available anymore at that point...
hence my problem...
Ok, so now that you know exactly what I intend to do, what do you guys think
is the best thing to do?
Cheers, Alan.
 

Re:Get access to Canvas.Handle just before it being destroyed

"Alan Garny" <XXXX@XXXXX.COM>writes
Quote
Argh, I knew I'd get that kind of comment... Ok, here is the reason
then...

My component is an OpenGL component... Amongst other things, I handle both
the WM_CREATE and WM_DESTROY messages. The reason is that I want to create
some 2D and 3D fonts that can be used by the component, using
"wglUseFontBitmaps" and "wglUseFontOutlines" respectively. It all works
fine, no problem there (i.e. I can use those fonts in my OpenGL scenes).

My problem, however, is when I have to destroy my component. I obviously
have to destroy my 2D and 3D fonts. To do so I need to call
"glDeleteLists"
for both types of font. But before doing that, I need to ensure that the
rendering context associated to the instance of my component is activated.
For that, I have to make a call to "ActivateRenderingContext", which is a
function that comes from the OpenGL12 unit by Mike Lischke.

As I am sure you have guessed by then, that is where the problem is, since
"ActivateRenderingContext" makes a call to both "GetPixelFormat" and
"wglMakeCurrent", with both of those functions needing a device context
(namely "Canvas.Handle"), which is not available anymore at that point...
hence my problem...

Ok, so now that you know exactly what I intend to do, what do you guys
think
is the best thing to do?
Hmm... I guess I should tell exactly *when* things go wrong... Basically, if
I drop my component on a form and decide to remove it, then an exception
will be raised, which is related to the problem I have described above.
However, if I have an instance of my component on a form and run my
application, then when I exit it, the instance of my component gets
destroyed *without* generating an exception...
Well, what I don't fully understand is why in the former case it doesn't
work, while it does in the second one...
Alan.
 

Re:Get access to Canvas.Handle just before it being destroyed

"Alan Garny" <XXXX@XXXXX.COM>writes:
Quote
Ok, so now that you know exactly what I intend to do, what do you guys
think
is the best thing to do?
I don't know anything about OpenGL, but the problem here seems to be
that your window handle has already been destroyed in your destructor.
So there's no way at that point, to get a DC (Canvas) for that window.
If the OpenGL routines will accept a DC associated with an arbitrary
window handle, (as opposed to your specifically), then you can use
GetDC(0) as I mentioned before.
If the DC has to be associated with your window specifically, then
you'll have to do this long before your destructor is called. Your
window handle is still valid when your receive the WM_DESTROY message,
and at that point you can get a DC for the window with:
procedure TMyThing.WMDestroy(var Msg: TMessage);
var
DC: THandle;
begin
DC := GetDC(Handle);
try
// Do something here with DC
finally
ReleaseDC(Handle, DC);
end;
inherited;
end;
Good luck.
Kurt
 

Re:Get access to Canvas.Handle just before it being destroyed

"Kurt Barthelmess (TeamB)" <XXXX@XXXXX.COM>writes
Quote
"Alan Garny" <XXXX@XXXXX.COM>writes:
>Ok, so now that you know exactly what I intend to do, what do you guys
>think is the best thing to do?
I don't know anything about OpenGL, but the problem here seems to be
that your window handle has already been destroyed in your destructor.
So there's no way at that point, to get a DC (Canvas) for that window.
If the OpenGL routines will accept a DC associated with an arbitrary
window handle, (as opposed to your specifically), then you can use
GetDC(0) as I mentioned before.
Now, as far as I know, that wouldn't work. You need the DC associated to the
window's canvas, not one that you make up or something.
Otherwise, what I don't understand is why my component only raises an
exception at design time, not at running time... that I really don't
understand...
Quote
If the DC has to be associated with your window specifically, then
you'll have to do this long before your destructor is called.
I would be happy to do that, as long as it is done when the component is on
the way to be destroyed. This said, the earliest I can think of handling is
WM_DESTROY... hence I am stuck... at the moment...
Quote
Your
window handle is still valid when your receive the WM_DESTROY message,
and at that point you can get a DC for the window with:

procedure TMyThing.WMDestroy(var Msg: TMessage);
var
DC: THandle;
begin
DC := GetDC(Handle);
try
// Do something here with DC
finally
ReleaseDC(Handle, DC);
end;
inherited;
end;
I think I see what you are getting at. However, we want a DC that is
associated to the window's canvas.
Alan.
 

Re:Get access to Canvas.Handle just before it being destroyed

"Alan Garny" <XXXX@XXXXX.COM>writes:
Quote
Now, as far as I know, that wouldn't work. You need the DC associated to the
window's canvas, not one that you make up or something.

I would be happy to do that, as long as it is done when the component is on
the way to be destroyed. This said, the earliest I can think of handling is
WM_DESTROY... hence I am stuck... at the moment...
I don't understand. I gave you the message handler for WM_DESTROY.
What's the problem?
Quote
>DC := GetDC(Handle);
I think I see what you are getting at. However, we want a DC that is
associated to the window's canvas.
We may have a miscommunication here. A TCanvas is simply a wrapper
around Windows GDI objects. Canvas.Handle is a DC (device context)
which is associated with the window of the component owning the
TCanvas. The line of code above obtains a device context associated
with your control's window (note that "Handle" there is your control's
window handle, not your Canvas' "Handle"), just a TCanvas would do if
you asked for Canvas.Handle. You should be able to use the value
assigned to DC just as if it were Canvas.Handle, except that you must
do all the object management (selecting pens, brushes, fonts,
palettes, or whatever) and remember to call ReleaseDC as shown in my
previous post.
Good luck.
Kurt
 

Re:Get access to Canvas.Handle just before it being destroyed

"Kurt Barthelmess (TeamB)" <XXXX@XXXXX.COM>writes
Quote
We may have a miscommunication here.
We did indeed... and your solution works fine...
Cheers, Alan.