Link to home
Start Free TrialLog in
Avatar of AntBon
AntBon

asked on

OO/Inheritance query

Hello again !!

I am still writing some code. I have a problem with impementing a new class which has been inherited from a previous one. Can you help, or give me away round it. I have shown the code below(there is quite a bit - sorry).
--------------------------------------
#ifndef mainH
#define mainH
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include "HSClass.h"
#include "MyAutomation.h"
#include <Menus.hpp>

class TForm1 : public TForm
{
__published:      // IDE-managed Components
    void __fastcall FormPaint(TObject *Sender);
    void __fastcall FormDestroy(TObject *Sender);
    void __fastcall FormCreate(TObject *Sender);
    void __fastcall FormMouseMove(TObject *Sender, TShiftState Shift,
                    int X, int Y);
    void __fastcall FormMouseDown(TObject *Sender, TMouseButton Button,
                    TShiftState Shift, int X, int Y);

private:      // User declarations
   THotSpotList *HotSpotList;
   MyAutomation *MyAutoCursor;
   void __fastcall AppIdle(TObject *Sender, bool &Done);

public:            // User declarations
    __fastcall TForm1(TComponent* Owner);
};

extern PACKAGE TForm1 *Form1;

#endif





//---------------------------------------------------------------------------
#ifndef MyAutomationH
#define MyAutomationH
#include "HSClass.h"

class MyAutomation
   {

   TForm *mpParent;  //Pointer to object TForm

   public:
      MyAutomation(TForm *Parent);    //Constructor
      void MyMoveCursor(int SourceX, int SourceY, int DestX, int DestY, int speed
                                                ,THotSpotList *HotSpotList=NULL);

   };
#endif


//---------------------------------------------------------------------------
//---------------------------------------------------------------------------


#include "MyAutomation.h"
#pragma package(smart_init)


//Member Functions (Methods) for MyAutomation Class

MyAutomation::MyAutomation(TForm *Parent)    // code for constructor
{
   return;
}


void MyAutomation::MyMoveCursor(int SourceX, int SourceY, int DestX, int DestY, int speed
                                                     ,THotSpotList *HotSpotList)

{
TPoint P,Q ;

P.x = DestX;
P.y = DestY;

//TForm *mpParent=new TForm1;

Q = mpParent->ScreenToClient(P);
//Q = ScreenToClient(P);

return;
}


---------------------------------------

I have a problem with this bit

//TForm *mpParent=new TForm1;

Q = mpParent->ScreenToClient(P);


I have put the following in FormCreate in the main program
MyAutoCursor  = new MyAutomation(this);

Can anyone tell me why it is not working (or anything i have missed off) i think i have problem with the TForm part of things


Thanks v Much
Avatar of nietod
nietod

In what way is it not working?
Avatar of AntBon

ASKER

Ok....When i call  MyAutoCursor->MyMoveCursor(X,Y,DestX,DestY,10); from main.cpp, i get the following error

'Access violation at address 400627FE in module 'VCL40.BPL'. Read of address FFFFFFFF

Essentialy all i am trying to do is code a classs that will move the cursor from one point on the screen to another.

Cheers
That is usually due to an invalid pointer.  use the debugger to see what pointer seems to be invalid at that point.

Most likely it is mpParent.  I don't see it being set anywhere, is it?  Like the constructor might be a likely place for it to be set--I think (its hard to say what you are trying to do)--but it is not set there.
Avatar of AntBon

ASKER

nietod thanks for your reply.

Yes i agree that it is probably the mpParent pointer that is causing me problems. I have tried to set it like so

mpParent=new TForm;

But i get a compilation error which says 'Couldn't find match for TForm::TForm()'
 
I have checked in main.h and TForm1 is inherited from TForm (you can see that in the code i posted before).

So i have hit a brick wall now.
>> 'Couldn't find match for TForm::TForm()'
That means that TForm doesn't have a default constructor, so you must pass parameters to it when you construct it, like

mpParent=new TForm(pass parameters here);

