📄 gif_unit.pas
字号:
unit Gif_Unit;
interface
uses Windows, Classes, Forms, Graphics, Controls, Consts, Dialogs, Variants;
const
MaxExtStrID = 61300;
PaletteMask = $02000000;
SGIFImage = MaxExtStrID - 200;
SNotImplemented = MaxExtStrID - 43;
SNoGIFData = MaxExtStrID - 202;
SWrongGIFColors = MaxExtStrID - 204;
SBadGIFCodeSize = MaxExtStrID - 205;
SGIFDecodeError = MaxExtStrID - 206;
SGIFEncodeError = MaxExtStrID - 207;
SUnrecognizedGIFExt = MaxExtStrID - 203;
SChangeGIFSize = MaxExtStrID - 201;
SGIFVersion = MaxExtStrID - 208;
type
TFillDirection = (fdTopToBottom, fdBottomToTop, fdLeftToRight, fdRightToLeft);
TParentControl = class(TWinControl);
function ResStr(const Ident: string): string;
function AllocMemo(Size: Longint): Pointer;
function HugeOffset(HugePtr: Pointer; Amount: Longint): Pointer;
function WidthOf(R: TRect): Integer;
function HeightOf(R: TRect): Integer;
function Max(A, B: Longint): Longint;
function Min(A, B: Longint): Longint;
function PaletteEntries(Palette: HPALETTE): Integer;
function PaletteColor(Color: TColor): Longint;
function CreateRealSizeIcon(Icon: TIcon): HIcon;
procedure GetIconSize(Icon: HIcon; var W, H: Integer);
procedure TwoBitsFromDIB(var BI: TBitmapInfoHeader; var XorBits, AndBits: HBITMAP);
procedure HMemCpy(DstPtr, SrcPtr: Pointer; Amount: Longint);
procedure FreeMemo(var fpBlock: Pointer);
procedure NotImplemented;
procedure ReadIcon(Stream: TStream; var Icon: HICON; ImageCount: Integer;
StartOffset: Integer);
procedure DrawRealSizeIcon(Canvas: TCanvas; Icon: TIcon; X, Y: Integer);
procedure StretchBltTransparent(DstDC: HDC; DstX, DstY, DstW, DstH: Integer;
SrcDC: HDC; SrcX, SrcY, SrcW, SrcH: Integer; Palette: HPalette;
TransparentColor: TColorRef);
procedure StretchBitmapRectTransparent(Dest: TCanvas; DstX, DstY,
DstW, DstH: Integer; SrcRect: TRect; Bitmap: TBitmap;
TransparentColor: TColor);
procedure StretchBitmapTransparent(Dest: TCanvas; Bitmap: TBitmap;
TransparentColor: TColor; DstX, DstY, DstW, DstH, SrcX, SrcY,
SrcW, SrcH: Integer);
procedure GradientFillRect(Canvas: TCanvas; ARect: TRect; StartColor,
EndColor: TColor; Direction: TFillDirection; Colors: Byte);
function MaxFloat(const Values: array of Extended): Extended;
procedure CopyParentImage(Control: TControl; Dest: TCanvas);
implementation
Uses SysUtils, Messages;
function ResStr(const Ident: string): string;
begin
Result := Ident;
end;
function AllocMemo(Size: Longint): Pointer;
begin
if Size > 0 then
Result := GlobalAllocPtr(HeapAllocFlags or GMEM_ZEROINIT, Size)
else Result := nil;
end;
function HugeOffset(HugePtr: Pointer; Amount: Longint): Pointer;
begin
Result := PChar(HugePtr) + Amount;
end;
procedure HMemCpy(DstPtr, SrcPtr: Pointer; Amount: Longint);
begin
Move(SrcPtr^, DstPtr^, Amount);
end;
procedure FreeMemo(var fpBlock: Pointer);
begin
if fpBlock <> nil then begin
GlobalFreePtr(fpBlock);
fpBlock := nil;
end;
end;
procedure NotImplemented;
begin
Screen.Cursor := crDefault;
MessageDlg(LoadStr(SNotImplemented), mtInformation, [mbOk], 0);
Abort;
end;
function MaxFloat(const Values: array of Extended): Extended;
var
I: Cardinal;
begin
Result := Values[0];
for I := 0 to High(Values) do
if Values[I] > Result then Result := Values[I];
end;
function WidthOf(R: TRect): Integer;
begin
Result := R.Right - R.Left;
end;
function HeightOf(R: TRect): Integer;
begin
Result := R.Bottom - R.Top;
end;
function Max(A, B: Longint): Longint;
begin
if A > B then Result := A
else Result := B;
end;
function Min(A, B: Longint): Longint;
begin
if A < B then Result := A
else Result := B;
end;
function PaletteEntries(Palette: HPALETTE): Integer;
begin
GetObject(Palette, SizeOf(Integer), @Result);
end;
function PaletteColor(Color: TColor): Longint;
begin
Result := ColorToRGB(Color) or PaletteMask;
end;
procedure OutOfResources; near;
begin
raise EOutOfResources.Create(ResStr(SOutOfResources));
end;
function WidthBytes(I: Longint): Longint;
begin
Result := ((I + 31) div 32) * 4;
end;
function GetDInColors(BitCount: Word): Integer;
begin
case BitCount of
1, 4, 8: Result := 1 shl BitCount;
else Result := 0;
end;
end;
function DupBits(Src: HBITMAP; Size: TPoint; Mono: Boolean): HBITMAP;
var
DC, Mem1, Mem2: HDC;
Old1, Old2: HBITMAP;
Bitmap: Windows.TBitmap;
begin
Mem1 := CreateCompatibleDC(0);
Mem2 := CreateCompatibleDC(0);
GetObject(Src, SizeOf(Bitmap), @Bitmap);
if Mono then
Result := CreateBitmap(Size.X, Size.Y, 1, 1, nil)
else begin
DC := GetDC(0);
if DC = 0 then OutOfResources;
try
Result := CreateCompatibleBitmap(DC, Size.X, Size.Y);
if Result = 0 then OutOfResources;
finally
ReleaseDC(0, DC);
end;
end;
if Result <> 0 then begin
Old1 := SelectObject(Mem1, Src);
Old2 := SelectObject(Mem2, Result);
StretchBlt(Mem2, 0, 0, Size.X, Size.Y, Mem1, 0, 0, Bitmap.bmWidth,
Bitmap.bmHeight, SrcCopy);
if Old1 <> 0 then SelectObject(Mem1, Old1);
if Old2 <> 0 then SelectObject(Mem2, Old2);
end;
DeleteDC(Mem1);
DeleteDC(Mem2);
end;
procedure TwoBitsFromDIB(var BI: TBitmapInfoHeader; var XorBits, AndBits: HBITMAP);
type
PLongArray = ^TLongArray;
TLongArray = array[0..1] of Longint;
var
Temp: HBITMAP;
NumColors: Integer;
DC: HDC;
Bits: Pointer;
Colors: PLongArray;
IconSize: TPoint;
BM: Windows.TBitmap;
begin
IconSize.X := GetSystemMetrics(SM_CXICON);
IconSize.Y := GetSystemMetrics(SM_CYICON);
with BI do begin
biHeight := biHeight shr 1; { Size in record is doubled }
biSizeImage := WidthBytes(Longint(biWidth) * biBitCount) * biHeight;
NumColors := GetDInColors(biBitCount);
end;
DC := GetDC(0);
if DC = 0 then OutOfResources;
try
Bits := Pointer(Longint(@BI) + SizeOf(BI) + NumColors * SizeOf(TRGBQuad));
Temp := CreateDIBitmap(DC, BI, CBM_INIT, Bits, PBitmapInfo(@BI)^, DIB_RGB_COLORS);
if Temp = 0 then OutOfResources;
try
GetObject(Temp, SizeOf(BM), @BM);
IconSize.X := BM.bmWidth;
IconSize.Y := BM.bmHeight;
XorBits := DupBits(Temp, IconSize, False);
finally
DeleteObject(Temp);
end;
with BI do begin
Inc(Longint(Bits), biSizeImage);
biBitCount := 1;
biSizeImage := WidthBytes(Longint(biWidth) * biBitCount) * biHeight;
biClrUsed := 2;
biClrImportant := 2;
end;
Colors := Pointer(Longint(@BI) + SizeOf(BI));
Colors^[0] := 0;
Colors^[1] := $FFFFFF;
Temp := CreateDIBitmap(DC, BI, CBM_INIT, Bits, PBitmapInfo(@BI)^, DIB_RGB_COLORS);
if Temp = 0 then OutOfResources;
try
AndBits := DupBits(Temp, IconSize, True);
finally
DeleteObject(Temp);
end;
finally
ReleaseDC(0, DC);
end;
end;
procedure ReadIcon(Stream: TStream; var Icon: HICON; ImageCount: Integer;
StartOffset: Integer);
type
PIconRecArray = ^TIconRecArray;
TIconRecArray = array[0..300] of TIconRec;
var
List: PIconRecArray;
HeaderLen, Length: Integer;
Colors, BitsPerPixel: Word;
C1, C2, N, Index: Integer;
IconSize: TPoint;
DC: HDC;
BI: PBitmapInfoHeader;
ResData: Pointer;
XorBits, AndBits: HBITMAP;
XorInfo, AndInfo: Windows.TBitmap;
XorMem, AndMem: Pointer;
XorLen, AndLen: Integer;
begin
HeaderLen := SizeOf(TIconRec) * ImageCount;
List := AllocMem(HeaderLen);
try
Stream.Read(List^, HeaderLen);
IconSize.X := GetSystemMetrics(SM_CXICON);
IconSize.Y := GetSystemMetrics(SM_CYICON);
DC := GetDC(0);
if DC = 0 then OutOfResources;
try
BitsPerPixel := GetDeviceCaps(DC, PLANES) * GetDeviceCaps(DC, BITSPIXEL);
if BitsPerPixel = 24 then Colors := 0
else Colors := 1 shl BitsPerPixel;
finally
ReleaseDC(0, DC);
end;
Index := -1;
{ the following code determines which image most closely matches the
current device. It is not meant to absolutely match Windows
(known broken) algorithm }
C2 := 0;
for N := 0 to ImageCount - 1 do begin
C1 := List^[N].Colors;
if C1 = Colors then begin
Index := N;
Break;
end
else if Index = -1 then begin
if C1 <= Colors then begin
Index := N;
C2 := List^[N].Colors;
end;
end
else if C1 > C2 then Index := N;
end;
if Index = -1 then Index := 0;
with List^[Index] do begin
BI := AllocMem(DIBSize);
try
Stream.Seek(DIBOffset - (HeaderLen + StartOffset), 1);
Stream.Read(BI^, DIBSize);
TwoBitsFromDIB(BI^, XorBits, AndBits);
GetObject(AndBits, SizeOf(Windows.TBitmap), @AndInfo);
GetObject(XorBits, SizeOf(Windows.TBitmap), @XorInfo);
IconSize.X := AndInfo.bmWidth;
IconSize.Y := AndInfo.bmHeight;
with AndInfo do
AndLen := bmWidthBytes * bmHeight * bmPlanes;
with XorInfo do
XorLen := bmWidthBytes * bmHeight * bmPlanes;
Length := AndLen + XorLen;
ResData := AllocMem(Length);
try
AndMem := ResData;
with AndInfo do
XorMem := Pointer(Longint(ResData) + AndLen);
GetBitmapBits(AndBits, AndLen, AndMem);
GetBitmapBits(XorBits, XorLen, XorMem);
DeleteObject(XorBits);
DeleteObject(AndBits);
Icon := CreateIcon(HInstance, IconSize.X, IconSize.Y,
XorInfo.bmPlanes, XorInfo.bmBitsPixel, AndMem, XorMem);
if Icon = 0 then OutOfResources;
finally
FreeMem(ResData, Length);
end;
finally
FreeMem(BI, DIBSize);
end;
end;
finally
FreeMem(List, HeaderLen);
end;
end;
function CreateRealSizeIcon(Icon: TIcon): HIcon;
var
Mem: TMemoryStream;
CI: TCursorOrIcon;
begin
Result := 0;
Mem := TMemoryStream.Create;
try
Icon.SaveToStream(Mem);
Mem.Position := 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -