オブジェクトを表示可能なAlphaBlendフォーム

解決


boon  2009-10-10 08:23:39  No: 35860

まずやりたい事。
VCLコンポーネントを配置してあるフォームの背景だけを透明にして、32bitのビットマップを背景を透けるように表示したい。

やった事。

その①
UpdateLayeredWindow関数を使う。
これだと背景(デスクトップ等)とビットマップはうまくブレンド出来るけど、オブジェクトが表示されなくなってしまう。

procedure TForm1.FormCreate(Sender: TObject);
var
  BlendFunction: TBlendFunction;
  BitmapPos: TPoint;
  BitmapSize: TSize;
  exStyle: DWORD;
  Bitmap: TBitmap;
begin
  // Enable window layering
  exStyle := GetWindowLongA(Handle, GWL_EXSTYLE);
  if (exStyle and WS_EX_LAYERED = 0) then
    SetWindowLong(Handle, GWL_EXSTYLE, exStyle or WS_EX_LAYERED);

  Bitmap := TBitmap.Create;
  try
    Bitmap.LoadFromFile('test.bmp');
    Bitmap.PixelFormat = pf32bit;

    ClientWidth := Bitmap.Width;
    ClientHeight := Bitmap.Height;

    BitmapPos := Point(0, 0);
    BitmapSize.cx := Bitmap.Width;
    BitmapSize.cy := Bitmap.Height;

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

    UpdateLayeredWindow(Handle, 0, nil, @BitmapSize, Bitmap.Canvas.Handle, @BitmapPos, 0, @BlendFunction, ULW_ALPHA);

  finally
    Bitmap.Free;
  end;
end;

その②
TransparentColorを使い背景を透明にしてから、アルファなビットマップを絵画する。
これだとオブジェクトは表示されるけど、ビットマップが背景ではなく、フォームの元の色とブレンドされてしまう・・・orz (当り前かw)

procedure TForm1.Button1Click(Sender: TObject);
var
  BF  :TBlendFunction;
  bmp :TBitmap;
begin
  BorderStyle := bsNone;
  Color := clWhite;
  TransparentColorValue := clWhite;
  TransparentColor := True;

  bmp :=TBitmap.Create;
   try
    bmp.LoadFromFile('test.bmp');
    bmp.PixelFormat := pf32bit;

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

    Windows.AlphaBlend(Canvas.Handle, 10, 10, bmp.Width, bmp.Height,
                       bmp.Canvas.Handle, 0, 0, bmp.Width, bmp.Height,
                       BF);
  finally
    bmp.Free;
  end;
end;

ソースはテスト用の物(コピペ)なので汚くてすいません。

と、いろいろ事項錯誤してみましたが、結局解決できず・・・
分かる方や参考になりそうなサイトを知っている方は教えてください。
よろしくお願いします。
WinXP + Delphi 2010 です。


monaa  2009-10-11 13:45:54  No: 35861

Windowsにそういった関数が無いのでゴリゴリやるしかないと思います。
それぞれコントロールの領域を取得して、
背景用のBitmapにその領域を不透明として描画すれば行けるのでは?


boon  2009-10-12 08:50:40  No: 35862

いろいろ考えたんですが、処理が複雑になりすぎるので、
アルファなビットマップを表示するフォームとオブジェクトだけのフォームを2枚透明にして重ね、同時に処理する事で思い通りの動作は出来ましたが、処理の仕方がイマイチ気に入りませんね。
もっといい処理の仕方ないですかねぇ。
とりあえず自己解決って事で。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加