Link to home
Start Free TrialLog in
Avatar of wolsen
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?
Avatar of delphized
delphized

Do you use some strange (unusual)  method to obtain the canvas? (getwindowdc, getdc )? fi yes you should use releasedc.
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?
ASKER CERTIFIED SOLUTION
Avatar of cubud
cubud
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of wolsen

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 ).
try looking at Dormant and FreeImage methods of TBitmap
Avatar of wolsen

ASKER

>try looking at Dormant and FreeImage methods of TBitmap

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.

Avatar of wolsen

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(Handle));
  TmpBitmap := CreateCompatibleBitmap(GetDC(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;
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).
try this

FPainting := True;
HideCaret(Handle);
DCHandle := GetDC(Handle);  **Don't keep calling GetDC!!
DC := CreateCompatibleDC(DCHandle);
TmpBitmap := CreateCompatibleBitmap(DCHandle, 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
Avatar of wolsen

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.