【问题标题】:Canvas does not allow drawing画布不允许绘图
【发布时间】:2013-04-04 12:38:00
【问题描述】:

我想将整个屏幕的屏幕截图绘制到 TForm1 画布上。

此代码在 Delphi XE3 中运行良好

procedure TForm1.Button1Click(Sender: TObject);
var
  c,scr: TCanvas;
  r,r2: TRect;
begin

  c := TCanvas.Create;
  scr := TCanvas.Create;
  c.Handle := GetWindowDC(GetDesktopWindow);
  try

    r := Rect(0, 0, 200, 200);
    form1.Canvas.CopyRect(r, c, r);

  finally
    ReleaseDC(0, c.Handle);
    c.Free;
  end;

现在我想先将屏幕截图复制到另一个画布。 有没有办法做到这一点而不会出现此错误?

procedure TForm1.Button1Click(Sender: TObject);
var
  c,scr: TCanvas;
  r,r2: TRect;
begin

  c := TCanvas.Create;
  scr := TCanvas.Create;
  c.Handle := GetWindowDC(GetDesktopWindow);
  try

    r := Rect(0, 0, 200, 200);

    scr.CopyRect(r,c,r); <-- Error, canvas does not allow drawing
    form1.Canvas.CopyRect(r, scr, r); <-- Error, canvas does not allow drawing

  finally
    ReleaseDC(0, c.Handle);
    c.Free;
  end;

【问题讨论】:

  • Canvas 不允许绘图,因为您没有指定尺寸。
  • 在这两个词中,TCanvas 必须与 TBitmap (TBitmapCanvas) 或 TForm (TControlCanvas) 或 Handle set 之类的东西直接关联。未能收到此错误。

标签: delphi delphi-xe3


【解决方案1】:

如果您需要使用额外的画布,则必须分配一个 HDC,例如

var
  WindowHandle:HWND;
  ScreenCanvas,BufferCanvas: TCanvas;
  r,r2: TRect;
  ScreenDC,BufferDC :HDC;
  BufferBitmap : HBITMAP;
begin
  WindowHandle := 0;
  ScreenCanvas := TCanvas.Create;
  BufferCanvas := TCanvas.Create;

  ScreenDC:=GetWindowDC(WindowHandle);
  ScreenCanvas.Handle := ScreenDC;

  BufferDC := CreateCompatibleDC(ScreenDC);
  BufferCanvas.Handle := BufferDC;
  BufferBitmap := CreateCompatibleBitmap(ScreenDC,
                     GetDeviceCaps(ScreenDC, HORZRES),
                     GetDeviceCaps(ScreenDC, VERTRES));
  SelectObject(BufferDC, BufferBitmap);

  try
    r := Rect(0, 0, 200, 200);
    BufferCanvas.CopyRect(r,ScreenCanvas,r);
    form1.Canvas.CopyRect(r, BufferCanvas, r);
  finally
    ReleaseDC(WindowHandle, ScreenCanvas.Handle);
    DeleteDC(BufferDC);
    DeleteObject(BufferBitmap);
    BufferCanvas.Free;
    ScreenCanvas.Free;
  end;
end;

【讨论】:

  • 一旦你这样做了,scr 就毫无意义了。你也可以直接画到bmp.Canvas
  • @RobKennedy 我知道这是一个例子,也可能是另一个 DC。
  • 这是一个非常纠结和错综复杂的例子:你根本没有多余的画布,它实际上是 bmp 的 MemDC 的一个不明显的克隆。
【解决方案2】:

是时候把我的解决方案扔进锅里了!

procedure TForm1.FormClick(Sender: TObject);
var
  ScreenCanvas: TCanvas;
begin
  ScreenCanvas := TCanvas.Create;
  try
    ScreenCanvas.Handle := GetWindowDC(GetDesktopWindow);
    Win32Check(ScreenCanvas.HandleAllocated);
    Canvas.CopyRect(Canvas.ClipRect, ScreenCanvas, ScreenCanvas.ClipRect);
  finally
    ReleaseDC(GetDesktopWindow, ScreenCanvas.Handle);
    ScreenCanvas.Free;
  end;
end;

【讨论】:

    猜你喜欢
    • 2017-11-28
    • 2010-09-10
    • 1970-01-01
    • 2017-03-19
    • 1970-01-01
    • 1970-01-01
    • 2014-11-12
    • 1970-01-01
    相关资源
    最近更新 更多