Delphi 如何使窗体在没有边框的情况下透明?

Delphi 如何使窗体在没有边框的情况下透明?,delphi,delphi-xe2,Delphi,Delphi Xe2,我想知道是否有可能使表单透明(AlphaBlend),而边界(最小化按钮所在的位置以及所有这些)也不透明?如果是,我怎么做 这是可能的,但您在此类表单上放置的任何控件都将不可见 这里有一些基本代码可以帮助您入门,但我从未在带有边框的表单上使用过它,因此边框功能可能会出现问题。最可能的情况是,您必须创建包含窗口边框的位图,并将该部分的alpha设置为255 procedure PremultiplyBitmap(Bitmap: TBitmap); var Row, Col: Integer;

我想知道是否有可能使表单透明(AlphaBlend),而边界(最小化按钮所在的位置以及所有这些)也不透明?如果是,我怎么做


这是可能的,但您在此类表单上放置的任何控件都将不可见

这里有一些基本代码可以帮助您入门,但我从未在带有边框的表单上使用过它,因此边框功能可能会出现问题。最可能的情况是,您必须创建包含窗口边框的位图,并将该部分的alpha设置为255

procedure PremultiplyBitmap(Bitmap: TBitmap);
var
  Row, Col: Integer;
  p: PRGBQuad;
begin
  Bitmap.AlphaFormat := afPremultiplied;
  for Row := 0 to Bitmap.Height - 1 do
    begin
      Col := Bitmap.Width;
      p := Bitmap.ScanLine[Row];
      while (Col > 0) do
        begin
          p.rgbBlue := p.rgbReserved * p.rgbBlue div 255;
          p.rgbGreen := p.rgbReserved * p.rgbGreen div 255;
          p.rgbRed := p.rgbReserved * p.rgbRed div 255;
          inc(p);
          dec(Col);
        end;
    end;
end;

procedure PremultiplyBitmapAlpha(Bitmap: TBitmap; Alpha: byte);
var
  Row, Col: Integer;
  p: PRGBQuad;
begin
  Bitmap.AlphaFormat := afPremultiplied;
  for Row := 0 to Bitmap.Height - 1 do
    begin
      Col := Bitmap.Width;
      p := Bitmap.ScanLine[Row];
      while (Col > 0) do
        begin
          p.rgbReserved := Alpha;
          p.rgbBlue := p.rgbReserved * p.rgbBlue div 255;
          p.rgbGreen := p.rgbReserved * p.rgbGreen div 255;
          p.rgbRed := p.rgbReserved * p.rgbRed div 255;
          inc(p);
          dec(Col);
        end;
    end;
end;

procedure BlendForm(Form: TCustomForm; Bmp: TBitmap);
var
  BitmapPos: TPoint;
  BitmapSize: TSize;
  BlendFunction: TBlendFunction;
begin
   BitmapPos := Point(0, 0);
   BitmapSize.cx := Bmp.Width;
   BitmapSize.cy := Bmp.Height;

   BlendFunction.BlendOp := AC_SRC_OVER;
   BlendFunction.BlendFlags := 0;
   BlendFunction.SourceConstantAlpha := 255;
   BlendFunction.AlphaFormat := AC_SRC_ALPHA;

   UpdateLayeredWindow(Form.Handle, 0, nil, @BitmapSize, Bmp.Canvas.Handle, @BitmapPos, 0, @BlendFunction, ULW_ALPHA);
end;

procedure TForm1.CreateWnd;
var
  ExStyle: DWORD;
begin
  inherited;
  ExStyle := GetWindowLong(Handle, GWL_EXSTYLE);
  if (ExStyle and WS_EX_LAYERED = 0) then
    SetWindowLong(Handle, GWL_EXSTYLE, ExStyle or WS_EX_LAYERED);
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  Bmp: TBitmap;
begin
  Bmp := TBitmap.Create;
  try
    Bmp.PixelFormat := pf32bit;
    Bmp.Width := ClientWidth;
    Bmp.Height := ClientHeight;
    PremultiplyBitmapAlpha(Bmp, 200);
    BlendForm(Form1, Bmp);
  finally
    Bmp.Free;
  end;
end;
使用的位图必须是32位位图。如果要将整个位图与某个alpha值混合,可以使用
PremultiplyBitmapAlpha
过程,如果位图具有alpha通道,则可以使用
PremultiplyBitmap
过程

为了提高速度,您可以使用如下预乘字节表:

var
  PreMult: array[byte, byte] of byte;

procedure InitializePreMult;
var
  Row, Col: Integer;
begin
  // precalculate all possible values of a*b
  for Row := 0 to 255 do
    for Col := Row to 255 do
      PreMult[Row, Col] := Row*Col div 255;
end;
然后,
PremultiplyBitmap
过程将使用该查找表:

procedure PremultiplyBitmap(Bitmap: TBitmap);
var
  Row, Col: integer;
  p: PRGBQuad;
begin
  for Row := 0 to Bitmap.Height-1 do
  begin
    Col := Bitmap.Width;
    p := Bitmap.ScanLine[Row];
    while (Col > 0) do
    begin
      p.rgbBlue := PreMult[p.rgbReserved, p.rgbBlue];
      p.rgbGreen := PreMult[p.rgbReserved, p.rgbGreen];
      p.rgbRed := PreMult[p.rgbReserved, p.rgbRed];
      inc(p);
      dec(Col);
    end;
  end;
end;

@SirRufo我怎么做?很复杂。您希望表单部分透明-即标题栏为实心,其余为半透明。要做到这一点,请使用UpdateLayeredWindow(并使用WS_EX_LAYERED样式创建表单-谷歌获取所有这些信息)。@NGLN这张图片是从您的代码中创建的吗?它是由两个单独的屏幕截图创建的。@NGLN您是指两个单独的表单吗?