DELPHI开发人员指南例子8.3,我看到一个小问题不太明白。
procedure TMainForm.GetCanvasRect里:
  R := AImage.Canvas.ClipRect;
  with AImage do begin
    ARect.TopLeft     := Point(0, 0);
    ARect.BottomRight := Point(Width, Height);
  end;
  R2 := ARect;
  ARect := R2;
其中R := AImage.Canvas.ClipRect,我感觉一点用也没有,就是浪费啊?还有  R2 := ARect;
  ARect := R2;这句话,我实在是想不出是为什么这样,这样赋值有意义吗?!!请高手指点{
Copyright ?1999 by Delphi 5 Developer's Guide - Xavier Pacheco and Steve Teixeira
}unit MainFrm;interfaceuses
  SysUtils, Windows, Messages, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls;type  TMainForm = class(TForm)
    imgCopyTo: TImage;
    imgCopyFrom: TImage;
    cbCopyMode: TComboBox;
    btnDrawImages: TButton;
    btnCopy: TButton;
    procedure FormShow(Sender: TObject);
    procedure btnCopyClick(Sender: TObject);
    procedure btnDrawImagesClick(Sender: TObject);
  private
    procedure DrawImages;
    procedure GetCanvasRect(AImage: TImage; var ARect: TRect);
  end;var
  MainForm: TMainForm;implementation{$R *.DFM}procedure TMainForm.GetCanvasRect(AImage: TImage; var ARect: TRect);
var
  R: TRect;
  R2: TRect;
begin
  R := AImage.Canvas.ClipRect;
  with AImage do begin
    ARect.TopLeft     := Point(0, 0);
    ARect.BottomRight := Point(Width, Height);
  end;
  R2 := ARect;
  ARect := R2;
end;procedure TMainForm.DrawImages;
var
  R: TRect;
begin
  // Draw an ellipse in img1
  with imgCopyTo.Canvas do
  begin
    Brush.Style := bsSolid;
    Brush.Color := clWhite;
    GetCanvasRect(imgCopyTo, R);
    FillRect(R);
    Brush.Color := clRed;
    Ellipse(10, 10, 100, 100);
  end;  // Draw an ellipse in img2
  with imgCopyFrom.Canvas do
  begin
    Brush.Style := bsSolid;
    Brush.Color := clWhite;
    GetCanvasRect(imgCopyFrom, R);
    FillRect(R);
    Brush.Color := clBlue;
    Ellipse(30, 30, 120, 120);
  end;end;procedure TMainForm.FormShow(Sender: TObject);
begin
  // Initialize the combobox to the first item
  cbCopyMode.ItemIndex := 0;
  DrawImages;
end;procedure TMainForm.btnCopyClick(Sender: TObject);
var
  cm: Longint;
  CopyToRect,
  CopyFromRect: TRect;
begin
  // Determine the copy mode based on the combo box selection
  case cbCopyMode.ItemIndex of
   0:  cm := cmBlackNess;
   1:  cm := cmDstInvert;
   2:  cm := cmMergeCopy;
   3:  cm := cmMergePaint;
   4:  cm := cmNotSrcCopy;
   5:  cm := cmNotSrcErase;
   6:  cm := cmPatCopy;
   7:  cm := cmPatInvert;
   8:  cm := cmPatPaint;
   9:  cm := cmSrcAnd;
   10: cm := cmSrcCopy;
   11: cm := cmSrcErase;
   12: cm := cmSrcInvert;
   13: cm := cmSrcPaint;
   14: cm := cmWhiteness;
   else
     cm := cmSrcCopy;
  end;  // Assign the selected copymode to Image1's CopyMode property.
  imgCopyTo.Canvas.CopyMode := cm;
  GetCanvasRect(imgCopyTo, CopyToRect);
  GetCanvasRect(imgCopyFrom, CopyFromRect);  // Now copy Image2 onto Image1 using Image1's CopyMode setting
  imgCopyTo.Canvas.CopyRect(CopyToRect, imgCopyFrom.Canvas, CopyFromRect);
end;procedure TMainForm.btnDrawImagesClick(Sender: TObject);
begin
  DrawImages;
end;end.

