OnMouseMove without object inspector delphi - delphi

my application has 350 edit fields and all of them shall have an OnMouseMove event.
I have generated this code for all of them:
...
type
...
procedure Edit1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
procedure Edit2MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
...
implementation
{$R *.dfm}
...
procedure TForm1.Edit1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
Edit1.SetFocus();
end;
procedure TForm1.Edit2MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
Edit2.SetFocus();
end;
...
But I didn't go to the object inspector to doubleclick OnMouseMove.
Is there a way to make this work without the object inspector.
Do you have an example line of code that would make it work for the first edit field?

You can create it once and assign it in code yourself:
type
TForm1=class(TForm)
procedure EditMouseMove(Sender: TObject; Shift: TShiftState;
X, Y: Integer);
procedure FormCreate(Sender: TObject);
//...
end;
implementation
procedure TForm1.EditMouseMove(Sender: TObject; Shift: TShiftState;
X, Y: Integer);
var
CurrEdit: TEdit;
begin
if (Sender is TEdit) then
begin
CurrEdit := TEdit(Sender);
// Do whatever with CurrEdit
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Edit1.OnMouseMove := EditMouseMove;
Edit2.OnMouseMove := EditMouseMove;
Edit3.OnMouseMove := EditMouseMove;
end;
If you want to assign the same one to every TEdit on the form:
procedure TForm1.FormCreate(Sender: TObject);
var
i: Integer;
begin
for i := 0 to ControlCount - 1 do
if Controls[i] is TEdit then
TEdit(Controls[i]).OnMouseMove := EditMouseMove;
end;

Related

Rectangle drawn always is erased when the next is created

