wolsen
asked on
Drawing problems: EOutOfResources,EInvalidOperation
I get the following exceptions when my program calls the Tcanvas.draw and Tcanvas.copyrect methods
Exception Type : EInvalidOperation
Message: Canvas does not allow drawing
Exception Type : EOutOfResources
Message: Error creating window device context
This program is distributed to many differrent users on many differrent machines. It does not occur on most machines.
There are no memory leaks in my program. I have verified this with a memory monitoring tool. Also, the reports I get show that I there is plenty of available RAM and disk space at the time the exception is raised.
The user interface uses many small offscreen Tbitmaps. None of them are bigger than 200X300. I also use some temporary Tbitmaps that are created and destroyed during Paint operations.
All of the drawing is done in the main thread of the program.
Any thoughts on what could be the cause of this problem?
Exception Type : EInvalidOperation
Message: Canvas does not allow drawing
Exception Type : EOutOfResources
Message: Error creating window device context
This program is distributed to many differrent users on many differrent machines. It does not occur on most machines.
There are no memory leaks in my program. I have verified this with a memory monitoring tool. Also, the reports I get show that I there is plenty of available RAM and disk space at the time the exception is raised.
The user interface uses many small offscreen Tbitmaps. None of them are bigger than 200X300. I also use some temporary Tbitmaps that are created and destroyed during Paint operations.
All of the drawing is done in the main thread of the program.
Any thoughts on what could be the cause of this problem?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thank you both for your comments.
>Do you use some strange (unusual) method to obtain the canvas? (getwindowdc, getdc )?
I don't think so, but I am using a some 3rd party code that may be doing this. I will have to check, and make sure that releaseDC is called appropriately. This may be the problem.
>Do you create fonts at runtime?
No.
Do you use a lot of visual components in your application?
Yes: several Timage components , several TGraphicControl descendents ( custom scroll bars, custom buttons ). There are two Tdrawgrids, as well as two Twebbrowsers. I am also using a transparent edit box component. All of these components are arranged on several layers of TPanels that are seperated By TSplitters, so that the interface has many degrees of adjustability.
your canvas is directed to the screen, correct?
Some of the drawing is done to "offscreen" TBitmaps. These bitmaps are later drawn to the screen during the paint events. My program stores many offscreen bitmaps. For example, the buttons store a bitmap for three differrent states ( regular, hover, press ).
>Do you use some strange (unusual) method to obtain the canvas? (getwindowdc, getdc )?
I don't think so, but I am using a some 3rd party code that may be doing this. I will have to check, and make sure that releaseDC is called appropriately. This may be the problem.
>Do you create fonts at runtime?
No.
Do you use a lot of visual components in your application?
Yes: several Timage components , several TGraphicControl descendents ( custom scroll bars, custom buttons ). There are two Tdrawgrids, as well as two Twebbrowsers. I am also using a transparent edit box component. All of these components are arranged on several layers of TPanels that are seperated By TSplitters, so that the interface has many degrees of adjustability.
your canvas is directed to the screen, correct?
Some of the drawing is done to "offscreen" TBitmaps. These bitmaps are later drawn to the screen during the paint events. My program stores many offscreen bitmaps. For example, the buttons store a bitmap for three differrent states ( regular, hover, press ).
try looking at Dormant and FreeImage methods of TBitmap
ASKER
>try looking at Dormant and FreeImage methods of TBitmap
Why? What are these methods, how will they help.
Why? What are these methods, how will they help.
>Win95/98 is much more forgiving, whereas NT will crash.
It can also be the other way around, Win9X resources are limited when compared to WinNT/2000/XP. You can have graphics apps work fine on NT systems while they crash on Win9x/ME. Visit this site http://www.aumha.org for more information, specificly this page http://aumha.org/win4/a/resource.htm
>>Do you use some strange (unusual) method to obtain the canvas? (getwindowdc, getdc )?
> I don't think so, but I am using a some 3rd party code that may be doing this. I will have to check, and make sure > that releaseDC is called appropriately. This may be the problem.
If ReleaseDC ins't called when it should be , then that's a resource leak. Which can be felt more if you use Win9x for the reason I mentioned above, it has much more limited resources.
>>try looking at Dormant and FreeImage methods of TBitmap
>Why? What are these methods, how will they help.
Description from Delphi help:
Use FreeImage to reduce the memory requirements of an application when color depth and pixel format are not an issue. Freeing the image releases the memory allocated for the bitmap image when it was originally loaded to disk. Consequently, some of the original pixel format of the bitmap is lost (for example, if you changed its format to a DIB) as well as the color depth of the bitmap.
When a bitmap is loaded into a bitmap object, the bitmap object creates an image of the loaded bitmap in memory. If the bitmap isn't changed, the memory image is used when saving the bitmap, to verify that the bitmap has not lost color depth or changed the pixel format.
It can also be the other way around, Win9X resources are limited when compared to WinNT/2000/XP. You can have graphics apps work fine on NT systems while they crash on Win9x/ME. Visit this site http://www.aumha.org for more information, specificly this page http://aumha.org/win4/a/resource.htm
>>Do you use some strange (unusual) method to obtain the canvas? (getwindowdc, getdc )?
> I don't think so, but I am using a some 3rd party code that may be doing this. I will have to check, and make sure > that releaseDC is called appropriately. This may be the problem.
If ReleaseDC ins't called when it should be , then that's a resource leak. Which can be felt more if you use Win9x for the reason I mentioned above, it has much more limited resources.
>>try looking at Dormant and FreeImage methods of TBitmap
>Why? What are these methods, how will they help.
Description from Delphi help:
Use FreeImage to reduce the memory requirements of an application when color depth and pixel format are not an issue. Freeing the image releases the memory allocated for the bitmap image when it was originally loaded to disk. Consequently, some of the original pixel format of the bitmap is lost (for example, if you changed its format to a DIB) as well as the color depth of the bitmap.
When a bitmap is loaded into a bitmap object, the bitmap object creates an image of the loaded bitmap in memory. If the bitmap isn't changed, the memory image is used when saving the bitmap, to verify that the bitmap has not lost color depth or changed the pixel format.
ASKER
This is the only portion of the code that is using "GetDC".
I don't see any red flags here, but I thought I would post the code, in case I missed something.
Everywhere else in the program, I am doing all of the drawing with TCanvas methods.
From Transparent Components for Delphi 32 (Medialight Software Solutions):
...
procedure TTransEdit.RepaintWindow;
var
DC: hDC;
TmpBitmap, Bitmap: hBitmap;
begin
if FTransparent then
begin
FPainting := true;
HideCaret(Handle);
DC := CreateCompatibleDC(GetDC(H andle));
TmpBitmap := CreateCompatibleBitmap(Get DC(Handle) , Succ(ClientWidth), Succ(ClientHeight));
Bitmap := SelectObject(DC, TmpBitmap);
PaintTo(DC, 0, 0);
BitBlt(GetDC(Handle), BorderRec[BorderStyle], BorderRec[BorderStyle], ClientWidth, ClientHeight, DC, 1, 1, SRCCOPY);
SelectObject(DC, Bitmap);
DeleteDC(DC);
ReleaseDC(Handle, GetDC(Handle));
DeleteObject(TmpBitmap);
ShowCaret(Handle);
FPainting := false;
end;
end;
I don't see any red flags here, but I thought I would post the code, in case I missed something.
Everywhere else in the program, I am doing all of the drawing with TCanvas methods.
From Transparent Components for Delphi 32 (Medialight Software Solutions):
...
procedure TTransEdit.RepaintWindow;
var
DC: hDC;
TmpBitmap, Bitmap: hBitmap;
begin
if FTransparent then
begin
FPainting := true;
HideCaret(Handle);
DC := CreateCompatibleDC(GetDC(H
TmpBitmap := CreateCompatibleBitmap(Get
Bitmap := SelectObject(DC, TmpBitmap);
PaintTo(DC, 0, 0);
BitBlt(GetDC(Handle), BorderRec[BorderStyle], BorderRec[BorderStyle], ClientWidth, ClientHeight, DC, 1, 1, SRCCOPY);
SelectObject(DC, Bitmap);
DeleteDC(DC);
ReleaseDC(Handle, GetDC(Handle));
DeleteObject(TmpBitmap);
ShowCaret(Handle);
FPainting := false;
end;
end;
the hBitmap variable, Bitmap, was never released via DeleteObject?
also, if you have, say, different states for buttons, etc, take a look at TImageList, which stores multiple images but only uses one bitmap handle (if we don't count the handle for image mask, of course).
also, if you have, say, different states for buttons, etc, take a look at TImageList, which stores multiple images but only uses one bitmap handle (if we don't count the handle for image mask, of course).
try this
FPainting := True;
HideCaret(Handle);
DCHandle := GetDC(Handle); **Don't keep calling GetDC!!
DC := CreateCompatibleDC(DCHandl e);
TmpBitmap := CreateCompatibleBitmap(DCH andle, ClientWidth, ClientHeight);
GDIFlush; **I have had trouble when this is not here!!
OldBitmap := SelectObject(DC, TmpBitmap); **Remember the old bitmap
PaintTo(DC, 0, 0);
BitBlt(DCHandle, BorderRec[etc], etc, ClientWidth, ClientHeight, DC, 1, 1, SRCCOPY);
SelectObject(DC, OldBitmap); **Put the old bitmap back!!
DeleteObject(TmpBitmap);
DeleteDC(DC); **You wasn't deleting this
ReleaseDC(Handle, DCHandle); **You wasn't releasing this!!
--
Pete
=============
Read or write technical articles
http://www.HowToDoThings.com
Audio compression components, FastStrings library, DIB controls
http://www.DroopyEyes.com
FPainting := True;
HideCaret(Handle);
DCHandle := GetDC(Handle); **Don't keep calling GetDC!!
DC := CreateCompatibleDC(DCHandl
TmpBitmap := CreateCompatibleBitmap(DCH
GDIFlush; **I have had trouble when this is not here!!
OldBitmap := SelectObject(DC, TmpBitmap); **Remember the old bitmap
PaintTo(DC, 0, 0);
BitBlt(DCHandle, BorderRec[etc], etc, ClientWidth, ClientHeight, DC, 1, 1, SRCCOPY);
SelectObject(DC, OldBitmap); **Put the old bitmap back!!
DeleteObject(TmpBitmap);
DeleteDC(DC); **You wasn't deleting this
ReleaseDC(Handle, DCHandle); **You wasn't releasing this!!
--
Pete
=============
Read or write technical articles
http://www.HowToDoThings.com
Audio compression components, FastStrings library, DIB controls
http://www.DroopyEyes.com
ASKER
Experts,
Thanks for all your comments.
cubud: I am waiting for feedback to see your suggestion fixes the problem. I'll get back to this in a day or two.
I will probably be splitting the points.
Thanks for all your comments.
cubud: I am waiting for feedback to see your suggestion fixes the problem. I'll get back to this in a day or two.
I will probably be splitting the points.
Do you create fonts at runtime?.
Do you use a lot of visual components in your application?
your canvas is directed to the screen, correct?