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 

Derived component created using "new" get no attention

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





PostPosted: Fri Jun 17, 2005 2:21 am    Post subject: Derived component created using "new" get no attention Reply with quote



Hi,
I have created a sprite component for DirecDraw, which is derived from
TGraphicControl. In this control I added 2 messages which will correspond
with CM_MOUSEENTER and CM_MOUSELEAVE. ant it has 2 constructer:

//Constructor 1
//--------------------------------------
__fastcall TSprite(TComponent *Owner) //the default constructor created by
CBuilder
{
//added these to initialize for dropped component
lpddssrc = NULL; //LPDIRECTDRAWSURFACE, the source of image
lpddsdst = NULL; //same, but the pointer of the surface to draw it's
image
x = 0;
y = 0;
width = 0;
height = 0;
index = 0; //index of the image in the source image
frames = 0; //number of frames in the source image
}

//Constructor 2, the one I used to new the Component
//Basically what different is just I supply all the neccessory info at
//call of constructor
//------------------------------------
__fastcall TSprite(LPDDS source, LPDDS dest, int w, int h, TComponent
*Owner) //LPDDS = LPDIRECTDRAWSURFACE, redefined
{
x = 0;
y = 0; //the sprite will always start at these location
src = source;
dst = dest;
width = w;
height = h;
index = 0;
frames = 2; /*actually some calcualtion, lets say I have a source with 2
frames*/
}

so basically not much difference. Now the problem is, when I do:
TSprite *sprite = new TSprite(this); //with constructor 1
or
TSprite *sprite = new TSprite(source, dest, 32, 32, this);

these components will not detect the mouse entering r leaving themselves,
nor will they draw themselves. I have to explicitly call to Sprite->Paint()
to have them paint on screen. Half of the problem may be solved, but still
they will not detact mouse event. I have almost the same component, doing
all the same thing (mouse, and other event), except for the Paint() - they
paint to Canvas instead of a DirectDraw surface. Those TCanvas versions are
all working perfectly - for both Paint() and Mouse events.

To further investigate, I decide to drop this TSprite on the form directly
and supply the parameters manually (as in the way I use the Constructor 1
version) and this time, it works as planned! Well, at least half working -
this time, it will detact the Mouse event (entering and leaving) though I
still have to call to Sprite->Paint() explicitly. I'm okay with the calling
of Paint(), but why for the new'ed version is not detecting the mouse while
the dropped version will see the mouse??? I did set the Parent parameter of
the new'ed version to "this". Is there anything more that I need to do to
make a self-made component to recieve mouse messages?

Thanks in advance.

Regards.



Back to top
Remy Lebeau (TeamB)
Guest





PostPosted: Fri Jun 17, 2005 3:00 am    Post subject: Re: Derived component created using "new" get no attention Reply with quote




"Choykw" <Newsreader (AT) Newsgroup (DOT) com> wrote


Quote:
it has 2 constructer:

Neither constructor is calling the base class TGraphicControl constructor.
You should be doing so, ie:


__fastcall TSprite::TSprite(TComponent *Owner)
: TGraphicControl(Owner) // <-- HERE
{
//...
}

__fastcall TSprite::TSprite(LPDDS source, LPDDS dest, int w, int h,
TComponent *Owner)
: TGraphicControl(Owner) // <-- HERE
{
//...
}

Quote:
these components will not detect the mouse entering r leaving
themselves, nor will they draw themselves.

TGraphicControl is a visual component. Are you ever assigning the Parent
property anywhere? Without that, the component cannot be shown visually
onscreen, or react to any visual actions, such a mouse movements.

Quote:
these components will not detect the mouse entering r leaving themselves,
nor will they draw themselves. I have to explicitly call to
Sprite->Paint()
to have them paint on screen.
snip
To further investigate, I decide to drop this TSprite on the form directly
and supply the parameters manually (as in the way I use the Constructor
1 version) and this time, it works as planned! Well, at least half
working -
this time, it will detact the Mouse event (entering and leaving) though I
still have to call to Sprite->Paint() explicitly.

