绘制画布时的范围检查错误

WeG*_*ars 3 delphi

我在这段代码中得到了Range检查错误:

{ This procedure is copied from RxLibrary VCLUtils }
procedure CopyParentImage(Control: TControl; Dest: TCanvas);
var
  I, Count, X, Y, SaveIndex: Integer;
  DC: HDC;
  R, SelfR, CtlR: TRect;
begin
  if (Control = nil) OR (Control.Parent = nil)
  then Exit;

  Count := Control.Parent.ControlCount;
  DC    := Dest.Handle;
  with Control.Parent
   DO ControlState := ControlState + [csPaintCopy];

  TRY
    with Control do
     begin
      SelfR := Bounds(Left, Top, Width, Height);
      X := -Left; Y := -Top;
     end;

    { Copy parent control image }
    SaveIndex := SaveDC(DC);
    TRY
      SetViewportOrgEx(DC, X, Y, nil);
      IntersectClipRect(DC, 0, 0, Control.Parent.ClientWidth, Control.Parent.ClientHeight);
      with TParentControl(Control.Parent) DO
       begin
        {$R-}
        Perform(WM_ERASEBKGND, DC, 0); <--------------- HERE
        {$R+}        
        PaintWindow(DC);
       end;
    FINALLY
      RestoreDC(DC, SaveIndex);
    END;

    { Copy images of graphic controls }
    for I := 0 to Count - 1 do begin
      if Control.Parent.Controls[I] = Control then Break
      else if (Control.Parent.Controls[I] <> nil) and
        (Control.Parent.Controls[I] is TGraphicControl) then
      begin
        with TGraphicControl(Control.Parent.Controls[I]) do begin
          CtlR := Bounds(Left, Top, Width, Height);
          if Bool(IntersectRect(R, SelfR, CtlR)) and Visible then
          begin
            ControlState := ControlState + [csPaintCopy];
            SaveIndex := SaveDC(DC);
            try
              SetViewportOrgEx(DC, Left + X, Top + Y, nil);
              IntersectClipRect(DC, 0, 0, Width, Height);
              {$R-}              
              Perform(WM_PAINT, DC, 0);  <--------------- HERE
              {$R+}
            finally
              RestoreDC(DC, SaveIndex);
              ControlState := ControlState - [csPaintCopy];
            end;
          end;
        end;
      end;
    end;
  FINALLY
    with Control.Parent DO
     ControlState := ControlState - [csPaintCopy];
  end;
end;
Run Code Online (Sandbox Code Playgroud)

有人在没有激活范围检查的情况下发布了代码:(

我把{$ R - } {$ R +}放在产生错误的行周围,代码现在正在运行,但我不确定会产生什么后果.我以后不想要一些奇怪的错误.


Delphi,Win 7 32bit

Rob*_*edy 9

Perform过程期望其第二个参数具有类型WParam,该类型是有符号整数类型.从Delphi 3开始,HDC实际参数的类型是无符号的(与大多数其他句柄类型一样).在基于NT的系统上,句柄的值通常高于MaxInt,这超出了范围WParam.这是范围检查错误的来源.

键入参数,你会没事的:

Perform(wm_EraseBkgnd, WParam(DC), 0);
Run Code Online (Sandbox Code Playgroud)

Perform方法将简单地将高无符号值解释为大的负值.它会将参数值发送到消息处理程序,消息处理程序会将其类型转换回HDC它想要的类型.所有类型都是相同的大小,所以没有危险.