Reputation: 1819
I have a Canvas, and I want to draw on it like MS Paint for example.
I have tried the following methods but with no success:
(1)
Canvas.OnMouseDown
procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
//Draw something (Lets say a rect for example*)
Image1.Canvas.Rectangle(x,y,x+4,y+4);
end;
(2)
I tried Canvas.OnMouseDown and Canvas.OnMouseUp combined as shown on in an example from this site:
http://www.delphipages.com/forum/showthread.php?t=142153
(3)
GetAsyncKeyState:
http://msdn.microsoft.com/en-us/library/ms646293%28VS.85%29.aspx to detect mouse downs
(4)
Mouse.IsDraging function.
I still cannot get any success with the above methods I have tried.
Every time when I want to drag the cursor and draw it justs places 1 Rect* at the position where I first clicked, how do I get it to progressively draw?
Upvotes: 0
Views: 4684
Reputation: 1921
if you need line like up code :
procedure TForm1.img1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
(Sender as TImage).Canvas.MoveTo(X, Y);
end;
procedure TForm1.img1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
(Sender as TImage).Canvas.LineTo(X, Y);
end;
or , if you need draw free-from line use:
procedure TForm1.img1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
with (Sender as TImage) do begin
if Shift = [ssLeft] then
Canvas.LineTo(X, Y);
Canvas.MoveTo(X, Y);
end;
end;
Upvotes: 0
Reputation:
The way I would do it is like this:
var
Form1: TForm1;
IsDrawing: Boolean; // flag to determine if drawing or not
implementation
{$R *.dfm}
procedure DoPaint(ACanvas: TCanvas; X, Y: Integer; AColor: TColor;
ASize: Integer; AStyle: TPenStyle; Persistent: Boolean);
begin
with ACanvas do
begin
Pen.Color := AColor;
Pen.Style := AStyle;
Pen.Width := ASize;
if not Persistent then
MoveTo(X, Y);
LineTo(X, Y);
end;
end;
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
case Button of
mbLeft:
begin
IsDrawing := True;
DoPaint(Form1.Canvas, X, Y, clBlue, 10, psSolid, False);
end;
end;
end;
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
if (GetAsyncKeyState(VK_LBUTTON) <> 0) and
(IsDrawing) then
begin
DoPaint(Form1.Canvas, X, Y, clBlue, 10, psSolid, True);
end;
end;
procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
IsDrawing := False;
end;
Two things to note here are the MouseMove event and GetAsyncKeyState. You used MouseDown and MouseUp, but MouseMove which is needed to continue the drawing.
The MouseMove event will track the movement on the canvas. Obviously you only need to draw if you were to begin with. To handle this you can set a simple Boolean flag as I have demonstrated using IsDrawing
- This is set to True when you MouseDown on the canvas, and set to False when you MouseUp on the canvas.
Using the IsDrawing
flag along with GetAsyncKeyState
you can now determine whether to continue drawing on the canvas or not. As described in the MSDN article you need to be aware that GetAsyncKeyState
only tracks the physical button layout, not the logical ones:
The GetAsyncKeyState function works with mouse buttons. However, it checks on the state of the physical mouse buttons, not on the logical mouse buttons that the physical buttons are mapped to. For example, the call GetAsyncKeyState(VK_LBUTTON) always returns the state of the left physical mouse button, regardless of whether it is mapped to the left or right logical mouse button. You can determine the system's current mapping of physical mouse buttons to logical mouse buttons by calling GetSystemMetrics(SM_SWAPBUTTON).
which returns TRUE if the mouse buttons have been swapped.
Upvotes: 2
Reputation: 125708
You need to track whether or not you're dragging the mouse (the left button is down), save where the starting point is, and in the OnMouseUp
event draw your line. (This won't fully do what you want, because it doesn't show where your line will appear, and won't clear any previous lines you've drawn. You need to track those in OnMouseMove
. It should get you started, though.)
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Vcl.Graphics,
Controls, Forms, Dialogs;
type
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
{ Private declarations }
Drawing: Boolean;
mX, mY: Integer;
public
{ Public declarations }
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
procedure TForm2.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if [ssLeft] = Shift then
begin
Drawing := True;
mX := X;
mY := Y;
end;
end;
procedure TForm2.FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Drawing and not (ssLeft in Shift) then // Left button released
begin
Canvas.MoveTo(mX, mY);
Canvas.LineTo(X, Y);
Drawing := False;
end;
end;
end.
Upvotes: 6
Reputation: 20320
In MouseDown, set a boolean to say its down and store the position of the mouse. InMouseMove if the mouse is down draw from last position to current position, store current position. In MouseUp reset the boolean
One way, anyway.
Upvotes: 3