解决方案 »

  1.   

    procedure TMainForm.GetCanvasRect(AImage: TImage; var ARect: TRect);
    var
      R: TRect;
      R2: TRect;
    begin
      R := AImage.Canvas.ClipRect;//在过程GetCanvasRect里锁定Canvas以免别更改,当GetCanvasRect结束便释放
      with AImage do begin
        ARect.TopLeft     := Point(0, 0);
        ARect.BottomRight := Point(Width, Height);
      end;
      R2 := ARect;
      ARect := R2;//因为ARect是传地址,所以为防止ARect在GetCanvasRect结束前意外更改,先保存为R2并在结束时赋给ARect
    end;
      

  2.   

    测试:点击Button1可以看到在事件没有结束前没有执行BitBtn1。直接点击BitBtn1看看。
    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, Buttons, jpeg, ExtCtrls;type
      TForm1 = class(TForm)
        Button1: TButton;
        Image1: TImage;
        BitBtn1: TBitBtn;
        procedure Button1Click(Sender: TObject);
        procedure BitBtn1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
    var rec:trect;
        i:integer;
    begin
         rec:=Image1.Canvas.ClipRect;
         for i:=0 to 2 do
         begin
            sleep(100);
            BitBtn1.OnClick(nil);
         end;
    end;procedure TForm1.BitBtn1Click(Sender: TObject);
    var b:boolean;
        REC:TRECT;
    begin
         REC.TopLeft:=POINT(0,0);
         REC.BottomRight:=POINT(100,100);
         Image1.Canvas.StretchDraw(REC,Image1.Picture.Graphic);
    end;end.
      

  3.   

    R := AImage.Canvas.ClipRect;//我理解错了,刚才用多线程重新测试。因为我跟踪ClipRect的实现没有进行锁定。应该是检查AImage.Picture
    选择project->options->compiler->选择USE DEBUG DCUS
    在R := AImage.Canvas.ClipRect设断点,跟踪进去发现它调用
    function TImage.GetCanvas: TCanvas;
    var
      Bitmap: TBitmap;
    begin
      if Picture.Graphic = nil then
      begin
    Bitmap := TBitmap.Create;
    try
      Bitmap.Width := Width;
      Bitmap.Height := Height;
      Picture.Graphic := Bitmap;
    finally
      Bitmap.Free;
    end;
      end;
      if Picture.Graphic is TBitmap then
    Result := TBitmap(Picture.Graphic).Canvas
      else
    raise EInvalidOperation.Create(SImageCanvasNeedsBitmap);
    end;所以我理解他的用意就是要检查你的图片格式是否正确,没有别的什么。这样写简洁有效。我也刚看DELPHI开发人员指南,以后多交流
      

  4.   

    struggle813(深蓝大道) 的说法值得商榷,
    >>他的用意就是要检查你的图片格式是否正确,没有别的什么
    如果如你所说,那用如下更加简洁,而且省了调用多一个过程的开销
    var R: TCanvas;
    begin
    R := AImage.Canvas;省略了调用 ClipRect 的开销! 那说明,关键是在 ClipRect ,
    当然,GetCanvas 也发挥作用,我想,先保证一定有个canvas看 ClipRect 是什么作用:
    property ClipRect: TRect read GetClipRect;function TCanvas.GetClipRect: TRect;
    begin
      RequiredState([csHandleValid]);
      GetClipBox(FHandle, Result);
    end;追踪到 TCanvas, 发现了这句代码,RequiredState([csHandleValid]);
    RequiredState 在 TCanvas 中很多地方用到,但在这里,实际好像没做什么,
    所以,我理解是一种预留的机制,在将来,可能在
    procedure TCanvas.CreateHandle;
    begin
    end;
    加入处理代码! 
    至于现在,主要是检查当前的 handle是否有效, 否则,
    raise EInvalidOperation.CreateRes(@SNoCanvasHandle);
      

  5.   

    property Graphic: TGraphic read FGraphic write SetGraphic;
      
    TGraphicClass = class of TGraphic;  { TPicture }
      { TPicture is a TGraphic container.  It is used in place of a TGraphic if the
        graphic can be of any TGraphic class.  LoadFromFile and SaveToFile are
        polymorphic. For example, if the TPicture is holding an Icon, you can
        LoadFromFile a bitmap file, where if the class was TIcon you could only read
        .ICO files.
          LoadFromFile - Reads a picture from disk.  The TGraphic class created
            determined by the file extension of the file.  If the file extension is
            not recognized an exception is generated.
          SaveToFile - Writes the picture to disk.
          LoadFromClipboardFormat - Reads the picture from the handle provided in
            the given clipboard format.  If the format is not supported, an
            exception is generated.
          SaveToClipboardFormats - Allocates a global handle and writes the picture
            in its native clipboard format (CF_BITMAP for bitmaps, CF_METAFILE
            for metafiles, etc.).  Formats will contain the formats written.
            Returns the number of clipboard items written to the array pointed to
            by Formats and Datas or would be written if either Formats or Datas are
            nil.
          SupportsClipboardFormat - Returns true if the given clipboard format
            is supported by LoadFromClipboardFormat.
          Assign - Copys the contents of the given TPicture.  Used most often in
            the implementation of TPicture properties.
          RegisterFileFormat - Register a new TGraphic class for use in
            LoadFromFile.
          RegisterClipboardFormat - Registers a new TGraphic class for use in
            LoadFromClipboardFormat.
          UnRegisterGraphicClass - Removes all references to the specified TGraphic
            class and all its descendents from the file format and clipboard format
            internal lists.
          Height - The native, unstretched, height of the picture.
          Width - The native, unstretched, width of the picture.
          Graphic - The TGraphic object contained by the TPicture
          Bitmap - Returns a bitmap.  If the contents is not already a bitmap, the
            contents are thrown away and a blank bitmap is returned.
          Icon - Returns an icon.  If the contents is not already an icon, the
            contents are thrown away and a blank icon is returned.
          Metafile - Returns a metafile.  If the contents is not already a metafile,
            the contents are thrown away and a blank metafile is returned. }
      

  6.   

    我觉得aiirii(ari-淘金坑) 说的有道理,也谢谢struggle813(深蓝大道) 了。
    aiirii(ari-淘金坑)原来叫爱的眼睛吧?!!呵呵