"Remy Lebeau (TeamB)" <
XXXX@XXXXX.COM >wrote in message
Quote
"Choykw" < XXXX@XXXXX.COM >wrote in message
news: XXXX@XXXXX.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 <vcl.h>
#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.
{smallsort}