Solved

canvas does not allow drawing

Posted on 2000-04-26
14
1,091 Views
Last Modified: 2008-03-04
I am double-buffering a bitmap and draw it on a form's canvas. It works fine without flicker, but after running my program for a while, I suddenly get the "canvas does not allow draing" error message. how do I solve this?
0
Comment
Question by:TropicalFish
[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
  • 8
  • 3
  • 3
14 Comments
 
LVL 6

Expert Comment

by:DrDelphi
ID: 2752926
I am guessing that perhaps, you have done of  a few different things.

1. you have not freed the offscreen bitmaps, thus depleting GDI resources.

2. You have locked the form's canvas.


any of this sound likely?


good luck!!
0
 

Author Comment

by:TropicalFish
ID: 2753146
Yes, I havn't freed the bitmaps. Could you please tell me how to do this (with code). I am using one bitmap as background, and another one that I constantly load different images from a resource into. I draw that bitmap on the background image several times, before I draw the background on the form's canvas. This works for about 100 screen updates, but then the memory probably runs out. How do I free it? Thanks.
0
 
LVL 6

Expert Comment

by:DrDelphi
ID: 2753191
Trop,
  what incarnation of C++ are you using? (C++ Builder, VC++, etc..?);
0
Independent Software Vendors: 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!

 

Author Comment

by:TropicalFish
ID: 2753206
I'm using C++ Builder 4.
0
 
LVL 6

Expert Comment

by:DrDelphi
ID: 2753243
Assuming you are using TBitmaps (and I am assuming that you are in BCB), your loop would look like this:


bmp =new TBitmap;
{
 //drawing code goes here
}

bmp->free;

Put this in your loop and you should be fine..


Good luck!!
0
 

Author Comment

by:TropicalFish
ID: 2753324
It sais: E2316 'free' is not a member of 'TBitmap'.
0
 

Author Comment

by:TropicalFish
ID: 2753366
Ok, now I'm using "bmp->Free()" to free all my bitmaps, but I still get the "wrong parameter" and "canvas does not allow drawing" after a while, plus now I also get a Win32 error code: 2. I'm confused.
0
 
LVL 14

Expert Comment

by:AlexVirochovsky
ID: 2754095
This exception is raised when an attempt is made to use the Handle
property of the Canvas when its handle is still invalid. That is, the
Canvas does not correspond to a valid device context. For example, the
following will raise the EInvalidOperation exception...

#include <memory>

std::auto_ptr<TCanvas> TempCanvas(new TCanvas());
ShowMessage(reinterpret_cast<int>(TempCanvas->Handle));


Since most TCanvas methods wrap a GDI function, and nearly all GDI
functions require a handle to a valid device context, simple operations
such as the following will also fail...

std::auto_ptr<TCanvas> TempCanvas(new TCanvas());
TempCanvas->FillRect(ClientRect);

or,

std::auto_ptr<TCanvas> TempCanvas(new TCanvas());
TempCanvas->Brush->Color = clRed;


The following however, will work, since the Handle property of the
TempCanvas is specified as the handle to the device context of a valid
windowed control...

std::auto_ptr<TCanvas> TempCanvas(new TCanvas());
TempCanvas->Handle = GetDC(Button1->Handle);
TempCanvas->FillRect(Button1->ClientRect);
ReleaseDC(Button1->Handle, TempCanvas->Handle);

For test your situation, post snippet
of you code.

Alex
0
 

Author Comment

by:TropicalFish
ID: 2754666

Graphics::TBitmap *lcd = new Graphics::TBitmap;
Graphics::TBitmap *knappbild = new Graphics::TBitmap;

Graphics::TBitmap *background = new Graphics::TBitmap;

Graphics::TBitmap *backbuffer = new Graphics::TBitmap;

background->LoadFromResourceID((int)HInstance,1400);
knappbild->LoadFromResourceID((int)HInstance,1401);
backbuffer->Width = background->Width;
backbuffer->Height = background->Height;
lcd->Transparent = true;
knappbild->Transparent = true;


void __fastcall TForm1::FormPaint(TObject *Sender)
{
backbuffer->Canvas->Draw(0,0,background);

lcd->LoadFromResourceID((int)HInstance,MarkPos + 1300);
backbuffer->Canvas->Draw(MarkCord[MarkPos][0],MarkCord[MarkPos][1],lcd);

if (FallPos < 4){
lcd->LoadFromResourceID((int)HInstance,FallPos + 1304);
backbuffer->Canvas->Draw(FallCord[FallPos][0],FallCord[FallPos][1],lcd);
}

if (FallPos != 0 && FallPos != 3) {lcd->LoadFromResourceID((int)HInstance,UpPos + 1500);
                                   backbuffer->Canvas->Draw(UpCord[UpPos],88,lcd);}
if (FallPos != 1 && FallPos != 2) {lcd->LoadFromResourceID((int)HInstance,NedPos + 1600);
                                   backbuffer->Canvas->Draw(NedCord[NedPos],128,lcd);}
lcd->LoadFromResourceID((int)HInstance,ental + 1200);
backbuffer->Canvas->Draw(216,71,lcd);
if (tiotal << 0 || hundratal << 0) {lcd->LoadFromResourceID((int)HInstance,tiotal + 1200);
                                    backbuffer->Canvas->Draw(201,71,lcd);}
if (hundratal << 0) {lcd->LoadFromResourceID((int)HInstance,hundratal + 1200);
                     backbuffer->Canvas->Draw(180,71,lcd);}

if (Miss > 0) {lcd->LoadFromResourceID((int)HInstance,Miss + 1210);
               backbuffer->Canvas->Draw(230,70,lcd);}

if (knpner[0] == 1) backbuffer->Canvas->Draw(32,158,knappbild);
if (knpner[1] == 1) backbuffer->Canvas->Draw(32,202,knappbild);
if (knpner[2] == 1) backbuffer->Canvas->Draw(314,203,knappbild);
if (knpner[3] == 1) backbuffer->Canvas->Draw(314,159,knappbild);

Form1->Canvas->Draw(0,0,backbuffer);
}
0
 
LVL 14

Expert Comment

by:AlexVirochovsky
ID: 2755212
I have some remarks to you code:
1. After using must free! as
void __fastcall TSwatForm::FormDestroy(TObject *Sender)
{
    delete lcd;
.....
    delete backbuffer ;
}
2. Test MarkCord,.., FallCord arrays:
   may by values are invalid
3. You use LoadFromResourceID function
   if ID (as NedPos + 1600) is invalid
: no resource with this ID, Draw fails
 Test all resources, espesially before
 error message!
4.  What meens
>>  if (hundratal << 0) ?
it is same as
if (hundratal)

5. And last : i don't like Load some
   bitmap during paint!
   Better way is : load during changings
   parameters (as FallPos for example),
   and paint deja loaded Bitmaps.

Alex

0
 

Author Comment

by:TropicalFish
ID: 2755718
Um.. it seems that "if(hundratal << 0)" does the same thing as "if(hundratal > 0)". Work both ways.. means bigger than 0. The MarkCord and FallCord arrays are fine, and all resources work up till the error point. I'll look into your points 1 and 5 though.

Also, I have put up my executable at:
http://w1.152.telia.com/~u15205559/Manhole05b.zip
If you have the time, maybe you want to take a look at it, it's a 307kb download. Start the game on gameA and play it with q,s,8,4 keys up till about 30 points (sometimes longer) Then you'll see the errors.
Thanks.
0
 

Author Comment

by:TropicalFish
ID: 2756813
Adjusted points from 50 to 75
0
 

Author Comment

by:TropicalFish
ID: 2756814
Now I have changed it so no bitmaps are loaded during paint, like you said. No difference. Only that I need to use 12 bitmaps instead of four, otherwise it writes over itself before drawing it to the backbuffer. I increased the points for this question, I really need this to workout!
0
 
LVL 14

Accepted Solution

by:
AlexVirochovsky earned 75 total points
ID: 2758608
I try you exe and get error:
borlnmm.dll missing.
But if I have get all dll, without source text I can't make debug!
And I think, that debug it is you
part. My part: make advice.
I think, that you must test punkt 3 from
my previous remark.
Use try /catch for find exect place
of error. In this moment test
all ID and arrays.

Other way: make intermediate printing
in file during every Paint and see
values , may be find some strange

And test system resources,may be
in some other part of text
you make "new" without "free"
or go out of array bound.

Alex
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

Introduction This article is the first in a series of articles about the C/C++ Visual Studio Express debugger.  It provides a quick start guide in using the debugger. Part 2 focuses on additional topics in breakpoints.  Lastly, Part 3 focuses on th…
What is C++ STL?: STL stands for Standard Template Library and is a part of standard C++ libraries. It contains many useful data structures (containers) and algorithms, which can spare you a lot of the time. Today we will look at the STL Vector. …
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.

623 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