You never have to, nor should you, ever call Paint() directly. Doing so
suggests that your component is fundamentaly flawed at its core. Please
show more of your code.

Quote:
I'm okay with the calling of Paint()

You should not be ok with it, because you should not be having to do it in
the first place.

Quote:
I did set the Parent parameter of the new'ed version to "this".

Where exactly?


Gambit



Back to top
Choykw
Guest





PostPosted: Fri Jun 17, 2005 4:47 am    Post subject: Re: Derived component created using "new" get no attention Reply with quote




"Remy Lebeau (TeamB)" <no.spam (AT) no (DOT) spam.com> wrote

Quote:

"Choykw" <Newsreader (AT) Newsgroup (DOT) com> wrote in message
news:42b2339b (AT) newsgroups (DOT) borland.com...

Neither constructor is calling the base class TGraphicControl constructor.
You should be doing so, ie:


__fastcall TSprite::TSprite(TComponent *Owner)
: TGraphicControl(Owner) // <-- HERE
{
//...
}

__fastcall TSprite::TSprite(LPDDS source, LPDDS dest, int w, int h,
TComponent *Owner)
: TGraphicControl(Owner) // <-- HERE
{
//...
}


oops! forgot to type those in. Yes, I did call the default constructor, else
the code will not compile.

Quote:

TGraphicControl is a visual component. Are you ever assigning the Parent
property anywhere? Without that, the component cannot be shown visually
onscreen, or react to any visual actions, such a mouse movements.


I did. After I called the "new" to create the object.

Quote:

You never have to, nor should you, ever call Paint() directly. Doing so
suggests that your component is fundamentaly flawed at its core. Please
show more of your code.

Okay, here they are :

the Sprite.cpp, as in dcluser.bpk:

//---------------------------------------------------------------------------
#include #pragma hdrstop
#include "Sprite.h"
#pragma package(smart_init)
//---------------------------------------------------------------------------
// ValidCtrCheck is used to assure that the components created do not have
// any pure virtual functions.
//
static inline void ValidCtrCheck(TSprite *)
{
new TSprite(NULL);
}
//---------------------------------------------------------------------------
__fastcall TSprite::TSprite(TComponent* Owner)
: TGraphicControl(Owner)
{
src = NULL;
dst = NULL;
fwidth = 0;
fheight = 0;
fframes = 0;
findex = 0;
fswidth = 0;
fsheight = 0;
FMouseInControl = false;
}
//---------------------------------------------------------------------------
__fastcall TSprite::TSprite(lpDDs source, lpDDs dest, int w, int h,
TComponent *Owner)
: TGraphicControl(Owner)
{
src = source;
dst = dest;
fwidth = w;
fheight = h;
DDSURFACEDESC ddsd;
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
src->GetSurfaceDesc(&ddsd);
fswidth = ddsd.dwWidth;
fsheight = ddsd.dwHeight;
fframes = fswidth / fwidth;
findex = 0;
FMouseInControl = false;
}
//---------------------------------------------------------------------------
namespace Sprite
{
void __fastcall PACKAGE Register()
{
TComponentClass classes[1] = {__classid(TSprite)};
RegisterComponents("Standard", classes, 0);
}
}
//---------------------------------------------------------------------------
void __fastcall TSprite::CMMouseEnter(TMessage &Msg)
{
findex = 1;
FMouseInControl = true;
}
//---------------------------------------------------------------------------
void __fastcall TSprite::CMMouseLeave(TMessage &Msg)
{
findex = 0;
FMouseInControl = false;
}
//---------------------------------------------------------------------------
void __fastcall TSprite::Paint(void)
{
if(src != NULL && dst != NULL)
{
TRect r = Rect(findex * fwidth, 0, (findex + 1) * fwidth, fheight);
//Here I assume all the source images are in a 1xN image strip (N is
the number
//of frames), I might add support for multiple rows, but not now.
dst->BltFast(fx, fy, src, &r, DDBLTFAST_WAIT |
DDBLTFAST_SRCCOLORKEY);
}
}
//---------------------------------------------------------------------------


