如何使用GDIPlus使矩形失效(InvalidateRect)

3
我能找到的所有GDIPlus演示代码都是没有无效绘制的。因此,当使用TImage在TScrollbox上进行MouseMove绘制时,如何在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库。
1个回答

6
InvalidateRect命令与GDI+无关。它是一条命令,告诉操作系统一个窗口的某个部分无效了,需要重新绘制。当操作系统下次决定重新绘制该窗口时,程序可以询问操作系统需要绘制多少窗口。
你的代码调用了InvalidateRect,然后又在同一部分窗口上进行了绘制。尽管如此,窗口仍然无效,因此当你下次处理wm_Paint消息时,操作系统会要求程序重新绘制该区域。
我不知道你为什么希望你的图像看起来有所不同,这与使滚动框无效无关。看起来你点击了角色的眼睛,然后向下和向右拖动鼠标,顺时针方向移动。
在每次鼠标移动时,你都会从原始点到当前鼠标位置绘制一条新线。你直接在当前显示的位图上绘制线条,然后要求图像控件重新绘制自己。它遵循并绘制位图——你刚刚添加了另一条线的位图。
我怀疑你想要发生的是每次鼠标移动都会出现一个黑色的线条,覆盖在一个未被污染的图像上。 InvalidateRect对此无济于事。你需要在以前的线条位置上重新绘制原始图像,然后再绘制新的线条。 InvalidateRect不能帮助你“撤消”以前的图形操作。它只是告诉操作系统一个窗口的某个部分应该在某个时候重新绘制。它并不说这些无效的像素应该用什么颜色重新绘制。这就是wm_Paint的作用。

谢谢你的回答。我明白你告诉我的内容,但我仍然不知道如何解决它。还有其他建议吗? - Bill
不要直接绘制到位图上,而是绘制到滚动框中。这样可以保持位图的原样。使旧线条区域无效。刷新以使图像覆盖旧线条。然后再绘制新线条。如果需要更多帮助,请提出一个关于你真正想做什么的新问题。 - Rob Kennedy
@Rob,不要绘制到位图上,而是绘制到滚动框中TScrollBox没有画布可以绘制。考虑到内容的滚动,这甚至不是一个好主意。我猜你是想说不要绘制到图像上,而是绘制到位图上,对吗? - TLama
不行,@Tlama。在位图上绘制图形正是首先引起这个问题的原因之一。在图像控件上进行绘制可能会奏效。关键是你需要在一个临时表面上进行绘制。由于位图会记录下你所绘制的内容,因此它并不符合要求。 - Rob Kennedy
@TLama - 这与在绘图处理程序之外绘制,然后在下一个绘图周期后想知道绘图可能已经消失的情况相反。Bill想要这种行为,但由于他修改了位图,所以绘图仍然存在。 - Sertac Akyuz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接