In the code below I would like the previously drawn rectangle to not be erased when the next rectangle is drawn. How achieve this?
type
TForm1 = class(TForm)
procedure FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
procedure FormMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure FormPaint(Sender: TObject);
private
{ Private declarations }
FSelecting: Boolean;
FSelection: TRect;
pos1, pos2, pos3, pos4: Integer;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
FSelection.Left := X;
FSelection.Top := Y;
FSelecting := true;
end;
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
if FSelecting then
begin
FSelection.Right := X;
FSelection.Bottom := Y;
Invalidate;
end;
end;
procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
FSelecting := false;
FSelection.Right := X;
FSelection.Bottom := Y;
Invalidate;
FSelection.NormalizeRect;
if FSelection.IsEmpty then
else
begin
pos1 := FSelection.Left;
pos2 := FSelection.Top;
pos3 := X;
pos4 := Y;
end;
end;
procedure TForm1.FormPaint(Sender: TObject);
begin
Canvas.Brush.Style := bsClear;
Canvas.Pen.Style := psSolid;
Canvas.Pen.Color := clRed;
Canvas.Rectangle(FSelection);
end;
When the form's client area is invalidated the entire surface is marked for redrawing. The next time OnPaint is called, what is painted is what is in the event handler. You draw one rectangle and so you see one.
You need to accumulate the information related to the rectangles you need to draw. Then in the paint handler, you can refer to the information and draw them all.
Below example is the slightly modified version of the code in the question. It substitutes a TQueue of rectangles in the place of unused integer variables (pos1, pos2..). A rectangle is queued and any excess rectangle is dequeued when mouse the button is released. Maximum number of recalled rectangles is defined by a constant. The paint handler enumerates the queue to draw the rectangles.
uses
..., generics.collections;
type
TForm1 = class(TForm)
procedure FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
procedure FormMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure FormPaint(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
FSelecting: Boolean;
FSelection: TRect;
FRectangles: TQueue<TRect>;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
const
MAXRECTANGLECOUNT = 2;
procedure TForm1.FormCreate(Sender: TObject);
begin
FRectangles := TQueue<TRect>.Create;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
FRectangles.Free;
end;
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
FSelection.Left := X;
FSelection.Top := Y;
FSelecting := true;
end;
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
if FSelecting then
begin
FSelection.Right := X;
FSelection.Bottom := Y;
Invalidate;
end;
end;
procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
FSelecting := false;
FSelection.Right := X;
FSelection.Bottom := Y;
Invalidate;
FSelection.NormalizeRect;
if not FSelection.IsEmpty then
begin
FRectangles.Enqueue(FSelection);
if FRectangles.Count > MAXRECTANGLECOUNT then
FRectangles.Dequeue;
end;
end;
procedure TForm1.FormPaint(Sender: TObject);
var
R: TRect;
begin
Canvas.Brush.Style := bsClear;
Canvas.Pen.Style := psSolid;
Canvas.Pen.Color := clRed;
Canvas.Rectangle(FSelection);
for R in FRectangles do
Canvas.Rectangle(R);
end;
end.

Delphi - Drag and Drop + MouseDown + MouseUp

I'm developing a drag 'n drop application and i'm feeling troubled with the Default DragCursor when Drag and Dropping an item as the following list of the default DragCursors:
So i'm trying to develop a new way to the user see the Drag 'n Drop movement like GMAIL:
My question is:
Are there the possibility to use Drag 'n drop events together Mouse events in Delphi 7?
If i put dmAutomatic in DragMode the MouseDown event does not work and if I put dmManual in DragMode the MouseDown works fine, but the DragDrop event does not work.
Here is my code below:
type
TForm1 = class(TForm)
pnlInformacaoDragDrop: TPanel;
pnl1: TPanel;
pnl2: TPanel;
procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
procedure FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure FormMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure pnl1DragDrop(Sender, Source: TObject; X, Y: Integer);
procedure pnl2DragDrop(Sender, Source: TObject; X, Y: Integer);
procedure pnl2DragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
procedure pnl1DragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
procedure pnl1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure pnl1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
private
{ Private declarations }
public
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{ TForm1 }
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
if Assigned(Self) then
begin
if pnlInformacaoDragDrop.Visible then
begin
pnlInformacaoDragDrop.Left :=X + 10;
pnlInformacaoDragDrop.Top := Y + 10;
end;
end;
end;
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if Assigned(Self) then
begin
if not pnlInformacaoDragDrop.Visible then
pnlInformacaoDragDrop.Visible := True;
// img1.BeginDrag(True);
end;
end;
procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if Assigned(Self) then
begin
if pnlInformacaoDragDrop.Visible then
pnlInformacaoDragDrop.Visible := False;
end;
end;
procedure TForm1.pnl1DragDrop(Sender, Source: TObject; X, Y: Integer);
begin
TPanel(Sender).Caption := TPanel(Sender).Caption + ' - ' + TPanel(Source).Caption;
end;
procedure TForm1.pnl2DragDrop(Sender, Source: TObject; X, Y: Integer);
begin
TPanel(Sender).Caption := TPanel(Sender).Caption + ' - ' + TPanel(Source).Caption;
end;
procedure TForm1.pnl2DragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
begin
Accept := true;
end;
procedure TForm1.pnl1DragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
begin
Accept := true;
end;
Sorry for my simple question, but I don't know how can i do it...
Thanks a lot!
You can use dmAutomatic and write a handler for the OnStartDrag event instead of the mouse events you tried to use.
From D7 documentation:
Description
Use the OnStartDrag event handler to implement special processing when
the user starts to drag the control or an object it contains.
OnStartDrag only occurs if DragKind is dkDrag.
...
The OnStartDrag event handler can create a TDragControlObjectEx
instance for the DragObject parameter to specify the drag cursor, or,
optionally, a drag image list.
Drag-n-drop is a modal operation. It necessarily will abscond with the mouse events while the button is down in order to service the drag operation.
In cmAutomatic, you're telling the component to automatically initiate a drag-n-drop operation on left button down. In dmManual, you are responsible for initiating the drag operation by calling BeginDrag from within the MouseDown event.
IOW, without grabbing the actual Windows mouse events (WM_LBUTTONDOWN, WM_MOUSEMOVE, WM_LBUTTONUP, etc..), the VCL drag-n-drop mechanism will obscure the higher-level mouse events. However, should you decide to process those messages directly, you will also break the drag-n-drop mechanism. Without carefully managing the events and the drag-n-drop subsystem, you can easily make things behave very badly.

Draw Rectangle on transparent form is very slow

AlphaBlend and DoubleBuffered set to True. I have Duo Core 2Ghz and drawing takes 100% CPU, even i had once BSOD. My goal is selecting custom area on screen and get coordinates. Enabling/disablin Windows Aero doesnt speed up. Thanks for help.
unit ZaznaczenieObszaru;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls;
type
TForm3 = class(TForm)
Image1: TImage;
procedure FormCreate(Sender: TObject);
procedure Image1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure Image1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
procedure Image1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure FormKeyPress(Sender: TObject; var Key: Char);
private
public
{ Public declarations }
end;
var
Form3: TForm3;
rysuj: boolean;
poczatekX, poczatekY, xGlobalne, yGlobalne: Integer;
kolorIzy: TColor;
implementation
{$R *.dfm}
procedure TForm3.FormCreate(Sender: TObject);
begin
Width := Screen.Width;
Height := Screen.Height;
rysuj := False;
kolorIzy := 14413224;
end;
procedure TForm3.FormKeyPress(Sender: TObject; var Key: Char);
begin
if (Key = #13) then Close;
end;
procedure TForm3.Image1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
Image1.Picture.Bitmap := nil;
Image1.Canvas.Brush.Color := kolorIzy;
poczatekX := X;
poczatekY := Y;
rysuj := true;
end;
procedure TForm3.Image1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
if rysuj = true then
begin
xGlobalne := X;
yGlobalne := Y;
Image1.Picture.Bitmap := nil;
Image1.Canvas.Brush.Color := kolorIzy;
Image1.Canvas.Rectangle(poczatekX, poczatekY, xGlobalne, yGlobalne)
end;
end;
procedure TForm3.Image1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
rysuj := False;
end;
end.
You could use a TPaintBox instead of TImage (It's Canvas is not meant for such usage as #Ken already commented) and draw your rectangle on the TPaintBox.OnPaint event. don't draw on Mouse events, but rather use TPaintBox.Invalidate. Here is an example:
procedure TForm1.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
poczatekX := X;
poczatekY := Y;
rysuj := True;
end;
procedure TForm1.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
if rysuj then
begin
xGlobalne := X;
yGlobalne := Y;
PaintBox1.Invalidate;
end;
end;
procedure TForm1.PaintBox1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
rysuj := False;
PaintBox1.Invalidate;
end;
procedure TForm1.PaintBox1Paint(Sender: TObject);
begin
if rysuj then
begin
PaintBox1.Canvas.Brush.Color := kolorIzy;
PaintBox1.Canvas.Rectangle(poczatekX, poczatekY, xGlobalne, yGlobalne);
end;
end;
I guess the same could be applied using only the TForm itself without any graphic controls, by drawing to the Form's canvas directly (same events as with the TPaintBox).
Try my NLDXPSelection component which is a non-visual component that provides drawing blue alpha blended selections on any control, form or screen. It has properties OnResize and OnFinish that tell the selection coördinates.
Source can be found here (open source).

Change color of a component when clicking down and up

I designed a component like "Tile" and I need to change the color when clicking down or up.
How can I do this?
Override the procedures MouseDown() and MouseUp() introduced in TControl to set the color of your component.
If your component does not have a color property you will need to override the Paint procedure.
type
TMyComp = Class(TGraphicControl)
private
FColor: TColor;
protected
// ....
Procedure Paint; override;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer); override;
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
override;
End;
implementation
{ TMyComp }
procedure TMyComp.MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
begin
inherited;
if Button = mbLeft then
begin
FColor := clRed;
invalidate;
end;
end;
procedure TMyComp.MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
begin
inherited;
if Button = mbLeft then
begin
FColor := clLime;
invalidate;
end;
end;
procedure TMyComp.Paint;
begin
inherited;
// ...
Canvas.Brush.Color := FColor;
Canvas.FillRect(BoundsRect);
// ....
end;

How to draw a line using mouse drag?

I need to draw a line in delphi using the cursor, I already have created the line code, but I can't get what to do next? How can do that, I push the mouse, when the line needs to start and drag my mouse or simple I release mouse button and I draw the line.
procedure TForm1.Button1Click(Sender: TObject);
var
x0, y0, x1, y1: Integer;
begin
x0 := StrToInt(Edit1.Text);
y0 := StrToInt(Edit2.Text);
x1 := StrToInt(Edit3.Text);
y1 := StrToInt(Edit4.Text);
Brezenhems(x0 , Y0 , X1 , Y1);
end;
I hope that someone helps me
Thanks
Something like this:
unit Unit4;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TForm4 = class(TForm)
procedure FormResize(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormPaint(Sender: TObject);
procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
private
{ Private declarations }
FStartPoint, FEndPoint: TPoint;
FDrawingLine: boolean;
bm: TBitmap;
procedure AddLineToCanvas;
procedure SwapBuffers;
public
{ Public declarations }
end;
var
Form4: TForm4;
implementation
{$R *.dfm}
procedure TForm4.FormCreate(Sender: TObject);
begin
bm := TBitmap.Create;
FDrawingLine := false;
end;
procedure TForm4.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
FStartPoint := Point(X, Y);
FDrawingLine := true;
end;
procedure TForm4.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
if FDrawingLine then
begin
SwapBuffers;
Canvas.MoveTo(FStartPoint.X, FStartPoint.Y);
Canvas.LineTo(X, Y);
end;
end;
procedure TForm4.FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
FDrawingLine := false;
FEndPoint := Point(X, Y);
AddLineToCanvas;
SwapBuffers;
end;
procedure TForm4.AddLineToCanvas;
begin
bm.Canvas.MoveTo(FStartPoint.X, FStartPoint.Y);
bm.Canvas.LineTo(FEndPoint.X, FEndPoint.Y);
end;
procedure TForm4.FormPaint(Sender: TObject);
begin
SwapBuffers;
end;
procedure TForm4.SwapBuffers;
begin
BitBlt(Canvas.Handle, 0, 0, ClientWidth, ClientHeight,
bm.Canvas.Handle, 0, 0, SRCCOPY);
end;
procedure TForm4.FormResize(Sender: TObject);
begin
bm.SetSize(ClientWidth, ClientHeight);
end;
end.
Compiled sample EXE
Notice that this method is simple and robust, but not optimal in terms of performance. This will likely be an issue if you try to run this on a Windows 3.1-era computer.
Another technique that can be used, without the need to create a bitmap, is using the Pen.Mode property. Something like this:
TForm2 = class(TForm)
procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
private
PO,LP: TPoint;
draw: boolean;
public
{ Public declarations }
end;
procedure TForm2.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
PO.X:= X;
PO.Y:= Y;
LP.X:= X;
LP.Y:= Y;
draw:= true;
Canvas.Pen.Mode:= pmNotXor;
end;
procedure TForm2.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
if draw then
begin
if (LP.X <> PO.X) or (LP.Y <> PO.Y) then
begin
Canvas.MoveTo(PO.X,PO.Y);
Canvas.LineTo(LP.X,LP.Y);
end;
LP.X:= X;
LP.Y:= Y;
Canvas.MoveTo(PO.X,PO.Y);
Canvas.LineTo(LP.X,LP.Y);
end;
end;
procedure TForm2.FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if draw then draw:= false;
end;

Resources