美しい無効な小さな血のアイコン

Delphiは、デフォルトで無効化されたアイコンが次のように見えることで長い間有名です。







そして、私は彼らが次のように見えることを望みます:







Delphiでは、無効なアイコンを独自のアイコンに置き換えて、画像の追加リストを指定できるという事実を利用しています。 しかし、そのようなアイコンを毎回描画して接続するのは退屈な作業です。 したがって、実行時にこの画像のリストを動的に作成します。



このような画像のリストは、特殊関数CreateSpecialImageList()で作成します。 引数として、元のアイコンのリストが必要になります。戻り値として必要なTImageListがすでにあります。 次に、次のコード行でフォームを作成するときに新しいアイコンを接続できます。



ActionManager.DisabledImages := CreateSpecialImageList(ImageList);
      
      







しかし、私たちはもっと深く行くべきだと思う...






関数の機能を拡張し、グレーの半透明のアイコンを作成する機能を追加するだけでなく、それらをより明るくまたはよりコントラストにすることもできます。 HotImagesプロパティのアイコンを作成するときにこれが必要になる場合があります。 したがって、いくつかの特別な状態のアイコンを作成するための汎用機能があります。



関数のソースコード:


 function CreateSpecialImageList(ASource: TCustomImageList; ABrightness, AContrast, AGrayscale, AAlpha: Single): TCustomImageList; type PBGRA = ^TBGRA; TBGRA = packed record B, G, R, A: Byte; end; TByteLUT = array [Byte] of Byte; function ByteRound(const Value: Single): Byte; inline; begin if Value < 0 then Result := 0 else if Value > 255 then Result := 255 else Result := Round(Value); end; procedure GetLinearLUT(var LUT: TByteLUT; X1, Y1, X2, Y2: Integer); var X, DX, DY: Integer; begin DX := X2 - X1; DY := Y2 - Y1; for X := 0 to 255 do LUT[X] := ByteRound((X - X1) * DY / DX + Y1); end; function GetBrightnessContrastLUT(var LUT: TByteLUT; const Brightness, Contrast: Single): Boolean; var B, C: Integer; X1, Y1, X2, Y2: Integer; begin X1 := 0; Y1 := 0; X2 := 255; Y2 := 255; B := Round(Brightness * 255); C := Round(Contrast * 127); if C >= 0 then begin Inc(X1, C); Dec(X2, C); Dec(X1, B); Dec(X2, B); end else begin Dec(Y1, C); Inc(Y2, C); Inc(Y1, B); Inc(Y2, B); end; GetLinearLUT(LUT, X1, Y1, X2, Y2); Result := (B <> 0) or (C <> 0); end; var LImageInfo: TImageInfo; LDibInfo: TDibSection; I, L: Integer; P: PBGRA; R, G, B, A: Byte; LUT: TByteLUT; LHasLUT: Boolean; begin Result := nil; if (ASource = nil) or (ASource.ColorDepth <> cd32bit) then Exit; Result := TImageList.Create(ASource.Owner); try Result.ColorDepth := cd32bit; Result.Assign(ASource); Result.Masked := False; FillChar(LImageInfo, SizeOf(LImageInfo), 0); ImageList_GetImageInfo(Result.Handle, 0, LImageInfo); FillChar(LDibInfo, SizeOf(LDibInfo), 0); GetObject(LImageInfo.hbmImage, SizeOf(LDibInfo), @LDibInfo); P := LDibInfo.dsBm.bmBits; LHasLUT := GetBrightnessContrastLUT(LUT, ABrightness, AContrast); for I := 0 to LDibInfo.dsBm.bmHeight * LDibInfo.dsBm.bmWidth - 1 do begin A := PA; R := MulDiv(PR, $FF, A); G := MulDiv(PG, $FF, A); B := MulDiv(PB, $FF, A); if LHasLUT then begin R := LUT[R]; G := LUT[G]; B := LUT[B]; end; if AGrayscale > 0 then begin L := (R * 61 + G * 174 + B * 21) shr 8; if AGrayscale >= 1 then begin R := L; G := L; B := L; end else begin R := ByteRound(R + (L - R) * AGrayscale); G := ByteRound(G + (L - G) * AGrayscale); B := ByteRound(B + (L - B) * AGrayscale); end; end; if AAlpha <> 1 then begin A := ByteRound(A * AAlpha); PA := A; end; PR := MulDiv(R, A, $FF); PG := MulDiv(G, A, $FF); PB := MulDiv(B, A, $FF); Inc(P); end; except FreeAndNil(Result); end; end;
      
      





関数の引数:






関数のソースコードは、ほとんどのドルピストにとって理解できると思いますが、いくつかの点を明確にする必要があると思います。



まず、TImageListのDIBイメージは、あらかじめフォーマットされた形式で格納されています。各ピクセルについて、一連のMulDiv()呼び出しによって元のカラーチャネル値を取得する操作を実行し、操作を実行してから元のピクセル形式を返します。



明るさとコントラストの変更は、LUT(ルックアップテーブル)-ルックアップテーブルを使用して実行されます。 2点の線形関数に基づいてテーブルを作成します。 明るさとコントラストのパラメータは、直接補正の開始点を目的の方向に単純にシフトします。 すべてのカラーチャンネルで同じ補正を実行するため、1つのLUTのみを使用します。



ピクセルのグレースケールの変更は、元の値から色の明るさの合計値までのオフセットを計算するだけで行われます。 引数AGrayscaleの値が大きいほど、新しい値は全体の明るさの値に近くなります。これにより、すべてのカラーチャンネルでグレーの近似値が得られます。



関数の使用


関数を使用するには、ソースコードをプロジェクトにコピーするだけです。 機能コードは自己完結型であり、サードパーティのコンポーネントまたはモジュールを必要としません。 便宜上、関数の引数を試すことができる小さなデモを作成しました。 デモのソースコードはこちらからダウンロードできます



元のアイコン






標準の無効状態の元のアイコン






コントラストのあるアイコンが10%増加しました






無効状態のアイコンは完全に灰色で、透明度は50%低下します






ここで与えられた機能があなたのデザインであなたに役立つことを願っています。 素敵なコーディングを!



UPD :このメソッドは、ColorDepth = cd32bitモードの画像リストでのみ機能します。



UPD2 ::コンパイルされたデモプロジェクトを開始すると、アイコンの周りに「黒い」背景が表示される場合があります。 プロジェクトの新しいバージョンをダウンロードしてください。 この問題は、Delphi XE3からDelphi XEへのプロジェクトの不正な転送が原因で発生しました。



UPD3 :Windows 2000で32ビットの無効なアイコンを実行している場合、調光効果が得られます。 この問題を解決するには、OSを判別し、2000番目の休暇AAlpha = 1の場合、アイコンは灰色になります。



All Articles