Board index » cppbuilder » How to implement it on Forms create at Runtime?

How to implement it on Forms create at Runtime?


2004-05-27 03:34:22 PM
cppbuilder22
Hi,
I'm using 2 methods on my form, the first method is using the
event 'Image1MouseDown' to move the form when the user drag the
image with the mouse (this image is the Title of my form), the
second method is 'TForm1::WndProc' which i use to implement the
events 'OnMouseEnter' and 'OnMouseOut' on components on the
form.
The question is how do i implement this methods on Forms that i
create at runtime? (i'm using an INI file for the form's info),
for example if i create at Runtime the form 'MyNewForm', which
have MyImage on it, how do i implement this 2 methods on it?
Thanks for any help on this, the code i'm using now is bellow.
Ramy.
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void __fastcall TForm1::Image1MouseDown( TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y )
{
if ( Button == mbLeft )
{
ReleaseCapture();
SNDMSG( Form1->Handle, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0 );
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void __fastcall TForm1::WndProc( Messages::TMessage &Message )
{
if ( ( Message.Msg == CM_MOUSEENTER ) || ( Message.Msg == CM_MOUSELEAVE ) )
{
TControl* pControl = reinterpret_cast<TControl*>( Message.LParam );
if ( pControl )
{
TImage *TypeImage = dynamic_cast<TImage*>( pControl );
if ( TypeImage )
{
if ( !strcmp( TypeImage->Name.c_str(), "Image1" ) )
{
if ( Message.Msg == CM_MOUSEENTER )
{
// Mouse In, do something...
}
else
{
// Mouse Out, do something...
}
}
}
}
}
else
{
TForm::WndProc( Message );
}
}
 
 

Re:How to implement it on Forms create at Runtime?

Ramy wrote:
Quote
The question is how do i implement this methods on Forms that i
create at runtime? (i'm using an INI file for the form's info),
for example if i create at Runtime the form 'MyNewForm', which
have MyImage on it, how do i implement this 2 methods on it?
void __fastcall TForm1::Image1MouseDown( TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y )
That is NOT TMyNewForm;
Quote
{
if ( Button == mbLeft )
{
ReleaseCapture();
SNDMSG( Form1->Handle, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0 );
That last line is not ok. Now you are restricted to an instance that
assigns to Form1. Better use:
SNDMSG( this->Handle, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0 );
or
SNDMSG( Handle, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0 );
Now it acts on the right instance.
If you have one TForm1 or TMyNewForm working than every new instance
will work too.
HAns.
 

Re:How to implement it on Forms create at Runtime?

"Ramy" < XXXX@XXXXX.COM >wrote in message
Quote
SNDMSG( Form1->Handle, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0 );
You are already inside Form1, thus there is no reason to use the global
Form1 pointer. Use the implicit 'this' pointer instead:
SNDMSG( this->Handle, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0 );
or
SNDMSG( Handle, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0 );
Also, since you are already inside the form, just use the Perform() method
instead:
Perform( WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0 );
Quote
void __fastcall TForm1::WndProc( Messages::TMessage &Message )
You can shorten that code to the following:
void __fastcall TForm1::WndProc(TMessage &Message)
{
if( (Message.Msg == CM_MOUSEENTER) || (Message.Msg ==
CM_MOUSELEAVE) )
{
TControl* pControl =
reinterpret_cast<TControl*>(Message.LParam);
if( (pControl) && (pControl == Image1) )
{
if( Message.Msg == CM_MOUSEENTER )
// Mouse In, do something...
else
// Mouse Out, do something...
}
}
else
TForm::WndProc(Message);
}
With that said - since you are apparently only interested in catching the
mouse notifications for Image1 only, then you should subclass Image1
directly and not use the form's WndProc() method at all. For example:
TWndMethod OldWndProc = NULL;
__fastcall TForm1::TForm1(TComponent *Owner)
: TForm(Owner)
{
OldImageWndProc = Image1->WindowProc;
Image1->WindowProc = ImageWndProc;
}
void __fastcall TForm1::ImageWndProc(TMessage &Message)
{
if( Message.Msg == CM_MOUSEENTER )
// Mouse In, do something...
else if( Message.Msg == CM_MOUSELEAVE )
// Mouse Out, do something...
else
OldImageWndProc(Message);
}
Gambit
 

{smallsort}

Re:How to implement it on Forms create at Runtime?

"Ramy" < XXXX@XXXXX.COM >wrote in message
Quote
The question is how do i implement this methods on Forms
that i create at runtime? (i'm using an INI file for the form's info),
for example if i create at Runtime the form 'MyNewForm', which
have MyImage on it, how do i implement this 2 methods on it?
The same way you did for Form1. If you have a new class derived from TForm,
which has a TImage on it, then you can use the exact code you already have.
Or are you saying that you are creating instances of TForm itself directly?
Please show your actual code that is creating the forms.
Gambit
 

Re:How to implement it on Forms create at Runtime?

"Ramy" < XXXX@XXXXX.COM >wrote:
Quote
I'm using 2 methods on my form, the first method is using the
event 'Image1MouseDown' to move the form when the user drag
the image with the mouse
To properly do this, you should be using OnMouseDown to detect
a click on the image and OnMouseMove to do the actual moving.
Quote
second method is 'TForm1::WndProc' which i use to implement
the events 'OnMouseEnter' and 'OnMouseOut' on components on
the form.

The question is how do i implement this methods on Forms
that i create at runtime? (i'm using an INI file for the form's info),
for example if i create at Runtime the form 'MyNewForm', which
have MyImage on it, how do i implement this 2 methods on it?
You just leave it as is. Just because the form is dynamically
allocated doesn't matter. However, if you're only checking for
MouseEnter/Leave for just the TImage, I would subclass it's
WndProc method instead of overriding the form's.
Try this code (untested):
Add this to the header:
private: // User declarations
bool MouseInImage;
TPoint ClickPoint;
TWndMethod OldImageWndProc;
void __fastcall NewImageWndProc( TMessage &Message );
public: // User declarations
__fastcall TForm1(TComponent* Owner); // don't duplicate this line
__fastcall TForm1::~TForm1();
Add this to the unit:
//-------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
{
ClickPoint = Point( -1, -1 );
MouseInImage = false;
OldImageWndProc = Image1->WindowProc;
Image1->WindowProc = NewImage1WndProc;
}
//-------------------------------------------------------------
__fastcall TForm1::~TForm1()
{
Image1->WindowProc = OldImageWndProc;
}
//-------------------------------------------------------------
void __fastcall TForm1::ImageWndProc( TMessage &Message )
{
if( Message.Msg == CM_MOUSEENTER || Message.Msg == CM_MOUSELEAVE )
{
if( Message.Msg == CM_MOUSEENTER ) MouseInImage = true;
else MouseInImage = false;
}
OldImageWndProc( Message );
}
//-------------------------------------------------------------
void __fastcall TForm1::Image1MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
{
ClickPoint = Point( X, Y );
}
//-------------------------------------------------------------
void __fastcall TForm1::Image1MouseMove(TObject *Sender, TShiftState Shift, int X, int Y)
{
if( Shift.Contains(ssLeft) )
{
if( X != ClickPoint.x || Y != ClickPoint.y )
{
// the user dragged the image so ...
// get X,Y in screen relative terms
TPoint P = Image1->ClientToScreen( Point(X,Y) );
// calculate the new Left and Top
if( P.x>ClickPoint.x ) Left = Left + (P.x - ClickPoint.x);
else Left = Left - (ClickPoint.x - P.x);
if( P.y>ClickPoint.y ) Top = Top + (ClickPoint.y - P.y);
else Top = Top - (ClickPoint.y - P.y);
}
}
}
//-------------------------------------------------------------
You would need to make some minor changes if the image is
dynamically allocated but I don't think that it is - is it?
~ JD
 

Re:How to implement it on Forms create at Runtime?

Hi, thanks both for your answers (which i still trying to
understand).
Remy, here is the full code which i use to create my runtime
Form and the Image which set on it, now how to do implement
the 2 methods i was asking about in my first post on this form
and on the image which set on it, so that i can move the form
by draging the image (just like it was the form's title) and
to do something when the user move the mouse "In" and "Out"
this image?
Thanks, here is the full code -
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
TForm *MyForm;
TImage *FormTitleImage;
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
MyForm = new TForm( Application );
MyForm->Top = 250;
MyForm->Left = 300;
MyForm->Width = 400;
MyForm->Height = 400;
MyForm->Color = clBlue;
MyForm->BorderStyle = bsNone;
MyForm->FormStyle = fsStayOnTop;
// Stay OnTop
// = = = = = = =
FormTitleImage = new TImage( Application );
FormTitleImage->Parent = MyForm;
FormTitleImage->Top = 80;
FormTitleImage->Left = 80;
FormTitleImage->Width = 40;
FormTitleImage->Height = 40;
FormTitleImage->Picture->LoadFromFile( "Title.bmp" );
MyForm->Show();
}
// - - - - - - - - - - - - - - - - - - - - - -
Quote
Or are you saying that you are creating instances of TForm itself directly?
Please show your actual code that is creating the forms.


Gambit
 

Re:How to implement it on Forms create at Runtime?

"Ramy" < XXXX@XXXXX.COM >wrote:
Quote

Hi, thanks both for your answers (which i still trying to
understand).

Remy, here is the full code which i use to create my runtime
Form and the Image which set on it, now how to do implement
the 2 methods i was asking about in my first post on this form
and on the image which set on it, so that i can move the form
by draging the image (just like it was the form's title) and
to do something when the user move the mouse "In" and "Out"
this image?

Thanks, here is the full code -

#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#pragma package(smart_init)
#pragma resource "*.dfm"

TForm1 *Form1;

TForm *MyForm;
TImage *FormTitleImage;

__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{

MyForm = new TForm( Application );
You can - and I would say should - set all of these properties
in the IDE. Why are you setting them here instead?
Quote
MyForm->Top = 250;
MyForm->Left = 300;
MyForm->Width = 400;
MyForm->Height = 400;
MyForm->Color = clBlue;
MyForm->BorderStyle = bsNone;
MyForm->FormStyle = fsStayOnTop;

// Stay OnTop
// = = = = = = =

Why are you dynamically allocating the image?
Quote
FormTitleImage = new TImage( Application );
FormTitleImage->Parent = MyForm;
FormTitleImage->Top = 80;
FormTitleImage->Left = 80;
FormTitleImage->Width = 40;
FormTitleImage->Height = 40;
You need some error checking here. ANYTHING can happen to the
file once the user launches Windows Explorer. But ... if you
don't allocate the image, you can set the image picture in the
IDE so you don't need this either.
Quote
FormTitleImage->Picture->LoadFromFile( "Title.bmp" );

I don't think that this is a good place for Show but if you
insist on keeping it here, be sure that it's always the last
line in the constructor.
Quote
MyForm->Show();
}
~ JD
 

Re:How to implement it on Forms create at Runtime?

Hi JD, thanks very much for the code, i'm getting this Error
when i tried to run it -
[C++ Error] Unit1.cpp(28): E2316 '_fastcall TForm::ImageWndProc
(TMessage &)' is not a member of 'TForm'.
But i still don't get it, let me try be more clear -
When i start my application i read an INI file which tell me
how many forms to create, for example -
NumberOfForms = 7; // I should create 7 forms + images on them
Now i start 7 loops to create 7 forms which each one have an
Image on it, how do i implement the 2 methods i was asking
about on each one of this forms, so that i can drag each one
of them by pressing and dragging the Image on this form, and
so i can do something when the user move it's mouse over the
image or out of it?
All the functions in your example start with -
void __fastcall TForm1::
I understand from that prefix that the function is only for
Form1, but i want to implement it on my DINAMIC forms... i did
not understand how to do this connection...
Hope it's more clear now, this is the code that i want to use
in order to create the forms and their images -
I have this globals -
TForm *MyForm[25];
TImage *FormTitleImage[25];
and the code itself is here -
for ( i = 0; i < NumberOfForms; i++ )
{
MyForm[i] = new TForm( Application );
MyForm[i]->Top = 250 + ( num * 20 );
MyForm[i]->Left = 300 + ( num * 20 );
MyForm[i]->Width = 400;
MyForm[i]->Height = 400;
MyForm[i]->Color = clBlue;
MyForm[i]->BorderStyle = bsNone;
MyForm[i]->FormStyle = fsStayOnTop;
FormTitleImage[i] = new TImage( Application );
FormTitleImage[i]->Parent = MyForm[i];
FormTitleImage[i]->Top = 80;
FormTitleImage[i]->Left = 80;
FormTitleImage[i]->Width = 40;
FormTitleImage[i]->Height = 40;
FormTitleImage[i]->Picture->LoadFromFile( "Title.bmp" );
MyForm[i]->Show();
}
// - - - - - - - - - -
Thanks very much all,
Ramy.
 

Re:How to implement it on Forms create at Runtime?

Sorry i ment -
MyForm[i]->Top = 250 + ( i * 20 );
MyForm[i]->Left = 300 + ( i * 20 );
and not -
MyForm[i]->Top = 250 + ( num * 20 );
MyForm[i]->Left = 300 + ( num * 20 );
( 'i' instead of 'num' )
Ramy
 

Re:How to implement it on Forms create at Runtime?

Why does it looks strange to you? I created my form dynamically,
and i want to put an Image on it, how can i do that if not
dynamically? is there other way?
Ramy
Quote
Why are you dynamically allocating the image?

~ JD
 

Re:How to implement it on Forms create at Runtime?

The best approach is to subclass the TImage. Click File | New
Unit and make it look like this:
//---- in the header ------------------------------------------
#ifndef Unit1H
#define Unit1H
//-------------------------------------------------------------
//#include <ExtCtrls.hpp>
//-------------------------------------------------------------
class TMyImage : public TImage
{
protected:
virtual void __fastcall WndProc( TMessage &Message );
DYNAMIC void __fastcall MouseDown(TMouseButton Button, TShiftState Shift, int X, int Y);
DYNAMIC void __fastcall MouseMove(TShiftState Shift, int X, int Y);
private:
typedef TImage inherited;
bool MouseInImage;
TPoint ClickPoint;
void __fastcall MyMouseEnterStuff();
void __fastcall MyMouseLeaveStuff();
public:
__fastcall TMyImage( TComponent* Owner );
};
//-------------------------------------------------------------
#endif
//---- Make the unit look like --------------------------------
#include <vcl.h>// you might not need this
//-------------------------------------------------------------#pragma hdrstop
//-------------------------------------------------------------
#include "Unit1.h"
//-------------------------------------------------------------__fastcall TMyImage::TMyImage(TComponent* Owner) : TImage( Owner )
{
ClickPoint = Point( -1, -1 );
MouseInImage = false;
Parent = Owner;
Top = 80;
Left = 80;
Width = 40;
Height = 40;
// you should put this in a resouce so that the user can
// muck with it and once in a resource, it gets loaded
// into memory when the program loads so there is no disk I/O
Picture->LoadFromFile( "Title.bmp" );
}
//-------------------------------------------------------------
void __fastcall TMyImage::WndProc(TMessage &Message)
{
if( Message.Msg == CM_MOUSEENTER ) MyMouseEnterStuff();
else if( Message.Msg == CM_MOUSELEAVE ) MyMouseLeaveStuff();
inherited::WndProc(Message);
}
//-------------------------------------------------------------
void __fastcall TMyEdit::MouseDown(TMouseButton Button, TShiftState Shift, int X, int Y)
{
ClickPoint = Point( X, Y );
inherited::MouseDown(Button, Shift, X, Y);
}
//-------------------------------------------------------------
void __fastcall TMyImage::MouseMove(TShiftState Shift, int X, int Y)
{
if( Shift.Contains(ssLeft) )
{
if( X != ClickPoint.x || Y != ClickPoint.y )
{
// the user dragged the image so ...
TForm* pForm = static_cast<TMyForm*>( Owner );
// get X,Y in screen relative terms
TPoint P = ClientToScreen( Point(X,Y) );
// calculate the new Left and Top
if( P.x>ClickPoint.x ) pForm->Left = pForm->Left + (P.x - ClickPoint.x);
else pForm->Left = pForm->Left - (ClickPoint.x - P.x);
if( P.y>ClickPoint.y ) pForm->Top = pForm->Top + (ClickPoint.y - P.y);
else pForm->Top = pForm->Top - (ClickPoint.y - P.y);
}
}
inherited::MouseMove(Shift, X, Y);
}
//-------------------------------------------------------------
void __fastcall TMyImage::MyMouseEnterStuff()
{
// do on enter stuff
MouseInImage = true;
}
//-------------------------------------------------------------
void __fastcall TMyImage::MyMouseLeaveStuff()
{
// do on exit stuff
MouseInImage = false;
}
//-------------------------------------------------------------
Now save the unit and include the header in the TMyForm unit
and make that look like:
//--- add to the TMyForm header -------------------------------
private: // User declarations
TMyImage* Image;
public: // User declarations
__fastcall TMyForm(TComponent* Owner); // don't duplicate this line
__fastcall TMyForm::~TMyForm();
//--- add to the TMyForm unit ---------------------------------
__fastcall TMyForm::TMyForm(TComponent* Owner) : TForm(Owner)
{
Image = new TMyImage( this );
// set the following properties in the IDE and remove from here
Width = 400;
Height = 400;
Color = clBlue;
BorderStyle = bsNone;
FormStyle = fsStayOnTop;
}
//-------------------------------------------------------------
__fastcall TMyForm::~TMyForm()
{
delete Image;
}
//-------------------------------------------------------------
// add an OnClose event
void __fastcall TMyForm::CloseFormClose(TObject *Sender, TCloseAction &Action)
{
Action = caFree;
}
//-------------------------------------------------------------
Now in the main form:
// you don't need the form array because the form will free it's self when closed
TForm *MyForm[25];
// you don't need the image array because the form will delete it when destroyed
TImage *FormTitleImage[25];
for( int x = 0; x < NumberOfForms; ++x )
{
TMyForm* pForm = new TMyForm( this );
pForm->Left = 300 + ( x * 20 );
pForm->Top = 250 + ( x * 20 );
}
~ JD
 

Re:How to implement it on Forms create at Runtime?

"Ramy" < XXXX@XXXXX.COM >wrote:
Quote

Why does it looks strange to you? I created my form dynamically,
and i want to put an Image on it, how can i do that if not
dynamically? is there other way?
You can just drop a TImage on the form from the component's
pallette inside the IDE. However, since you want to do other
stuff with it, it's better to subclass the TImage which means
dynamically allocating it unless you make it into a component
and install it into the IDE.
~ JD
 

Re:How to implement it on Forms create at Runtime?

Hi JD, sorry for the delay, i was trying to understand your
code and how to use it, thanks very much for your much help.
First let me see if i understood your code, i open a new
Project, and call the form "MyForm", right?
Then i Click: File -->New -->Unit, and then i copy your code
of the image to the 'Unit1.h' and the 'Unit1.cpp'.
Then, as i understand, i should change the original .cpp and .h
files as you had show me, so at the end i should have project
which have 2 Cpp Files and 2 H files, right?
OK i hope that it's right, and that's what i did, and...
I got this 2 errors -
For the line
Parent = Owner; // ( in the TMyImage Constructor )
i get this error -
[C++ Error] Unit1.cpp(12): E2034 Cannot convert 'TComponent *'
to 'TWinControl *'.
and for the following line -
TForm* pForm = static_cast<TMyForm*>( Owner );
i'm getting this error -
[C++ Error] Unit1.cpp(44): E2303 Type name expected.
( Usually i'm ussing dynamic_cast , what is 'static_cast' ? )
Hope we can make this code works at the end... :-)
Thanks very much,
Ramy
 

Re:How to implement it on Forms create at Runtime?

"Ramy" < XXXX@XXXXX.COM >wrote:
Quote

Hi JD, sorry for the delay, i was trying to understand your
code and how to use it, thanks very much for your much help.

First let me see if i understood your code, i open a new
Project, and call the form "MyForm", right?
I thought that you'd do that in the current project. The
'Unit1' stuff is just the default stuff that the IDE uses
until you save it.
Quote
Then i Click: File -->New -->Unit, and then i copy your code
of the image to the 'Unit1.h' and the 'Unit1.cpp'.
Well that depends. If you haven't saved the first 2 forms or
did save them but didn't change the names, the stand alone unit
(the one with out a form) will be named Unit3.
Quote
Then, as i understand, i should change the original .cpp and .h
files as you had show me, so at the end i should have project
which have 2 Cpp Files and 2 H files, right?
The project should have a Main form, A 2nd (TMyForm) form that gets dynamically allocated and a unit without a form (TMyImage).
Quote
I got this 2 errors -

For the line

Parent = Owner; // ( in the TMyImage Constructor )
Ok. Cast the Owner to a TForm and then assign the TForm to the
Parent:
Parent = dynamic_cast<TForm*>( Owner );
Quote
and for the following line -

TForm* pForm = static_cast<TMyForm*>( Owner );

i'm getting this error -

[C++ Error] Unit1.cpp(44): E2303 Type name expected.
It doesn't know what a TMyForm is but that's ok. Just use a
TForm instead.
TForm* pForm = dynamic_cast<TForm*>( Owner );
Quote
( Usually i'm ussing dynamic_cast , what is 'static_cast' ? )
It has less overhead but can't be used here.
~ JD
 

Re:How to implement it on Forms create at Runtime?

Hi, thanks for the Errors solutions, but i'm confused and i
did not yet understood the files stuff....
Let's start from the beginning, this will be our base point -
Let's say that i had open a new project and i saved it with
the default names, so now i'm having -
Unit1.cpp
Unit1.H
Form1 ( the main form )
Now what? should i select: File -->New -->'Unit'
( Which will be Unit2.CPP and Unit2.H )
And put in it all the code that you gave me for the 'TMyImage'
Class? ( and at each place where you wrote 'Unit1' i should
write 'Unit2'... )
Correct untill now? I hope it is.
Now what i did not understand, should i put the code that you
gave me for 'TMyForm' Class at -
Unit1.cpp
Unit1.H
which are already exist? or should i choose from the menu -
File -->New -->Form
And put all the 'TMyForm' there?
Anything else?
Thanks very much,
Ramy