But is that really what you want?  1st of all, do you want it to point to a TForm or a TForm1?  And do you want it to point a a new one that is created at that time, or to an existing one?  The MyAutomation() constructor takes a pointer to a TForm.  Is that the parent TForm?

I don't know the answers to this, only you do.
Try moving the call to the FormShow rather than Create. I get this kind of thing all the time in Delphi (same VCL) and it is because the Form is created PRIOR to being shown, hence ScreenToClient,ClientToScreen and a slew of other form related macros/functions don't yet apply. I have found that in FormShow the problem is *usually* resolved. Good Luck!!
Avatar of AntBon

ASKER

nietod, thanks again. TForm1 is a derived class based on TForm, and i need my new class to a TForm (which i have done).

Essetialy i have been given the class header files, and i need to write the method code for them - I have no problem (well not much anyway), the only thing i cannot suss out is this.

I have posted all relevant code below. As i previously mentioned all this class should do is move the cursor from A to B (it's just implementing the class which is bogging me down). I hope i am not coming across as of of those people who just wants there homework done, because this is not the case, i have genuine problem and am prepared to stick at it - but i just need a pointer (no pun intended)

Any more advice you can give would be greatfully received - Thanks



//---------------------------------------------------------------------------
#ifndef mainH
#define mainH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include "HSClass.h"
//#include "Automation.h"
#include "MyAutomation.h"
#include <Menus.hpp>


#define SHUFFLE_COUNT 10
#define ARRAY_SIZE    16
#define ARR_OFFSET    9
#define ARR_OFFSET1   7
#define MAX_ATTEMPTS  2  //Maximum no. of tries before auto-cursor
#define DestY_OFFSET  50 //Offset to ensure AutoCursor hits middle(ish) of sign


//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:      // IDE-managed Components
    void __fastcall FormPaint(TObject *Sender);
    void __fastcall FormDestroy(TObject *Sender);
    void __fastcall FormCreate(TObject *Sender);
    void __fastcall FormMouseMove(TObject *Sender, TShiftState Shift,
                    int X, int Y);
    void __fastcall FormMouseDown(TObject *Sender, TMouseButton Button,
                    TShiftState Shift, int X, int Y);

private:      // User declarations
   THotSpotList *HotSpotList;
   MyAutomation *MyAutoCursor;
   void __fastcall AppIdle(TObject *Sender, bool &Done);

public:            // User declarations
    __fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif



//---------------------------------------------------------------------------
#include <vcl.h>
#include <stdlib.h> // for randomise and random functions
#include <dos.h>
#include <string.h>
#include <winuser.h>

#pragma hdrstop
#include "main.h"


#include <mmsystem.h>
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"

int RoadSign[ARRAY_SIZE];
int PrevHotSpot=-1;
// TbltState State;

TForm1 *Form1;
//---------------------------------------------------------------------------
//This is the constuctor for the form.
__fastcall TForm1::TForm1(TComponent* Owner): TForm(Owner)
{
     Application->OnIdle = AppIdle;
     HotSpotList=NULL; //Dont allow paint until constructed
     HotSpotList = new THotSpotList(this,String("1stroad.bmp"),3);
}

//---------------------------------------------------------------------------
void __fastcall TForm1::FormPaint(TObject *Sender)
{
//Repaint the bitmap - if there is one
    if (HotSpotList) Canvas->Draw(0,0,HotSpotList->bmpBackground);
}

//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
//As the form is killed off, tell the hot spot list to destroy itself

   delete HotSpotList;

}

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{

    HotSpotList = new THotSpotList(this,"1stroad.bmp",3);
//  AutoCursor  = new TAutomation(this);
    MyAutoCursor  = new MyAutomation(this);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift,
      int X, int Y)
{

// TbltState Down,U;
//int static PrevHotSpot=-1;
int HotSpotNum = HotSpotList->GetHotSpot(X,Y);


if (HotSpotNum != PrevHotSpot) //Make sure its not the same hotspot
   if (PrevHotSpot >= 0)
      HotSpotList->HotSpot[PrevHotSpot]->BlitImage(0); // reset image


   if (HotSpotNum >= 0) // New Hotspot
      {
      HotSpotList->HotSpot[HotSpotNum]->BlitImage(1);// Show new highlight
      PrevHotSpot=HotSpotNum;
      }
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormMouseDown(TObject *Sender, TMouseButton Button,
      TShiftState Shift, int X, int Y)
{
int HotSpotNum = HotSpotList->GetHotSpot(X,Y);
int Response;
int DestX,DestY;
int static i=0,wrong=0;
//TPoint P,Q ;

   if (HotSpotNum == -1) return;

   HotSpotList->HotSpot[HotSpotNum]->BlitImage(2);
   sndPlaySound("tick.wav",SND_SYNC);
   Response = (rand() % 5) + 1; //Generate random value for response

   if (RoadSign[i] == HotSpotNum) // User has selected correct roadsign.
      {
      sndPlaySound(String("Correct"+String(Response)+String(".wav")).c_str(),SND_SYNC);
      HotSpotList->HotSpot[HotSpotNum]->MakeCold();
      wrong=0;
      if (i == 8) //Last Sign on 1st screen, so show next screen
         {
         HotSpotList = new THotSpotList(this,String("2ndroad.bmp"),3);
         Canvas->Draw(0,0,HotSpotList->bmpBackground);
         }
      else if (i == 15) //Last Sign - Terminate application
         {
         Application->Terminate();
         return;
         }

      sndPlaySound("SeeIfYouCan.wav",SND_SYNC); //Next sign to guess
      sndPlaySound(String(HotSpotList->HotSpot[RoadSign[++i]]->GetText()+
                                              String(".wav")).c_str(),SND_SYNC);
      }
   else //User has selected wrong sign
      {
      sndPlaySound(String("InCorrect"+String(Response)+String(".wav")).c_str(),SND_SYNC);
      wrong++;
      if (wrong == MAX_ATTEMPTS)
         {
         sleep(2);
         sndPlaySound(String("Help"+String(Response)+String(".wav")).c_str(),SND_SYNC);
         DestX=HotSpotList->HotSpot[RoadSign[i]]->HotX;
         DestY=HotSpotList->HotSpot[RoadSign[i]]->HotY+DestY_OFFSET;
//        MyAutoCursor->MyMoveCursor(X,Y,DestX,DestY,10,HotSpotList);
//          P.x=HotSpotList->HotSpot[RoadSign[i]]->HotX;
//          P.y=HotSpotList->HotSpot[RoadSign[i]]->HotY+DestY_OFFSET;
//          Q=ClientToScreen(P);
//          AutoCursor->MoveCursor(X,Y,DestX,DestY,10,HotSpotList);
          MyAutoCursor->MyMoveCursor(X,Y,DestX,DestY,10);
//        PostMessage(Handle,WM_MBUTTONDOWN,0,0)
         mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0); //Simulate LMB Down
//         mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0); //Simulate LMB Up
         wrong=0;
         }
      }
}
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
void __fastcall TForm1::AppIdle(TObject *Sender, bool &Done)

