Solved

OO/Inheritance query

Posted on 2000-04-08
16
227 Views
Last Modified: 2010-04-02
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
0
Comment
Question by:AntBon
  • 8
  • 6
  • 2
16 Comments
 
LVL 22

Expert Comment

by:nietod
ID: 2696454
In what way is it not working?
0
 

Author Comment

by:AntBon
ID: 2696561
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
0
 
LVL 22

Expert Comment

by:nietod
ID: 2696583
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.
0
 

Author Comment

by:AntBon
ID: 2696709
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.
0
 
LVL 22

Expert Comment

by:nietod
ID: 2696827
>> '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.
0
 
LVL 6

Expert Comment

by:DrDelphi
ID: 2697060
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!!
0
 

Author Comment

by:AntBon
ID: 2697488
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


//---------------------------------------------------------------------------
0
 

Author Comment

by:AntBon
ID: 2697495
More advice needed

0
Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

 

Author Comment

by:AntBon
ID: 2697554
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
0
 
LVL 22

Expert Comment

by:nietod
ID: 2697579
What was the problem?  Was it what I had said?
0
 
LVL 6

Expert Comment

by:DrDelphi
ID: 2697756
I'm interested in knowing what it was too....
0
 

Author Comment

by:AntBon
ID: 2697778
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
0
 
LVL 22

Accepted Solution

by:
nietod earned 25 total points
ID: 2697831
It looks to me like the loop is trying to always move 1 x pixel on each movement.  But if the line is nearly vertical, or is vertical, that 1 pixel x movement cooresponds to a very large y pixel movement.  

You need to make the cursor move 1 pixel (or some other distance) in the desired direction, not in the x or y direction.

You are going to have rounding problems this way, so to make it wor right, for each step of the calcualtion you will have to start the calculation of from the starting point, not the last point the cursor was at.  You can figure out the total distance to be traveled using the pythagorean theorem.  This tells you how many total steps to take (how many loops to run)

For each step (iteraton of the loop) you set the new x to the old x (source x) plus the current step number times total x distance (destination x - source x) divided by the number of total steps.  You do the same with the Y.

You realy must use a better timing mechanism than
>>for (int pause = 0;pause < 1000000; pause++);;
0
 

Author Comment

by:AntBon
ID: 2698046
Good One.....i will give that calculation a go......but my maths is not the best

I will try anyway !
0
 

Author Comment

by:AntBon
ID: 2698051
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)....

0
 
LVL 22

Expert Comment

by:nietod
ID: 2698086
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.
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

  Included as part of the C++ Standard Template Library (STL) is a collection of generic containers. Each of these containers serves a different purpose and has different pros and cons. It is often difficult to decide which container to use and …
This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
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 additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

708 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

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now