Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Change cursor when over TImage (and restore when exit TImage). 1

Status
Not open for further replies.

Roland1980

Programmer
Nov 7, 2003
6
0
0
NL
Hi,

The subject says it all :).

I am making an captionless form and want to drag it when over 4 small images (instead of border).

Dragging (clicking mouse when OnMouseOver etc,) is working, but I can't get it working to change the cursor when over en restore when !over.

Thx, R.
 
Hope I understand you right...here goes...

Create a form and add a TImage to it and load an image into it....

Create an event for the OnMouseMove and enter the following code in that event, supposing Form1 and Image1 the code procedure would be:

void __fastcall TForm1::Image1MouseMove(TObject *Sender, TShiftState Shift,
int X, int Y)
{
Screen->Cursor = crHourGlass;
}

This would make it so that when the cursor moves over the image then the cursor changes to the hourglass. Problem one half sorted...

The tricky bit is knowing when the mouse is no longer over the image to turn the cursor "back" to it's original...

However..

Add the following code to the main form's OnMouseMove event...

void __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift,
int X, int Y)
{
Screen->Cursor = crArrow;
}

This will make the cursor be an arrow while ever the mouse is not over the image.

This works since the mouse can not be over the image and the form at the same time. The effect is the one you're after I think... just apply the same principle to your captionless form.

Regards





 
howdy...

I have had trouble with this issue as well, and the pervious sugesstion may work, but it did not im my case. What I did was create a simple function to check the position, the set the cursor accordingly
Code:
TPoint Position = MainForm->OBJECT->ScreenToClient(Mouse->CursorPos);

 if((Position.x >= 10)
  &&(Position.x <= MainForm->OBJECT->Width)
  &&(Position.y >= 10)
  &&(Position.y <= MainForm->OBJECT->Height))
 {
  return true;
 }
 else
 {
  return false;
 }

Maybe the previous method didnt work because my form was almost completely covered with a page control. Maybe I am an idiot and didn't do it right... who knows? But this could be another route to take.

I appologize for being a moron (if not an idiot)
Hope I could help...
onrdbandit
 
Yes, the page control's OnMouseMove event would also have to reset the cursor, and any other TWinControls on the form would have to have the same code to be safe.

Since the TImage is derived from TGraphicControl and not TWinControl, it has no OnEnter/OnExit events. I would check the position each time the mouse moves (over anything). You could use a timer I suppose to check the mouse's position.

The only difference in the code above I would suggest is checking the mouse's coordinates in relation to the main form and where the TImages are.

TPoint Position = MainForm->ScreenToClient(Mouse->CursorPos);

if ((Position.x >= Image1->Left) && (Position.x <= (Image1->Left + Image1->Width)) && (Position.y >= Image1->Top) && (Position.y <= (Image1->Top + Image1->Height)))
{
}
else
{
}

Make that a function and pass in the images (Image1, Image2, etc...) and you're all set.

Chris
 
Hi all!

Consider that you can write a simple component. It based on TTimer and have an important property called PointedControl. The Timer event should check the control that mouse points, and set it to PointedComponent property.

Header fragment:
.
.
.
private:
TTimer * Timer;
TControl * _PointedControl;
void __fastcall SetPointedControl(TControl * value);
void __fastcall TimerTick(TObject * Sender);

public:
__fastcall TMyHitOutComponent(TComponent * AOwner); //constructor
virtual void __fastcall BeforeDestruction();
__property TControl * PointedControl = { read=_PointedControl, write=SetPointedControl } //why public? If user set Enabled to false, she/he can simulate the hit/out events

protected:
virtual void __fastcall SetEnabled(bool value);

__published:
...
.
.
.

Implementation fragment:
.
.
.
__fastcall TMyHitOutComponent::TMyHitOutComponent(TComponent * AOwner) : TComponent(AOwner)
{
Timer=new TTimet(this);
Timer->Enabled=true; //this is the default for every component in Builder
Timer->OnTimer=TimerTick;
Timer->Interval=100; //you can publish this property called Sensitivity or sumthin'
}

void __fastcall TMyHitOutComponent::SetEnabled(bool value)
{
TComponent::SetEnabled(value);
Timer->Enabled=value;
PointedControl=NULL;
}

void __fastcall TMyHitOutComponent::BeforeDestruction()
{
PointedControl=NULL;
TComponent::BeforeDestruction();
}

void __fastcall TMyHitOutComponent::TimerTick(TObject * Sender)
{
TControl * pointedcont=NULL;
//here you check out for control that mouse point, if none (when mouse points outside from Owner) or == Owner leave pointedcont NULL (see the code above in that thread)
.
.
.
PointedControl=pointedcont;
}

void __fastcall TMyHitOutComponent::SetPointedControl(TControl * value)
{
if (_PointedControl!=value)
{
DWORD Coords=(Mouse->CursorPos.y<<16) | Mouse->CursorPos.x;
if (_PointedControl) _PointedControl->Perform(WM_LBUTTONUP,MK_LBUTTON,Coords);
_PointedControl=value;
if (_PointedControl) _PointedControl->Perform(WM_LBUTTONDOWN,MK_LBUTTON,Coords);
}
}
.
.
.

