在画布上绘图 - 如何检查鼠标左键是否已关闭?

时间:2012-04-26 22:07:51

标签: delphi

我有一个Canvas,我想像MS Paint那样绘制它。

我尝试过以下方法,但没有成功:

(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)

我尝试了Canvas.OnMouseDown和Canvas.OnMouseUp的组合,如本网站的示例所示:

http://www.delphipages.com/forum/showthread.php?t=142153

(3)

GetAsyncKeyState:

http://msdn.microsoft.com/en-us/library/ms646293%28VS.85%29.aspx检测鼠标按下

(4)

Mouse.IsDraging功能。

我尝试过的上述方法仍然无法取得任何成功。

每次当我想拖动光标并绘制它时,只需将1 Rect *放在我第一次点击的位置,我该如何逐渐绘制它?

4 个答案:

答案 0 :(得分:6)

您需要跟踪是否要拖动鼠标(左按钮已关闭),保存起点,并在OnMouseUp事件中绘制您的线。 (这不会完全按照您的意愿行事,因为它不会显示您的线条的显示位置,也不会清除您之前绘制的任何线条。您需要跟踪这些线条。 OnMouseMove。但它应该让你开始。)

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.

答案 1 :(得分:3)

在MouseDown中,设置一个布尔值来表示它的向下并存储鼠标的位置。 InMouseMove如果鼠标从最后位置向下绘制到当前位置,则存储当前位置。 在MouseUp中重置布尔值

无论如何,一种方式。

答案 2 :(得分:2)

我这样做的方式是这样的:

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;

这里要注意的两件事是MouseMove事件和GetAsyncKeyState。您使用了MouseDown和MouseUp,但是继续绘图需要MouseMove。

MouseMove事件将跟踪画布上的移动。显然你只需要画画,如果你开始。要处理这个问题,你可以设置一个简单的布尔标志,正如我在{0}上演示的那样 - 当你在画布上使用MouseDown时设置为True,当你在画布上设置MouseUp时设置为False。

使用IsDrawing标记和IsDrawing,您现在可以确定是否继续在画布上绘图。如MSDN文章中所述,您需要注意GetAsyncKeyState仅跟踪物理按钮布局,而不是逻辑按钮布局:

  

GetAsyncKeyState函数适用于鼠标按钮。但是,它   检查物理鼠标按钮的状态,而不是逻辑上的   物理按钮映射到的鼠标按钮。例如,   调用GetAsyncKeyState(VK_LBUTTON)始终返回的状态   离开物理鼠标按钮,无论它是否映射到   左或右逻辑鼠标按钮。您可以确定系统   物理鼠标按钮到逻辑鼠标按钮的当前映射   调用GetSystemMetrics(SM_SWAPBUTTON)。

     

如果已交换鼠标按钮,则返回TRUE。

答案 3 :(得分:0)

如果您需要类似代码的行:

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;

或者,如果您需要免费使用抽奖:

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;