【问题标题】:How To InvalidateRect With GDIPlus如何使用 GDIPlus 使矩形无效
【发布时间】:2012-04-24 02:36:05
【问题描述】:

我能找到的所有 GDIPlus 演示代码都没有失效。那么,当在 TScrollbox 上使用 MouseMove 和 TImage 绘图时,如何使 GDIPlus API 中的矩形无效?

function NormalizeRect ( R: TRect ): TRect;
begin

  // This routine normalizes a rectangle. It makes sure that the Left,Top
  // coords are always above and to the left of the Bottom,Right coords.

  with R do
  begin

    if Left > Right then
      if Top > Bottom then
        Result := Rect ( Right, Bottom, Left, Top )
      else
        Result := Rect ( Right, Top, Left, Bottom )
    else if Top > Bottom then
      Result := Rect ( Left, Bottom, Right, Top )
    else
      Result := Rect ( Left, Top, Right, Bottom );

  end;

end;

procedure TFormMain.Image1MouseDown ( Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer );
begin
  if Line1.Down then
  begin
    GPPointStart := MakePoint ( X, Y );
  end;
end;

procedure TFormMain.Image1MouseMove ( Sender: TObject; Shift: TShiftState; X, Y: Integer );
var
  graphics: TGPGraphics;
  pen: TGPPen;
  SolidBrush: TGPSolidBrush;
  rgbTriple: windows.RGBTRIPLE;
  iRect: TRect;
begin  
  if Line1.Down then
  begin
    if ssLeft in Shift then
    begin
      iRect := NormalizeRect ( Rect ( X, Y, Image1.Picture.Bitmap.Width, Image1.Picture.Bitmap.Height ) );
      InvalidateRect ( ScrollBox1.Handle, @iRect, TRUE );
      graphics := TGPGraphics.Create ( Image1.Picture.Bitmap.Canvas.Handle );
      graphics.Flush ( FlushIntentionFlush );
      GPPointEnd := MakePoint ( X, Y );
      rgbTriple := ColorToRGBTriple ( ColorBox1.Selected );
      pen := TGPPen.Create ( MakeColor ( StrToInt ( Alpha1.Text ), rgbTriple.rgbtRed, rgbTriple.rgbtGreen, rgbTriple.rgbtBlue )
        );
      pen.SetWidth ( StrToInt ( Size1.Text ) );
      graphics.DrawLine ( pen, GPPointStart.X, GPPointStart.Y, GPPointEnd.X, GPPointEnd.Y );
      graphics.Free;
      Image1.Refresh;
    end;
   end;
end;

这是它的样子:

在 Delphi 2010 中使用来自 http://www.progdigy.com 的 GDIPlus 库。

【问题讨论】:

    标签: delphi gdi+


    【解决方案1】:

    InvalidateRect 命令与 GDI+ 无关。这是一个命令,告诉操作系统 window 的某个部分是无效的,应该重新绘制。当操作系统下一次决定重新绘制该窗口时,程序可以询问操作系统需要绘制多少窗口。

    您的代码正在调用InvalidateRect,然后它会在窗口的同一部分上进行绘制。但是,该窗口仍然无效,因此操作系统会要求您的程序稍后在您下一次处理 wm_Paint 消息时重新绘制该区域。

    我不知道您为什么希望您的图像看起来有任何不同,这与使滚动框无效无关。看起来你点击了角色的眼睛,然后顺时针向右拖动鼠标。

    每次鼠标移动时,都会从原始品脱到当前鼠标位置画一条新线。您直接在当前显示的位图上绘制线条,然后要求图像控件重绘自身。它服从并绘制位图——您刚刚添加了另一行的位图。

    我怀疑您打算发生的情况是,每次鼠标移动都会导致一条黑线出现在原本干净的图像上。 InvalidateRect 对此无济于事。您需要在前一行位置重新绘制原始图像,然后绘制新行。 InvalidateRect 不会帮助您“撤消”之前的图形操作。它只是告诉操作系统某个窗口的某个部分应该在某个时候重新绘制。它没有说明这些无效像素应该用什么颜色重新绘制。这就是wm_Paint 的用途。

    【讨论】:

    • 感谢您的回答。我明白你在告诉我什么,但我仍然不知道如何解决它。还有什么建议吗?
    • 不是绘制到位图,而是绘制到滚动框。这使位图保持不变。使旧线路区域无效。刷新以使图像覆盖旧线。然后画新线。如果您需要更多帮助,请提出一个关于您真正想要做什么的新问题。
    • @Rob,不是绘制到位图,而是绘制到滚动框TScrollBox 没有可以绘制的画布。当您考虑内容滚动时,这甚至不是一个好主意。我猜你的意思是不是绘制到图像,而是绘制到位图不是吗?
    • 不,@Tlama。绘制位图是导致此问题的部分原因。绘制到图像控件可能会起作用。底线是您需要绘制到一个无常表面。位图不符合条件,因为它会记住您绘制的内容。
    • @TLama - 这与在油漆处理程序外部绘图然后想知道在下一个油漆周期后绘图可能去了哪里相反。比尔想要这种行为,但由于他修改了位图,所以绘图仍然存在。
    猜你喜欢
    • 2011-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多