BorlandTalk.com Forum Index BorlandTalk.com
Borland discussion newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Where to get a Canvas (for TextWidth()) if 'Application->Mai

 
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> C++ Builder (VCL Components Usage)
View previous topic :: View next topic  
Author Message
MR
Guest





PostPosted: Fri Feb 10, 2006 8:03 am    Post subject: Where to get a Canvas (for TextWidth()) if 'Application->Mai Reply with quote



To calculate the textwidth for a certain font I always use the
member-function TCanvas::TextWidth and the canvas I mostly used was
Application->MainForm->Canvas.

(I did this by manipulating Appliction->MainForm->Font and set it back
to it's former value at the end of the function, but that's another
story)

Now I have the case that 'Application->MainForm'==NULL, i.e. is not
yet initialized, in my case inside FormCreate().

Where can I get a Canvas for use with TextWidth() now?

(If I remember right (I tried much yesterday...) I tried it with
something like
TCanvas *canvas=new TCanvas;
int width=canvas->TextWidth("abc");
but there was a runtime-exception, telling me that TextWidth() was not
applicable to my canvas.

Thanks a lot,

Michael
Back to top
JD
Guest





PostPosted: Fri Feb 10, 2006 9:03 am    Post subject: Re: Where to get a Canvas (for TextWidth()) if 'Application- Reply with quote



MR <> wrote:
Quote:

[...] 'Application->MainForm'==NULL, i.e. is not yet
initialized, in my case inside FormCreate().

Never ever use OnCreate. It is a Delphi remnant which can
execute before the form's constructor which is illegal in
C++. The same can be said for OnDestroy except that it can
execute *after* the destructor. Use the constructor and
destructor instead.

Quote:
Where can I get a Canvas for use with TextWidth() now?

There are a number of ways that you can go about that but
there are many other things that can't be done until the
application is fully constructed. In these cases, one needs
to wait until that happens and the solution is quite simple:


//--- in the header -------------------------------------------
#define UWM_INITIALIZED (WM_USER + 100)

protected: // User declarations
virtual void __fastcall WndProc( TMessage &Message );

//--- in the unit ---------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
{
::PostMessage( Handle, UWM_INITIALIZED, NULL, NULL );
}
//-------------------------------------------------------------
void __fastcall TForm1::WndProc( TMessage &Message )
{
if( Message.Msg == UWM_INITIALIZED )
{
//
}
TForm::WndProc( Message );
}
//-------------------------------------------------------------

~ JD
Back to top
HF
Guest





PostPosted: Fri Feb 10, 2006 9:03 am    Post subject: Re: Where to get a Canvas (for TextWidth()) if 'Application- Reply with quote



I prefer to use the Form's Constructor but is working also in FormCreate
event

__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
TCanvas *canvas=new TCanvas();
canvas->Handle = GetDC(Application->Handle);
int width=canvas->TextWidth("abc");
ShowMessage(IntToStr(width));
ReleaseDC(Application->Handle,canvas->Handle);
}

-Minas
Back to top
Remy Lebeau (TeamB)
Guest





PostPosted: Fri Feb 10, 2006 12:03 pm    Post subject: Re: Where to get a Canvas (for TextWidth()) if 'Application- Reply with quote

"HF" <min_charLOOK (AT) ATyahoo (DOT) gr> wrote in message
news:43ec479a (AT) newsgroups (DOT) borland.com...

Quote:
TCanvas *canvas=new TCanvas();

That is a memory leak. You are never freeing the TCanvas. You don't need
to create a new TCanvas anyway. The form's own TCanvas is valid in the
constructor, ie:

__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
ShowMessage(Canvas->TextWidth("abc"));
}

Quote:
ReleaseDC(Application->Handle,canvas->Handle);

That is also an error, because you are not resetting the Canvas->Handle to
NULL after freeing the HDC..


Gambit
Back to top
Remy Lebeau (TeamB)
Guest





PostPosted: Fri Feb 10, 2006 12:03 pm    Post subject: Re: Where to get a Canvas (for TextWidth()) if 'Application- Reply with quote

<MR> wrote in message news:igfou1tqsdkqkb8gaelj8kjcgvgv2dp8a3 (AT) 4ax (DOT) com...

Quote:
Now I have the case that 'Application->MainForm'==NULL,
i.e. is not yet initialized, in my case inside FormCreate().

Do not use the OnCreate event. It is a Delphi idiom that produces illegal
behavior in C++ as it can be triggered before the constructor. Use the
actual constructor instead..

You can use the implicit 'this' pointer to access the form's Canvas, ie:

__fastcall TForm1::TForm1(TComponent *Owner)
: TForm(Owner)
{
... = Canvas->TextWidth(...);
}

Quote:
I tried it with something like
TCanvas *canvas=new TCanvas;
int width=canvas->TextWidth("abc");
but there was a runtime-exception, telling me that TextWidth()
was not applicable to my canvas.

You probably did not assign a valid HDC to the TCanvas::Handle property.


Gambit
Back to top
HF
Guest





PostPosted: Fri Feb 10, 2006 12:03 pm    Post subject: Re: Where to get a Canvas (for TextWidth()) if 'Application- Reply with quote

Remy, you are right :-)

Thanks
Back to top
MR
Guest





PostPosted: Fri Feb 10, 2006 5:03 pm    Post subject: Re: Where to get a Canvas (for TextWidth()) if 'Application- Reply with quote