the Sprite.h for the cpp above:

//---------------------------------------------------------------------------
#ifndef SpriteH
#define SpriteH
//---------------------------------------------------------------------------
#include <SysUtils.hpp>
#include <Classes.hpp>
#include <Controls.hpp>
#include <ddraw.h>
#include <ddutil.h>
#define lpDDs LPDIRECTDRAWSURFACE
//---------------------------------------------------------------------------
class PACKAGE TSprite : public TGraphicControl
{
private:
MESSAGE void __fastcall CMMouseEnter(TMessage &Msg);
MESSAGE void __fastcall CMMouseLeave(TMessage &Msg);

protected:


public:
__fastcall TSprite(TComponent* Owner);
__fastcall TSprite(lpDDs source, lpDDs dest, int w, int h, TComponent
*Owner);
bool FMouseInControl;
lpDDs src, dst;
int fx, fy, fwidth, fheight, fframes, findex, fswidth, fsheight;
void __fastcall Paint(void);

__published:
__property int x={read=fx, write=fx};
__property int y={read=fy, write=fy};
__property int spwidth={read=fwidth, write=fwidth};
__property int spheight={read=fheight, write=fheight};

BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(CM_MOUSEENTER, TMessage, CMMouseEnter)
MESSAGE_HANDLER(CM_MOUSELEAVE, TMessage, CMMouseLeave)
END_MESSAGE_MAP(TGraphicControl)
};
//---------------------------------------------------------------------------
#endif



note that the above component is not finished. I only added the Mouse Enter
and Mouse Leave detection and the Paint(), just enough for testing to see if
it is working.


Quote:
You should not be ok with it, because you should not be having to do it in
the first place.

I did set the Parent parameter of the new'ed version to "this".

Where exactly?

in my test app code, after I "new" the TSprite.

void __fastcall TForm1::Button1Click(TObject *Sender)//start the app in
DirectDraw mode
{
initDD(); //init the DirectDraw to 640x480x16,
//double buffered

//sprite1 is the "dropped" version of the component,
//i.e. design time version dropped as a visual
//component on the form
sprite1->src = lpddspot;
sprite1->dst = lpddsback;

//sprite is the runtime version, using "new"
sprite = new TSprite(this);
sprite->Parent = this;
sprite->src = lpddspot;
sprite->dst = lpddsback;
sprite->fwidth = 32;
sprite->fheight = 32;
sprite->fx = 320;
sprite->fy = 240;
Timer1->Enabled = true; //to update and flip the screen buffer
Button1->Visible = false;
Form1->SetFocus();
ready = true; //tells the updater that it weather it should update,
//to prevent AV due to lpDDs are NULL
}


Quote:


Gambit



and after careful thoughts, I might not want to have a component that paint
itself, I'd rather want a component that only paints itself when I want it
to, when I'm updating the application in the loop (think a game loop: Read
input->process/update->render screen->flip->repeat loop). I'm not sure how
is the default behavior of Paint(), but I do not want it to paint itself
when the destination surface is locked or is updating by other screen
elements, nor would I want to have a screen element that will not paint
itself (it think it is not neccessory to paint) when I want it to paint. Is
there a way to achieve this? (rather than relying on the Paint() which I
could not decide when it will activate)

Thanks.

Regards.



Back to top
Choykw
Guest





PostPosted: Sat Jun 18, 2005 5:27 am    Post subject: Re: Derived component created using "new" get no attention Reply with quote

Any help?


"Choykw" <Newsreader (AT) Newsgroup (DOT) com> wrote

Quote:

snipped




Back to top
Choykw
Guest





PostPosted: Mon Jun 20, 2005 4:19 am    Post subject: Re: Derived component created using "new" get no attention Reply with quote

please?

"Choykw" <Newsreader (AT) Newsgroup (DOT) com> wrote

Quote:
Any help?


"Choykw" <Newsreader (AT) Newsgroup (DOT) com> wrote in message
news:42b255d6 (AT) newsgroups (DOT) borland.com...

snipped




Back to top
Remy Lebeau (TeamB)
Guest





