0

我有一个画布,我想像 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

4 回答 4

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.
于 2012-04-26T22:19:28.690 回答
3

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

无论如何,一种方式。

于 2012-04-26T22:13:45.590 回答
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 事件将跟踪画布上的移动。显然,如果你要开始的话,你只需要画画。要处理这个问题,你可以设置一个简单的布尔标志,正如我所演示的那样IsDrawing- 当你在画布上 MouseDown 时设置为 True,当你在画布上 MouseUp 时设置为 False。

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

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

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

于 2012-04-27T10:39:12.940 回答
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;
于 2012-04-29T19:55:46.113 回答