It helped me a lot to know how to create a new canvas, because I now
can e.g. change it's font size inside a function (e.g. to test the
canvas's TextWidth()-methode with this new size) without having to set
it back to it's old value later...

If I get it right, the correct snippet was:

TCanvas *canvas=new TCanvas();
canvas->Handle = GetDC(Application->Handle);
int width=canvas->TextWidth("abc");
ShowMessage(IntToStr(width));
ReleaseDC(Application->Handle,canvas->Handle);
canvas->Handle=NULL; // necessary??
delete canvas;

Thanks,

Michael
Back to top
MR
Guest





PostPosted: Fri Feb 10, 2006 5:03 pm    Post subject: Re: Where to get a Canvas (for TextWidth()) if 'Application- Reply with quote

Quote:
You probably did not assign a valid HDC to the TCanvas::Handle property.
Yes, exactly...


Thanks,

Michael
Back to top
MR
Guest





PostPosted: Fri Feb 10, 2006 5:03 pm    Post subject: Re: Where to get a Canvas (for TextWidth()) if 'Application- Reply with quote

"JD" <nospam (AT) nospam (DOT) com> schrieb:

Quote:

MR <> wrote:

[...] 'Application->MainForm'==NULL, i.e. is not yet
initialized, in my case inside FormCreate().

Never ever use OnCreate. It is a Delphi remnant which can
execute before the form's constructor which is illegal in
C++. The same can be said for OnDestroy except that it can
execute *after* the destructor. Use the constructor and
destructor instead.

Oh, interesting. Thinking a little bit about how this can be, I
suppose FormCreate() is called from within the constructor of
TForm()!? Ok, I'll use the constructor/destructor in the future...


Quote:
Where can I get a Canvas for use with TextWidth() now?

There are a number of ways that you can go about that but
there are many other things that can't be done until the
application is fully constructed. In these cases, one needs
to wait until that happens and the solution is quite simple:


//--- in the header -------------------------------------------
#define UWM_INITIALIZED (WM_USER + 100)

protected: // User declarations
virtual void __fastcall WndProc( TMessage &Message );

//--- in the unit ---------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
{
::PostMessage( Handle, UWM_INITIALIZED, NULL, NULL );
}
//-------------------------------------------------------------
void __fastcall TForm1::WndProc( TMessage &Message )
{
if( Message.Msg == UWM_INITIALIZED )
{
//
}
TForm::WndProc( Message );
}
//-------------------------------------------------------------

Because I do not know for sure when the user (i.e. I) will call the
function using the TextWidth(), I used the version when it created
it's own Canvas by itself.

Thanks a lot,

Michael
Back to top
Remy Lebeau (TeamB)
Guest





PostPosted: Fri Feb 10, 2006 6:03 pm    Post subject: Re: Where to get a Canvas (for TextWidth()) if 'Application- Reply with quote

<MR> wrote in message news:a4dpu1dd86qupmcp13qui5ll64llvqi52p (AT) 4ax (DOT) com...

Quote:
If I get it right, the correct snippet was:

Try this:

TCanvas *canvas = new TCanvas;
try
{
HWND hwnd = Application->Handle;
HDC hdc = GetDC(hwnd);
if( hdc )
{
try
{
canvas->Handle = hdc;
try
{
int saved = SaveDC(hdc);
if( saved != 0 )
{
try
{
// change the canvas settings as needed ...
ShowMessage(canvas->TextWidth("abc"));
}
__finally {
RestoreDC(hdc, saved);
}
}
}
__finally {
canvas->Handle = NULL;
}
}
__finally {
ReleaseDC(hwnd, hdc);
}
}
}
__finally {
delete canvas;
}


Gambit
Back to top
Remy Lebeau (TeamB)
Guest





PostPosted: Fri Feb 10, 2006 6:03 pm    Post subject: Re: Where to get a Canvas (for TextWidth()) if 'Application- Reply with quote

<MR> wrote in message news:7odpu1510odlq46vd993v56gsc95cap57a (AT) 4ax (DOT) com...

Quote:
Oh, interesting. Thinking a little bit about how this can be,
I suppose FormCreate() is called from within the constructor
of TForm()!?

Yes. Specifically, in TCustomForm's constructor.

The Delphi object model has a different ancestor/descendant creation order
then the C++ object model has. In Delphi, descendant classes are created
first and then ancestor classes second, thus ancestor constructors can
access descendant class members. In C++, the reverse is the case instead,
and ancestor constructors cannot access descendant members. VCL objects
always use the Delphi model, even when used in the C++ environment.

As such, the TCustomForm constructor can call the descendant form's OnCreate
event handler before the descendant constructor has been executed - which is
an illegal operation in C++.


Gambit
Back to top
MR
Guest





PostPosted: Sat Feb 11, 2006 9:03 am    Post subject: Re: Where to get a Canvas (for TextWidth()) if 'Application- Reply with quote

Oops! Many possible problems possible about to occurr...


Thanks,

Michael
Back to top
JD
Guest





PostPosted: Sat Feb 11, 2006 3:03 pm    Post subject: Re: Where to get a Canvas (for TextWidth()) if 'Application- Reply with quote

MR <> wrote:
Quote:

There are a number of ways that you can go about that but
there are many other things that can't be done until the
application is fully constructed. In these cases, one needs
to wait until that happens

Because I do not know for sure when the user (i.e. I) will call the
function using the TextWidth(), I used the version when it created
it's own Canvas by itself.

You missed the point of my post.

~ JD
Back to top
Display posts from previous:   
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> C++ Builder (VCL Components Usage) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.