{
     static bool intro=true;

     if (intro)
        { //Play introduction to the game - Once only
        sndPlaySound("Intro.wav",SND_SYNC);
        sndPlaySound("SeeIfYouCan.wav",SND_SYNC);
        sndPlaySound(String(HotSpotList->HotSpot[RoadSign[0]]->GetText()+
                                             String(".wav")).c_str(),SND_SYNC);
        intro=false;
        }

//     PostMessage(WM_MOUSEMOVE);
}




//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "MyAutomation.h"
#pragma package(smart_init)

MyAutomation::MyAutomation(TForm *Parent)    // code for constructor
{
   Parent=new TForm;
   return;
}


void MyAutomation::MyMoveCursor(int SourceX, int SourceY, int DestX, int DestY, int speed
                                                     ,THotSpotList *HotSpotList)

{
TPoint P,Q ;

P.x = DestX;
P.y = DestY;

Q = mpParent->ScreenToClient(P);
//Q = ScreenToClient(P);

SetCursorPos(DestX,DestY);

return;
}


//---------------------------------------------------------------------------
#ifndef MyAutomationH
#define MyAutomationH


#include "HSClass.h"

//---------------------------------------------------------------------------

class MyAutomation
   {

   TForm *mpParent;  //Pointer to object TForm

   public:
      MyAutomation(TForm *Parent);    //Constructor
      void MyMoveCursor(int SourceX, int SourceY, int DestX, int DestY, int speed
                                                ,THotSpotList *HotSpotList=NULL);

   };

