Adding a Field to a Form Object to Track Mouse Actions
Go Up to Rubber Banding Example
To track whether a mouse button was pressed, you must add an object field to the form object. When you add a component to a form, Delphi adds a field that represents that component to the form object, so that you can refer to the component by the name of its field. You can also add your own fields to forms by editing the type declaration in the form unit's header file.
In the following example, the form needs to track whether the user has pressed a mouse button. To do that, it adds a Boolean field and sets its value when the user presses the mouse button.
To add a field to an object, edit the object's type definition, specifying the field identifier and type after the public directive at the bottom of the declaration.
Delphi/C++Builder "owns" any declarations before the public directive: that's where it puts the fields that represent controls and the methods that respond to events.
The following code gives a form a field called Drawing of type bool
, in the form object's declaration. It also adds two fields to store points Origin and MovePt of type TPoint.
class TForm1 : public TForm {
__published: // IDE-managed Components
void __fastcall FormMouseDown(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y);
void __fastcall FormMouseMove(TObject *Sender, TShiftState Shift,
int X, int Y);
void __fastcall FormMouseUp(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y);
private: // User declarations
public: // User declarations
__fastcall TForm1(TComponent* Owner);
bool Drawing; // field to track whether button was pressed
TPoint Origin, MovePt; // fields to store points
};
When you have a Drawing field to track whether to draw, set it to true when the user presses the mouse button, and false when the user releases it:
void __fastcall TForm1::FormMouseDown(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y) {
Drawing = true; // set the Drawing flag
Canvas->MoveTo(X, Y); // set pen position
}
void __fastcall TForm1::FormMouseUp(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y) {
Canvas->LineTo(X, Y); // draw line from PenPos to (X, Y)
Drawing = false; // clear the Drawing flag
}
Then you can modify the OnMouseMove event handler to draw only when Drawing is true:
void __fastcall TForm1::FormMouseMove(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y) {
if (Drawing)
Canvas->LineTo(X, Y); // only draw if mouse is down }
This results in drawing only between the mouse-down and mouse-up events, but you still get a scribbled line that tracks the mouse movements instead of a straight line.
The problem is that each time you move the mouse, the mouse-move event handler calls LineTo, which moves the pen position, so by the time you release the button, you've lost the point where the straight line was supposed to start.