PostPosted: Mon Jun 20, 2005 6:09 pm    Post subject: Re: Derived component created using "new" get no attention Reply with quote


"Choykw" <Newsreader (AT) Newsgroup (DOT) com> wrote


Quote:
void __fastcall TSprite::CMMouseEnter(TMessage &Msg)
snip
void __fastcall TSprite::CMMouseLeave(TMessage &Msg)
snip


Neither of those are calling the base class Dispatch() method to pass on the
messages for default handling.

Quote:
void __fastcall Paint(void);

Paint() should be declared as 'protected', not 'public'.

Quote:
BEGIN_MESSAGE_MAP

A MESSAGE_MAP should be declared as 'public', not '__published'.

Quote:
//sprite is the runtime version, using "new"
sprite = new TSprite(this);
sprite->Parent = this;
sprite->src = lpddspot;
snip


Why declare a second contructor if you don't actually use it?

Quote:
and after careful thoughts, I might not want to have a component
that paint itself, I'd rather want a component that only paints itself
when I want it to

Then you should be drawing to an in-memory bitmap instead and display the
bitmap when needed. That is how typical double-buffered systems work,
especially when animation and such is involved.


Gambit



Back to top
Choykw
Guest





PostPosted: Tue Jun 21, 2005 2:42 am    Post subject: Re: Derived component created using "new" get no attention Reply with quote


"Remy Lebeau (TeamB)" <no.spam (AT) no (DOT) spam.com> wrote

Quote:

"Choykw" <Newsreader (AT) Newsgroup (DOT) com> wrote in message
news:42b255d6 (AT) newsgroups (DOT) borland.com...

void __fastcall TSprite::CMMouseEnter(TMessage &Msg)
snip
void __fastcall TSprite::CMMouseLeave(TMessage &Msg)
snip

Neither of those are calling the base class Dispatch() method to pass on
the
messages for default handling.


I was following the example in the book "C++ Builder 6 Developer Guide" from
SAMS publishing...Seems like I've yet again wasted my money on poorly
written books. The examples there never mentioned about Dispatch() method.
Strange is I've used almost identical codes to make another "Icon" type of
component (it has a graphic and a text label), the only difference is this
TSprite is drwing on a DirectDraw Surface while the TMultiIcon (thats what I
called the other one) is drawing to a TCanvas. The TMultiIcon is working
fine, it draws correctly, react to Mouse event correctly.




Quote:
void __fastcall Paint(void);

Paint() should be declared as 'protected', not 'public'.

It was originally protected, but since it is not drawing correctly, I moved
it to public so that I can call it in my test application.


Quote:

BEGIN_MESSAGE_MAP

A MESSAGE_MAP should be declared as 'public', not '__published'.

okay, this one got me there. The book DID put it in the __published area.
Sigh...guessed I should only buy books from Borland from now on.


Quote:

//sprite is the runtime version, using "new"
sprite = new TSprite(this);
sprite->Parent = this;
sprite->src = lpddspot;
snip

Why declare a second contructor if you don't actually use it?

I used both constructors in different cases. The one with only an Owner as
parameter is used when the component is dropped on the form, to avoid Access
Violation, since I haven't created the LPDIRECTDRAWSURFACEs at design time.
The second constructor is for design time creation of the component via
"new" operator. I couldn't rely on the design time constructor since I
couldn't predict any of my apps will need how many of these TSprites and
drop them at design time (well, actually I could, but that will impose
limitations on how many TSprites I could have in an app, and also waste
resource if i actually need less of them - my target machines are P200 with
32 MB RAM)


Quote:

and after careful thoughts, I might not want to have a component
that paint itself, I'd rather want a component that only paints itself
when I want it to

Then you should be drawing to an in-memory bitmap instead and display the
bitmap when needed. That is how typical double-buffered systems work,
especially when animation and such is involved.

Yes. I'm doing that, I paint to the offscreen buffer.

Thanks for your reply, I'll try to find out how the Dispatch() method works.


Quote:


Gambit





Back to top
Choykw
Guest





