如何从控制中禁用图像?

时间:2015-12-25 17:36:30

标签: delphi graphics delphi-10-seattle

我把这个代码放在一起,从控件中创建一个灰度位图:

procedure TForm1.PseudoDisableControl(const AWinControl: TWinControl; const AImage: TImage);
var
  Bmp: TBitmap;
  function Control2Bitmap(Control_: TWinControl): TBitmap;
  // http://delphidabbler.com/tips/24
  begin
    Result := TBitmap.Create;
    with Result do
    begin
      Height := Control_.Height;
      Width := Control_.Width;
      Canvas.Handle := CreateDC(nil, nil, nil, nil);
      Canvas.Lock;
      Control_.PaintTo(Canvas.Handle, 0, 0);
      Canvas.Unlock;
      DeleteDC(Canvas.Handle);
    end;
  end;
type
  PRGB32Array = ^TRGB32Array;
  TRGB32Array = packed array [0 .. MaxInt div SizeOf(TRGBQuad) - 1] of TRGBQuad;
  procedure MakeGrey(Bitmap: TBitmap);
  // http://stackoverflow.com/questions/4101855/converting-a-pngimage-to-grayscale-using-delphi
  var
    w, h: integer;
    y: integer;
    sl: PRGB32Array;
    x: integer;
    grey: byte;
  begin
    Bitmap.PixelFormat := pf32bit;
    w := Bitmap.Width;
    h := Bitmap.Height;
    for y := 0 to h - 1 do
    begin
      sl := Bitmap.ScanLine[y];
      for x := 0 to w - 1 do
        with sl[x] do
        begin
          grey := (rgbBlue + rgbGreen + rgbRed) div 3;
          rgbBlue := grey;
          rgbGreen := grey;
          rgbRed := grey;
        end;
    end;
  end;
begin
  Bmp := Control2Bitmap(AWinControl);
  try
    MakeGrey(Bmp);
    AImage.AutoSize := True;
    AImage.Picture.Bitmap := Bmp;
  finally
    Bmp.Free;
  end;
end;

这会创建此结果,例如:

enter image description here

但是,我需要让图像看起来像一个禁用的控件:

enter image description here

我怎么能实现这个目标?

编辑: MBo的解决方案对我来说非常适合3,但是,通过轨道栏控制(来自TMS的TAdvTrackbar),轨道栏周围会留下一个亮区:< / p>

enter image description here

2 个答案:

答案 0 :(得分:1)

您可以使用以下公式生成对比度降低的浅灰色图片:

grey := (rgbBlue + rgbGreen + rgbRed + 2 * 255) div (3 + 2); // try also 1 instead of 2

但是如果windows主题使用另一种颜色编码方案来禁用该怎么办?

答案 1 :(得分:0)

您可以通过提供其句柄来截取任何窗口的屏幕截图:

function ScreenshotDisabledWindow(const AWindow: HWND;
  out AScreenshotBitmap: TBitmap): boolean;
var
  _Canvas: TCanvas;
  r, t: TRect;
  _WindowEnabled: boolean;
begin
  Result := False;
  if AWindow = 0 then
    Exit;

  _WindowEnabled := IsWindowEnabled(AWindow);
  _Canvas := TCanvas.Create;
  _Canvas.Handle := GetWindowDC(GetDesktopWindow);
  try
    if _WindowEnabled then
      EnableWindow(AWindow, False);

    if AWindow <> 0 then
      GetWindowRect(AWindow, t);

    r := Rect(0, 0, t.Right - t.Left, t.Bottom - t.Top);
    AScreenshotBitmap.Width := t.Right - t.Left;
    AScreenshotBitmap.Height := t.Bottom - t.Top;
    AScreenshotBitmap.Canvas.CopyRect(r, _Canvas, t);
    Result := True;
  finally
    ReleaseDC(0, _Canvas.Handle);
    FreeAndNil(_Canvas);
    EnableWindow(AWindow, _WindowEnabled);
  end;
end;

你这样称呼它:

var
  _Image: TBitmap;
begin
  _Image := TBitmap.Create;
  try
    if not ScreenshotDisabledWindow(Button1.Handle, _Image) then
      raise Exception.Create('Invalid handle provided???');

    Image1.Picture.Assign(_Image);
  finally
    FreeAndNil(_Image);
  end;