If done, install this nonvisual component for yer Builder &quot;MyBestComponent&quot; palette, and drop it to any form/frame (just for the record TFrame was the reasont why i've payed for Builder 6.0 more than 1.000 USD).

For example drop a TButton to that form. Create event handlers for OnMouseDown and OnMouseUp

void __fastcall TMyCoolForm::MyCoolButtonMouseDown(System::TObject* Sender, TMouseButton Button, Classes::TShiftState Shift, int X, int Y)
{
//and here is the trick:
if (Sender==MyHitOutComponent)
{
//for example:
MyCoolButton->Font->Style=MyCoolButton->Font->Style << fsBold;
}
else
{
//the REAL OnMouseDown handler
}
}

void __fastcall TMyCoolForm::MyCoolButtonMouseUp(System::TObject* Sender, TMouseButton Button, Classes::TShiftState Shift, int X, int Y)
{
//and here is the trick:
if (Sender==MyHitOutComponent)
{
//for example:
MyCoolButton->Font->Style=MyCoolButton->Font->Style >> fsBold;
}
else
{
//the REAL OnMouseUp handler
}
}

That's it. Give it a try.

unbornchikken

p.s.: For advanced users you can publish a TClass ThatTypeOnly property with a custom property editor like New Component wizard inheritance chooser section. And change the SetPointedControl code like this:

void __fastcall TMyHitOutComponent::SetPointedControl(TControl * value)
{
if (_PointedControl!=value)
{
DWORD Coords=(Mouse->CursorPos.y<<16) | Mouse->CursorPos.x;
if (_PointedControl && _PointedControl->InheritsFrom(_ThatTypeOnly)) _PointedControl->Perform(WM_LBUTTONUP,MK_LBUTTON,Coords);
_PointedControl=value;
if (_PointedControl && _PointedControl->InheritsFrom(_ThatTypeOnly)) _PointedControl->Perform(WM_LBUTTONDOWN,MK_LBUTTON,Coords);
}
}

Modify yer form/frame constructor to this, or use yer nice property editor.

MyHitOutComponent->ThatTypeOnly=__classid(TButton);

p.p.s.: Consider that you better publish a TWinControl * Container property to avoid use of Owner in TimerTick method.

p.p.p.s.: It's important if you delete a control manually, you should do this before:

if (MyHitOutComponent->PointedControl==IllKillThisControl) MyHitOutComponent->PointedControl=NULL;
//the timer wont tick before the next command, that lies in same thread, so you can:
delete IllKillThisControl;

p.p.p.p.s.: It's just an idea i haven't tested this code, so it might contains some bugs.
 
Sorry, i've ****ed it up. Here is the correct code:

void __fastcall TMyHitOutComponent::SetPointedControl(TControl * value)
{
if (_PointedControl!=value)
{
DWORD Coords=(Mouse->CursorPos.y<<16) | Mouse->CursorPos.x;
TControl * prevcontrol=_PointedControl;
_PointedControl=value;
if (prevcontrol)
{
prevcontrol->Tag=1;
prevcontrol->Perform(WM_LBUTTONUP,MK_LBUTTON,Coords);
prevcontrol=Tag=0;
}
if (_PointedControl)
{
_PointedControl->Tag=1;
_PointedControl->Perform(WM_LBUTTONDOWN,MK_LBUTTON,Coords);
_PointedControl->Tag=0;
}
}
}

void __fastcall TMyCoolForm::MyCoolButtonMouseDown(System::TObject* Sender, TMouseButton Button, Classes::TShiftState Shift, int X, int Y)
{
//and here is the trick:
if (((TControl *)Sender->Tag) && Sender==MyHitOutComponent->PointedControl)
{
//for example:
MyCoolButton->Font->Style=MyCoolButton->Font->Style << fsBold;
}
else
{
//the REAL OnMouseDown handler
}
}

void __fastcall TMyCoolForm::MyCoolButtonMouseUp(System::TObject* Sender, TMouseButton Button, Classes::TShiftState Shift, int X, int Y)
{
//and here is the trick:
if (((TControl *)Sender->Tag) && Sender==MyHitOutComponent->PointedControl)
{
//for example:
MyCoolButton->Font->Style=MyCoolButton->Font->Style >> fsBold;
}
else
{
//the REAL OnMouseUp handler
}
}

You can use a betted event administration strategy than Tag propery...

unbornchikken
 
Hi BuilderSpec, onrdbandit, Supernat03 & unbornchikken,

It has been a while since I posted this question, but thanks so much! Really apreciate it!

Helped me also to understand some things a bit better.


Best wishes for the new year to all,

Roland(BE).
 
Hi :)

Just install this Delphi TImage component in C++Builder, Save the contents between =Start= and =Stop= as HighlightImage.pas file.

It will add OnMouseEnter and OnMouseLeave events for the TImage

=Start=

unit HighlightImage;

interface
uses Messages, Controls, Classes, StdCtrls ,Graphics ,SysUtils,ExtCtrls;


type
THighlightImage = class(TImage)
private
FOnMouseEnter: TNotifyEvent;
FOnMouseLeave: TNotifyEvent;
public
procedure MouseEnter(var msg : TMessage); message CM_MOUSEENTER;
procedure MouseLeave(var msg : TMessage); message CM_MOUSELEAVE;
published
property OnMouseEnter: TNotifyEvent read FOnMouseEnter write FOnMouseEnter;
property OnMouseLeave: TNotifyEvent read FOnMouseLeave write FOnMouseLeave;
end;

procedure Register;

implementation

{ THighlightImage }

procedure THighlightImage.MouseEnter(var msg: TMessage);
begin
if Assigned(FOnMouseEnter) then FOnMouseEnter(self);
end;

procedure THighlightImage.MouseLeave(var msg: TMessage);
begin
if Assigned(FOnMouseLeave) then FOnMouseLeave(self);
end;

procedure Register;
begin
RegisterComponents('Samples', [THighlightImage]);
end;

end.


=end=
 
just change the cursor property of the image to waht ever you desire at design time or do it somwhere at run time.

it will chnge back and forth on its own accord in the proper time by itself when you move the cursor over and away from the image..

entirely to much thought is going on here to accomplish a simple task.

tomcruz.net
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top