4

Vista が最初にリリースされた数年前に、これについて質問しましたが、問題を解決することはなく、後で検討するものとして棚上げしました。

見栄えを良くするために多大な努力を払ったスプラッシュスクリーンがあります。32bpp のアルファブレンド PNG です。デスクトップ構成がオフになっている場合、Windows XPまたはVista +でうまく機能するいくつかのコード(必要に応じて掘り下げることができます!)があります。しかし、Vista+ では透明部分がすべて黒くなり、見栄えがすべて崩れてしまいます。

だから、私の質問は次のとおりです。デスクトップ構成がアクティブ化されている場合とされていない場合の両方で機能する方法で、32bpp アルファブレンド PNG をスプラッシュ画面として表示できた人はいますか? 私は、必要に応じて、無料であろうとなかろうと、サードパーティのコンポーネントを使用することに反対していません。

理想的には、これは Delphi 7 で機能します。

更新: 非常にうまく機能する以下の回答に加えて、TMS TAdvSmoothSplashScreen コンポーネントも、多少複雑ではあるが、このタスクを非常にうまく処理することがわかりました。

4

2 に答える 2

6

ティム、「Windows クラシック」テーマを選択して、Vista/D2007 でこれを試してみました。

Delphi のアルファ ブレンド スプラッシュ スクリーン - パート 2 http://melander.dk/articles/alphasplash2/2/

私が見ることができる黒い背景はありません...それはまだ素晴らしいです.

于 2009-08-04T18:38:07.953 に答える
5

Bob S のリンク先の記事が正しい答えを示しています。その記事には実際に必要な追加情報がかなり含まれているため、これを使用して作成したフォーム/ユニットを次に示します (ここからGraphicEx ライブラリが必要になることに注意してください:

unit Splash2Form;

interface

    uses
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
    Dialogs, ExtCtrls, GraphicEx;

type
    TSplash2 = class(TForm)
    private
        { Private declarations }
    procedure PreMultiplyBitmap(Bitmap: TBitmap);
    public
        constructor Create(Owner: TComponent);override;
        { Public declarations }
        procedure CreateParams(var Params: TCreateParams);override;
    procedure Execute;
  end;

var
  Splash2: TSplash2;

implementation

{$R *.dfm}

{ TSplash2 }

constructor TSplash2.Create(Owner: TComponent);
begin
  inherited;
  Brush.Style := bsClear;
end;

procedure TSplash2.CreateParams(var Params: TCreateParams);
begin
    inherited;
end;

procedure TSplash2.Execute;
var exStyle: DWORD;
    BitmapPos: TPoint;
  BitmapSize: TSize;
  BlendFunction: TBlendFunction;
  PNG: TPNGGraphic;
  Stream: TResourceStream;
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);

  PNG := TPNGGraphic.Create;
  try

      Stream := TResourceStream.Create(HInstance, 'SPLASH', RT_RCDATA);
      try
          PNG.LoadFromStream(Stream);
    finally
        Stream.Free;
        end;

    PreMultiplyBitmap(PNG);

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

      BitmapPos := Point(0, 0);
    BitmapSize.cx := ClientWidth;
      BitmapSize.cy := ClientHeight;

      // Setup alpha blending parameters
    BlendFunction.BlendOp := AC_SRC_OVER;
      BlendFunction.BlendFlags := 0;
    BlendFunction.SourceConstantAlpha := 255;
      BlendFunction.AlphaFormat := AC_SRC_ALPHA;

    // ... and action!
      UpdateLayeredWindow(Handle, 0, nil, @BitmapSize, PNG.Canvas.Handle,
      @BitmapPos, 0, @BlendFunction, ULW_ALPHA);

      Show;

  finally
    PNG.Free;
  end;
end;

procedure TSplash2.PreMultiplyBitmap(Bitmap: TBitmap);
var
  Row, Col: integer;
  p: PRGBQuad;
  PreMult: array[byte, byte] of byte;
begin
  // precalculate all possible values of a*b
  for Row := 0 to 255 do
    for Col := Row to 255 do
    begin
      PreMult[Row, Col] := Row*Col div 255;
      if (Row <> Col) then
        PreMult[Col, Row] := PreMult[Row, Col]; // a*b = b*a
    end;

  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;

end.
于 2009-08-04T19:25:16.847 に答える