#endif


//---------------------------------------------------------------------------
Avatar of AntBon

ASKER

More advice needed

Avatar of AntBon

ASKER

nietod - I have cracked it.....many thanks for all your help.  The 'class' stuff was giving me a real headache...

I can get on with the rest of the stuff now.....Probably be speaking to you later :-).......


Thanks again
What was the problem?  Was it what I had said?
I'm interested in knowing what it was too....
Avatar of AntBon

ASKER

nietod,

you were right, i had not set mpParent pointer - i have now :-)

this is called from main.cpp

MyAutoCursor  = new MyAutomation(this);



my new class definition

class MyAutomation
   {

   TForm *mpParent;  //Pointer to object TForm

   public:
      MyAutomation(TForm *Parent);    //Constructor
      void MyMoveCursor(int SourceX, int SourceY, int DestX, int DestY, int speed
                                                ,THotSpotList *HotSpotList=NULL);

   };


my new method

MyAutomation::MyAutomation(TForm *Parent)    // code for constructor
{
   mpParent = Parent; //nietod....here it is...
   return;
}


void MyAutomation::MyMoveCursor(int SourceX, int SourceY, int DestX, int DestY, int speed
                                                     ,THotSpotList *HotSpotList)

{
TPoint P,Dest,Source;

int step=1,x=0,y,xpos=0,ypos,xdir,ydir;
float ratio,ylength,xlength;

//Convert passed Source and Dest client co-ordinates to there screen equivalent.
P.x = SourceX;
P.y = SourceY;
Source = mpParent->ClientToScreen(P); //Source co-ordinates
P.x = DestX;
P.y = DestY;
Dest = mpParent->ClientToScreen(P); //Dest co-ordinates

if (Dest.x > Source.x) //Move to the right
   {
   xdir = RIGHT;
   xlength=Dest.x - Source.x;
   }
else
   {
   xlength = Source.x - Dest.x; //Move to the left
   xdir = LEFT;
   }

if (Dest.y > Source.y) //Move Downwards
   {
   ylength=Dest.y - Source.y;
   ydir = DOWN;
   }
else
   {
   ylength = Source.y - Dest.y; //Move upwards
   ydir = UP;
   }

ratio = ylength/xlength;

ypos = Source.y;

while (xpos != Dest.x)
{
   x = x + step * xdir;
   y = abs(x) * ratio * ydir;

   xpos = x + Source.x;
   ypos = y + Source.y;
   SetCursorPos(xpos,ypos);
   Application->ProcessMessages();
   for (int pause = 0;pause < 1000000; pause++);;
}

return;

}



Incidently i have a maths problem with the MyMoveCursor method. I have coded it to move the cursor from Source to Dest, when this in a vertical direction, the cursor movement gets quicker (too quick if its very vertical), where as if is horizontal , it works ok.....basically the more vertical the direction it is the quicker the mouse cursor moves....

I reckon the problem is in the 'While' loop

Any takers.........any ideas

Thanks for the assistance
ASKER CERTIFIED SOLUTION
Avatar of nietod
nietod

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 AntBon

ASKER

Good One.....i will give that calculation a go......but my maths is not the best

I will try anyway !
Avatar of AntBon

ASKER

Good One.....i will give that calculation a go......but my maths is not the best

I will try anyway !

How would you use code a timing mechansism then ? - The only thing i can think of is sleep(), but i think that works in seconds(i'll check that out)....

sleep is in milliseconds, but its granularity is probalby at least 10 ms and its accuracty could at times be much worse, like 100 ms.  You can use GetTickCount() to get the system time in ms, with a granularity of about 10 ms.  You can also use the multimedia timer.