PostPosted: Tue Jun 21, 2005 6:54 am    Post subject: Re: Derived component created using "new" get no attention Reply with quote


"Choykw" <Newsreader (AT) Newsgroup (DOT) com> wrote

Quote:

"Remy Lebeau (TeamB)" <no.spam (AT) no (DOT) spam.com> wrote in message
news:42b70814$1 (AT) newsgroups (DOT) borland.com...

"Choykw" <Newsreader (AT) Newsgroup (DOT) com> wrote in message
news:42b255d6 (AT) newsgroups (DOT) borland.com...

void __fastcall TSprite::CMMouseEnter(TMessage &Msg)
snip
void __fastcall TSprite::CMMouseLeave(TMessage &Msg)
snip

Neither of those are calling the base class Dispatch() method to pass on
the
messages for default handling.


I was following the example in the book "C++ Builder 6 Developer Guide"
from SAMS publishing...Seems like I've yet again wasted my money on poorly
written books. The examples there never mentioned about Dispatch() method.
Strange is I've used almost identical codes to make another "Icon" type of
component (it has a graphic and a text label), the only difference is this
TSprite is drwing on a DirectDraw Surface while the TMultiIcon (thats what
I called the other one) is drawing to a TCanvas. The TMultiIcon is working
fine, it draws correctly, react to Mouse event correctly.





Okay, I made another mistake here, I missed out the Invalidate() in both
CMMouseEnter() and CMMouseLeave(). Now I solved the Paint() problem, though
as I expected, the way of letting the control painting itself is not what I
want. It paints before my test app draw to the back buffer, and when the app
is updating the back buffer, the first thing it does is blank the whole
buffer - so erasing the image of the component.

So, now what I need is a non-visual component that have mouse event...any
suggestion what should I base my component on? TControl?



Thanks in advance.



Back to top
Remy Lebeau (TeamB)
Guest





PostPosted: Tue Jun 21, 2005 5:28 pm    Post subject: Re: Derived component created using "new" get no attention Reply with quote


"Choykw" <Newsreader (AT) Newsgroup (DOT) com> wrote


Quote:
I was following the example in the book "C++ Builder 6 Developer Guide"
from SAMS publishing...Seems like I've yet again wasted my money on
poorly written books. The examples there never mentioned about Dispatch()
method.

A MESSAGE_MAP is a series of precompiler macros that override the virtual
Dispatch() method. Unless you are going to swallow the messages, you should
pass them on to the base class's Dispatch() for default handling.

Quote:
Strange is I've used almost identical codes to make another "Icon" type
of component (it has a graphic and a text label), the only difference is
this
TSprite is drwing on a DirectDraw Surface while the TMultiIcon (thats
what I called the other one) is drawing to a TCanvas. The TMultiIcon is
working fine, it draws correctly, react to Mouse event correctly.

If all you are doing is changing where the drawing is directed to, and
nothing else has changed, then there should be no reason why the TSprite
would not work as well. If you give TMultiIcon a DD surface, and make no
other changes, does it still work?

Quote:
Paint() should be declared as 'protected', not 'public'.

It was originally protected, but since it is not drawing correctly,
I moved it to public so that I can call it in my test application.

Move it back to 'protected'. You are not supposed to be calling it directly
at all.


Gabit



Back to top
Remy Lebeau (TeamB)
Guest





PostPosted: Tue Jun 21, 2005 5:30 pm    Post subject: Re: Derived component created using "new" get no attention Reply with quote


"Choykw" <Newsreader (AT) Newsgroup (DOT) com> wrote


Quote:
as I expected, the way of letting the control painting itself is not
what I want.

What EXACTLY do you want? Please be more specific.

Quote:
It paints before my test app draw to the back buffer, and when
the app is updating the back buffer, the first thing it does is blank
the whole buffer - so erasing the image of the component.

Do all of your main drawing to a bitmap, and have Paint() draw whatever is
currently in the bitmap. What are you having troubles with?

Quote:
So, now what I need is a non-visual component that have mouse event...

There is no such thing. The mouse is a visual device. It only works with
visual controls.


Gambit



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.