MMDIBCv.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:45k
- {========================================================================}
- {= (c) 1995-98 SwiftSoft Ronald Dittrich =}
- {========================================================================}
- {= All Rights Reserved =}
- {========================================================================}
- {= D 01099 Dresden = Fax.: +49(0)351-8037944 =}
- {= Loewenstr.7a = info@swiftsoft.de =}
- {========================================================================}
- {= Actual versions on http://www.swiftsoft.de/index.html =}
- {========================================================================}
- {= This code is for reference purposes only and may not be copied or =}
- {= distributed in any format electronic or otherwise except one copy =}
- {= for backup purposes. =}
- {= =}
- {= No Delphi Component Kit or Component individually or in a collection=}
- {= subclassed or otherwise from the code in this unit, or associated =}
- {= .pas, .dfm, .dcu, .asm or .obj files may be sold or distributed =}
- {= without express permission from SwiftSoft. =}
- {= =}
- {= For more licence informations please refer to the associated =}
- {= HelpFile. =}
- {========================================================================}
- {= $Date: 11.11.98 - 16:02:52 $ =}
- {========================================================================}
- unit MMDIBCv;
- {$I COMPILER.INC}
- {$IFNDEF WIN32}
- {$DEFINE USEWING}
- {$ENDIF}
- interface
- uses
- {$IFDEF WIN32}
- Windows,
- {$ELSE}
- WinTypes,
- WinProcs,
- {$ENDIF}
- Classes,
- Controls,
- Graphics,
- Dialogs,
- SysUtils,
- MMObj,
- MMUtils,
- MMDIB,
- CRightC
- {$IFDEF USEWING}
- ,MMWinG
- {$ENDIF};
- const
- { different DIB Orientations }
- DIB_TOPDOWN = -1;
- DIB_BOTTOMUP = 1;
- { DIB_TOPDOWN is the fastest, but many drivers can't work with }
- { this STANDARD format. For example the ATI driver causes a GPF }
- { in BitBlt. NEVER buy a ATI card, if you would have trouble do it!}
- DIB_ORIENT: integer = DIB_BOTTOMUP; { Bottom - Up DIB !! }
- type
- EMMDIBError = class(Exception);
- {-- TMMDIBCanvas ----------------------------------------------------}
- TMMDIBCanvas = class(TCanvas)
- private
- FOwner : TComponent;
- FHDIBDC : THandle;
- FBits : integer;
- FHOrigBitmap : HBitmap;
- FHBitmap : HBitmap;
- FHBackGround : HBitmap;
- FPBitMapInfo : PBitMapInfo;
- FHPalette : HPalette;
- FPLogPalette : PLogPalette;
- FRealize : Boolean;
- FMapped : Boolean;
- FPSurface : Pointer;
- FPBackSurface: Pointer;
- FWidth : integer;
- FHeight : integer;
- FClipRect : TRect;
- FBackBitmap : TBitmap;
- FStretchBgnd : Boolean;
- FNeedUpdate : Boolean;
- FCanUpdate : Boolean;
- FAnimFirst : Integer;
- FAnimColors : TList;
- FAnimLock : Integer;
- FAnimValues : TList;
- FAnimCount : Integer;
- procedure SetBPP(aValue: integer);
- procedure SetWidth(aWidth: integer);
- procedure SetHeight(aHeight: integer);
- procedure SetBackBitmap(aBitmap: TBitmap);
- procedure SetRealize(Value: Boolean);
- procedure SetMapped(Value: Boolean);
- procedure SetStretchBgnd(Value: Boolean);
- procedure BackGroundChanged(Sender: TObject);
- procedure CheckDIB;
- procedure CreateDIB;
- procedure DestroyDIB;
- procedure RecreateDIB;
- function GetAnimCount: Integer;
- procedure SetAnimCount(Value: Integer);
- function GetAnimColor(Index: Integer): TColor;
- function GetAnimColorValue(Index: Integer): TColor;
- procedure SetAnimColorValue(Index: Integer; Value: TColor);
- function GetAnimColorIndex(Index: Integer): Integer;
- procedure FreeColors;
- protected
- procedure CreateHandle; override;
- public
- constructor Create(aOwner: TComponent); virtual;
- destructor Destroy; override;
- procedure SetBounds(aLeft, aTop, aWidth, aHeight: Integer); virtual;
- procedure SetLogPalette(pLogPal: PLogPalette);
- procedure DIB_Init;
- procedure DIB_InitDrawing;
- procedure DIB_DoneDrawing;
- procedure DIB_SetTColor(Color: TColor);
- procedure DIB_SetColorRef(ColorRef: Longint);
- function DIB_ColorToIndex(Color: TColor): Longint;
- procedure DIB_SetColor(Index: Longint);
- procedure DIB_SetClipRect(R: TRect);
- function DIB_GetClipRect: TRect;
- function DIB_GetPixelAddress(aSurface: Pointer; X, Y: integer): Pointer;
- procedure DIB_SetPixel(X, Y: integer; Color: Longint);{$IFDEF WIN32}pascal;{$ENDIF}
- function DIB_GetPixel(X, Y: integer): Longint;{$IFDEF WIN32}pascal;{$ENDIF}
- procedure DIB_Line(X1, Y1, X2, Y2: integer);{$IFDEF WIN32}pascal;{$ENDIF}
- procedure DIB_LineNotXor(X1, Y1, X2, Y2: integer);{$IFDEF WIN32}pascal;{$ENDIF}
- procedure DIB_MoveTo(X,Y: integer);{$IFDEF WIN32}pascal;{$ENDIF}
- procedure DIB_LineTo(X,Y: integer);{$IFDEF WIN32}pascal;{$ENDIF}
- procedure DIB_HLine(X1, X2, Y: integer);{$IFDEF WIN32}pascal;{$ENDIF}
- procedure DIB_HLineDashed(X1, X2, Y: integer);{$IFDEF WIN32}pascal;{$ENDIF}
- procedure DIB_HLineDoted(X1, X2, Y, Steps: integer);{$IFDEF WIN32}pascal;{$ENDIF}
- procedure DIB_VLine(X, Y1, Y2: integer);{$IFDEF WIN32}pascal;{$ENDIF}
- procedure DIB_VLineXor(X, Y1, Y2: integer);{$IFDEF WIN32}pascal;{$ENDIF}
- procedure DIB_VLineNotXor(X, Y1, Y2: integer);{$IFDEF WIN32}pascal;{$ENDIF}
- procedure DIB_VLineDashed(X, Y1, Y2: integer);{$IFDEF WIN32}pascal;{$ENDIF}
- procedure DIB_VLineDoted(X, Y1, Y2, Steps: integer);{$IFDEF WIN32}pascal;{$ENDIF}
- procedure DIB_VLineMultiColor(X, Y: integer; Colors: PByte; Cnt: integer);{$IFDEF WIN32}pascal;{$ENDIF}
- procedure DIB_Rectangle(X1, Y1, X2, Y2: integer);{$IFDEF WIN32}pascal;{$ENDIF}
- procedure DIB_FillRect(Rect: TRect);{$IFDEF WIN32}pascal;{$ENDIF}
- procedure DIB_FillRectXor(Rect: TRect);{$IFDEF WIN32}pascal;{$ENDIF}
- procedure DIB_FillRectDoted(Rect: TRect; Doted: Boolean);{$IFDEF WIN32}pascal;{$ENDIF}
- procedure DIB_Ellipse(X, Y: integer; StAngle, EndAngle, XRadius, YRadius: Word);{$IFDEF WIN32}pascal;{$ENDIF}
- procedure DIB_FillEllipse(X, Y: integer; XRadius, YRadius: Word);{$IFDEF WIN32}pascal;{$ENDIF}
- procedure DIB_Clear;{$IFDEF WIN32}pascal;{$ENDIF}
- procedure DIB_CopyDIBBits(Source:Pointer;XDst,YDst,Width,Height,XSrc,YSrc: integer);{$IFDEF WIN32}pascal;{$ENDIF}
- procedure DIB_BitBlt(DestDC: THandle; Dest: TRect; X, Y: integer);
- procedure DIB_StretchBlt(DestDC: THandle; Dest: TRect; Src: TRect);
- procedure BeginAnimate;
- procedure EndAnimate;
- property Surface: Pointer read FPSurface;
- property BackSurface: Pointer read FPBackSurface;
- property BitmapInfo: PBitmapInfo read FPBitmapInfo;
- property Bitmap: HBitmap read FHBitmap;
- property Palette: HPalette read FHPalette;
- property AnimatedColorCount: Integer read GetAnimCount write SetAnimCount;
- property AnimatedColor[i: Integer]: TColor read GetAnimColor;
- property AnimatedColorValue[i: Integer]: TColor read GetAnimColorValue write SetAnimColorValue;
- property AnimatedColorIndex[i: Integer]: Integer read GetAnimColorIndex ;
- published
- property BitsPerPixel: integer read FBits write SetBPP stored True;
- property PaletteRealize: Boolean read FRealize write SetRealize default False;
- property PaletteMapped: Boolean read FMapped write SetMapped default False;
- property BackGroundBitmap: TBitmap read FBackBitmap write SetBackBitmap;
- property StretchBackGround: Boolean read FStretchBgnd write SetStretchBgnd default True;
- property Width: integer read FWidth write SetWidth default 1;
- property Height: integer read FHeight write SetHeight default 1;
- end;
- TMMDIBDrawProc = procedure(Clear: Boolean) of object;
- {-- TMMDIBGraphicControl --------------------------------------------------}
- TMMDIBGraphicControl = class(TMMGraphicControl)
- private
- FTag2 : integer;
- FDIBCanvas : TMMDIBCanvas;
- FBackGround: TBitmap;
- FUseBackDIB: Boolean;
- FTempUseDIB: Boolean;
- function GetBPP: integer;
- procedure SetRealize(aValue: Boolean);
- function GetRealize: Boolean;
- procedure SetMapped(aValue: Boolean);
- function GetMapped: Boolean;
- procedure BackGroundChanged(Sender: TObject);
- procedure SetBackGround(aBitmap: TBitmap);
- procedure SetUseBackDIB(aValue: Boolean);
- protected
- procedure FastDraw(DrawProc: TMMDIBDrawProc; Clear: Boolean);
- procedure SetBPP(aValue: integer); virtual;
- procedure Loaded; override;
- function GetPalette: HPALETTE; override;
- property UseBackGroundDIB: Boolean read FUseBackDIB write SetUseBackDIB default False;
- property BackGroundDIB: TBitmap read FBackGround write SetBackGround;
- property PaletteRealize: Boolean read GetRealize write SetRealize default False;
- property PaletteMapped: Boolean read GetMapped write SetMapped default False;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- procedure SetBounds(aLeft, aTop, aWidth, aHeight: integer); override;
- procedure DrawBackGround; virtual;
- property DIBCanvas: TMMDIBCanvas read FDIBCanvas write FDIBCanvas;
- property BitsPerPixel: integer read GetBPP write SetBPP default 8;
- published
- property Tag2: integer read FTag2 write FTag2;
- end;
- {------------------------------------------------------------------------}
- { !!! DO NOT TOUCH !!! THIS IS INTERNAL, BUT MUST BE GLOBAL !!! }
- {------------------------------------------------------------------------}
- var
- DataSection: TRtlCriticalSection;
- { filled by DIB_InitDrawing and used by the asm stuff }
- biBits: Longint; { DIB Bits per Pixel }
- biBPP: Longint; { DIB Bytes per Pixel }
- biWidth: Longint; { DIB Width }
- biHeight: Longint; { DIB Height }
- biScanWidth: Longint; { Real Width for one scanLine }
- biLineDiff: Longint; { Real differenz to next line }
- biColor: Longint; { temp. color value }
- biSurface: Pointer; { pointer to bitmap data }
- biPenPos: TPoint; { internal pen position }
- biClipRect: TRect; { clipping rectangle }
- implementation
- {$IFDEF WIN32}{$L MMDIB32.OBJ}{$ELSE}{$L MMDIB16.OBJ}{$ENDIF}
- {$F+}
- procedure TMMDIBCanvas.DIB_Init; external;
- procedure TMMDIBCanvas.DIB_SetPixel(X, Y: integer; Color: Longint); external;
- function TMMDIBCanvas.DIB_GetPixel(X, Y: integer): Longint; external;
- procedure TMMDIBCanvas.DIB_Line(X1, Y1, X2, Y2: integer); external;
- procedure TMMDIBCanvas.DIB_LineNotXor(X1, Y1, X2, Y2: integer); external;
- procedure TMMDIBCanvas.DIB_MoveTo(X, Y: integer); external;
- procedure TMMDIBCanvas.DIB_LineTo(X, Y: integer); external;
- procedure TMMDIBCanvas.DIB_HLine(X1, X2, Y: integer); external;
- procedure TMMDIBCanvas.DIB_HLineDashed(X1, X2, Y: integer); external;
- procedure TMMDIBCanvas.DIB_HLineDoted(X1, X2, Y, Steps: integer); external;
- procedure TMMDIBCanvas.DIB_VLine(X, Y1, Y2: integer); external;
- procedure TMMDIBCanvas.DIB_VLineXor(X, Y1, Y2: integer); external;
- procedure TMMDIBCanvas.DIB_VLineNotXor(X, Y1, Y2: integer); external;
- procedure TMMDIBCanvas.DIB_VLineDashed(X, Y1, Y2: integer); external;
- procedure TMMDIBCanvas.DIB_VLineDoted(X, Y1, Y2, Steps: integer); external;
- procedure TMMDIBCanvas.DIB_VLineMultiColor(X, Y: integer; Colors: PByte; Cnt: integer); external;
- procedure TMMDIBCanvas.DIB_Rectangle(X1, Y1, X2, Y2: integer); external;
- procedure TMMDIBCanvas.DIB_FillRect(Rect: TRect); external;
- procedure TMMDIBCanvas.DIB_FillRectXor(Rect: TRect); external;
- procedure TMMDIBCanvas.DIB_FillRectDoted(Rect: TRect; Doted: Boolean); external;
- procedure TMMDIBCanvas.DIB_Ellipse(X, Y: integer; StAngle, EndAngle, XRadius, YRadius: Word); external;
- procedure TMMDIBCanvas.DIB_FillEllipse(X, Y: integer; XRadius, YRadius: Word);external;
- procedure TMMDIBCanvas.DIB_Clear; external;
- procedure TMMDIBCanvas.DIB_CopyDIBBits(Source:Pointer;XDst,YDst,Width,Height,XSrc,YSrc: integer); external;
- {$F-}
- {-- TMMDIBCanvas --------------------------------------------------------}
- constructor TMMDIBCanvas.Create(aOwner: TComponent);
- begin
- inherited Create;
- FOwner := aOwner;
- {$IFDEF USEWING}
- if (NOT WinGDLLLoaded) then
- {$IFDEF WIN32}
- raise EMMDIBError.Create(LoadResStr(IDS_DLLERROR)+' WING32.DLL');
- {$ELSE}
- raise EMMDIBError.Create(LoadResStr(IDS_DLLERROR)+' WING.DLL');
- {$ENDIF}
- {$ENDIF}
- DIB_Init;
- FBits := 8;
- FHDIBDC := 0;
- FHBitmap := 0;
- FHOrigBitmap := 0;
- FHPalette := 0;
- FPSurface := NIL;
- FPBitmapInfo := NIL;
- FPLogPalette := Nil;
- FRealize := False;
- FMapped := False;
- FCanUpdate := True;
- FStretchBgnd := True;
- FPBackSurface := NIL;
- FHBackGround := 0;
- FBackBitmap := TBitmap.Create;
- FBackBitmap.OnChange := BackGroundChanged;
- FWidth := 1;
- FHeight := 1;
- CreateHandle;
- end;
- {-- TMMDIBCanvas --------------------------------------------------------}
- Destructor TMMDIBCanvas.Destroy;
- begin
- DestroyDIB;
- FBackBitmap.Free;
- Handle := 0;
- DeleteDC(FHDIBDC);
- FHDIBDC := 0;
- if (FPLogPalette <> nil) then GlobalFreeMem(Pointer(FPLogPalette));
- FreeColors;
- FAnimValues.Free;
- inherited Destroy;
- end;
- {-- TMMDIBCanvas --------------------------------------------------------}
- procedure TMMDIBCanvas.CheckDIB;
- begin
- if FNeedUpdate then RecreateDIB;
- end;
- {-- TMMDIBCanvas --------------------------------------------------------}
- procedure TMMDIBCanvas.CreateHandle;
- begin
- if (FHDIBDC = 0) then
- begin
- {$IFDEF USEWING}
- FHDIBDC := WinGCreateDC;
- if (FHDIBDC = 0) then
- raise EMMDIBError.Create('Unable to access WinG device context');
- {$ELSE}
- FHDIBDC := CreateCompatibleDC(0);
- if (FHDIBDC = 0) then
- raise EMMDIBError.Create('Unable to access DIB device context');
- {$ENDIF}
- FNeedUpdate := True;
- end;
- CheckDIB;
- end;
- {-- TMMDIBCanvas --------------------------------------------------------}
- procedure TMMDIBCanvas.SetWidth(aWidth: integer);
- begin
- SetBounds(0,0,aWidth,FHeight);
- end;
- {-- TMMDIBCanvas --------------------------------------------------------}
- procedure TMMDIBCanvas.SetHeight(aHeight: integer);
- begin
- SetBounds(0,0,FWidth,aHeight);
- end;
- {-- TMMDIBCanvas --------------------------------------------------------}
- procedure TMMDIBCanvas.SetBounds(aLeft, aTop, aWidth, aHeight: Integer);
- begin
- if (aWidth <> FWidth) or (aHeight <> FHeight) then
- begin
- FWidth := aWidth;
- FHeight := aHeight;
- FClipRect := Rect(0,0,FWidth,FHeight);
- Handle := 0;
- FNeedUpdate := True;
- end;
- end;
- {-- TMMDIBCanvas --------------------------------------------------------}
- procedure TMMDIBCanvas.SetBPP(aValue: integer);
- begin
- if (aValue <> FBits) then
- begin
- if (aValue <> 8) and (aValue <> 24) then
- raise EMMDIBError.Create('Bitlength not supported yet');
- FBits := aValue;
- RecreateDIB;
- end;
- end;
- {-- TMMDIBCanvas --------------------------------------------------------}
- procedure TMMDIBCanvas.SetBackBitmap(aBitmap: TBitmap);
- begin
- if (aBitmap <> FBackBitmap) then FBackBitmap.Assign(aBitmap);
- end;
- {-- TMMDIBCanvas --------------------------------------------------------}
- procedure TMMDIBCanvas.BackGroundChanged(Sender: TObject);
- begin
- RecreateDIB;
- end;
- {-- TMMDIBCanvas --------------------------------------------------------}
- procedure TMMDIBCanvas.SetStretchBgnd(Value: Boolean);
- begin
- if (Value <> FStretchBgnd) then
- begin
- FStretchBgnd := Value;
- if not FBackBitmap.Empty then RecreateDIB;
- end;
- end;
- {-- TMMDIBCanvas --------------------------------------------------------}
- procedure TMMDIBCanvas.SetLogPalette(pLogPal: PLogPalette);
- begin
- if (FPLogPalette <> nil) then
- begin
- GlobalFreeMem(Pointer(FPLogPalette));
- FPLogPalette := nil;
- end;
- if (pLogPal <> nil) then
- with pLogPal^ do
- if (palVersion >= $300) and (palNumEntries <= 256) then
- begin
- FPLogPalette := GlobalAllocMem(sizeOf(TLogPalette)+sizeOf(TPaletteEntry)*256);
- Move(pLogPal^,FPLogPalette^,sizeOf(TLogPalette)+sizeOf(TPaletteEntry)*palNumEntries);
- end;
- RecreateDIB;
- end;
- {-- TMMDIBCanvas --------------------------------------------------------}
- procedure TMMDIBCanvas.SetRealize(Value: Boolean);
- begin
- if (Value <> FRealize) then
- begin
- FRealize := Value;
- RecreateDIB;
- end;
- end;
- {-- TMMDIBCanvas --------------------------------------------------------}
- procedure TMMDIBCanvas.SetMapped(Value: Boolean);
- begin
- if (Value <> FMapped) then
- begin
- FMapped := Value;
- end;
- end;
- {------------------------------------------------------------------------}
- { It is possible, because number palette entries <= 256 }
- function FindUniqueColor(Pal: PLogPalette): TColorRef;
- var
- N : Integer;
- C : TColorRef;
- function Unique: Boolean;
- var
- i: Integer;
- begin
- Result := False;
- for i := 0 to N - 1 do
- with Pal^.palPalEntry[i] do
- if RGB(peRed,peGreen,peBlue) = C then
- Exit;
- Result := True;
- end;
- begin
- N := Pal^.palNumEntries;
- C := 0;
- while not Unique do Inc(C);
- Result := C;
- end;
- {------------------------------------------------------------------------}
- function ColorToPalEntry(C: TColorRef): TPaletteEntry;
- begin
- with Result do
- begin
- peRed := GetRValue(C);
- peGreen := GetGValue(C);
- peBlue := GetBValue(C);
- peFlags := PC_RESERVED;
- end;
- end;
- {-- TMMDIBCanvas --------------------------------------------------------}
- procedure TMMDIBCanvas.CreateDIB;
- Var
- LogPal: PLogPalette;
- {$IFDEF WIN32}
- BackBitImageSize: DWord;
- BackBitInfoSize: DWord;
- {$ELSE}
- BackBitImageSize: Longint;
- BackBitInfoSize: Longint;
- {$ENDIF}
- BackBitInfo: PBitmapInfo;
- BackBitImage: Pointer;
- i,j,H,W,aWidth,aHeight: integer;
- C: TColorRef;
- begin
- if (FHDIBDC = 0) then exit;
- LogPal := nil;
- BackBitInfo := nil;
- BackBitImage := nil;
- {$IFNDEF WIN32}
- FBits := 8;
- {$ENDIF}
- { create the bitmap header }
- FPBitmapInfo := PBitmapInfo(DIB_Create(FBits,DIB_ORIENT,FWidth,FHeight,False));
- with FPBitMapInfo^.bmiHeader do
- begin
- {$IFDEF USEWING}
- if WinGRecommendDIBFormat(FPBitMapInfo) then
- begin { make sure it's 8bpp and remember the orientation }
- biBitCount := FBits;
- biCompression := BI_RGB;
- end;
- {$ENDIF}
- biWidth := Max(FWidth,1);
- biHeight := Max(FHeight,1) * DIB_ORIENT;
- end;
- LogPal := CreateSystemColorPalette;
- try
- with LogPal^ do
- begin
- if (FBackBitmap <> nil) and (not FBackBitmap.Empty) then
- begin
- GetDIBSizes(FBackBitmap.Handle, BackBitInfoSize, BackBitImageSize);
- BackBitInfo:= GlobalAllocMem(BackBitInfoSize);
- BackBitImage:= GlobalAllocMem(BackBitImageSize);
- GetDIB(FBackBitmap.Handle, FBackBitmap.Palette, BackBitInfo^, BackBitImage^);
- i := 10;
- GetPaletteEntries(FBackBitmap.Palette, i, 235, palPalEntry[i]);
- end
- else if (FPLogPalette <> nil) then
- begin
- for i := 10 to 246 do
- with FPLogPalette^.palPalEntry[i] do
- begin
- palPalEntry[i].peRed := peRed;
- palPalEntry[i].peGreen := peGreen;
- palPalEntry[i].peBlue := peBlue;
- palPalEntry[i].peFlags := PC_NOCOLLAPSE;
- end;
- end;
- FreeColors;
- if FAnimCount <> 0 then
- begin
- FAnimColors := TList.Create;
- { For now let's alloc upper colors for animation }
- for i := 246 - FAnimCount + 1 to 246 do
- begin
- C := FindUniqueColor(LogPal);
- palPalEntry[i] := ColorToPalEntry(C);
- FAnimColors.Add(Pointer(LongInt(C)));
- end;
- FAnimFirst := 246 - FAnimCount + 1;
- end
- else FAnimFirst := 256;
- { copy from the palette to the DIB bitmap color table }
- for i := 0 to 255 do
- with FPBitmapInfo^.bmiColors[i], palPalEntry[i] do
- begin
- rgbRed := peRed;
- rgbGreen := peGreen;
- rgbBlue := peBlue;
- { Set the PC_NOCOLLAPSE flag for each of our colors so }
- { that GDI won't merge them together. Be careful not }
- { to set PC_NOCOLLAPSE for the sys color entries or }
- { we'll get multpile copies of these colors in the }
- { palette when we realize it. }
- if (i > 9) and (i < 246) and not (i >= FAnimFirst) then
- rgbReserved := PC_NOCOLLAPSE
- else
- rgbReserved := 0;
- end;
- { create the palette }
- FHPalette := CreatePalette(LogPal^);
- end;
- if (FBackBitmap <> NIL) and (not FBackBitmap.Empty) then
- begin
- {$IFDEF USEWING}
- FHBackGround := WinGCreateBitmap(FHDIBDC, FPBitMapInfo, @FPBackSurface);
- {$ELSE}
- FHBackGround := CreateDIBSection(FHDIBDC, FPBitMapInfo^, DIB_RGB_Colors,
- FPBackSurface, {$IFDEF DELPHI3}0{$ELSE}Nil{$ENDIF}, 0);
- {$ENDIF}
- FHOrigBitmap := SelectObject(FHDIBDC, FHBackGround);
- aWidth := BackBitInfo^.bmiHeader.biWidth;
- aHeight := BackBitInfo^.bmiHeader.biHeight;
- SetStretchBltMode(FHDIBDC, STRETCH_DELETESCANS);
- if FStretchBgnd then
- begin
- StretchDIBits(FHDIBDC,
- 0, 0,
- FWidth,
- FHeight,
- 0, 0,
- aWidth,
- aHeight,
- BackBitImage,
- BackBitInfo^,
- DIB_RGB_Colors,
- SRCCOPY);
- end
- else
- begin
- i := 0;
- H := FHeight;
- while H > 0 do
- begin
- j := 0;
- W := FWidth;
- while W > 0 do
- begin
- StretchDIBits(FHDIBDC,
- j*aWidth, i*aHeight,
- aWidth,aHeight,
- 0, 0,
- aWidth,
- aHeight,
- BackBitImage,
- BackBitInfo^,
- DIB_RGB_Colors,
- SRCCOPY);
- dec(W,aWidth);
- inc(j);
- end;
- dec(H,aHeight);
- inc(i);
- end;
- end;
- FHBackGround := SelectObject(FHDIBDC, FHOrigBitmap);
- end;
- finally
- GlobalFreeMem(Pointer(BackBitInfo));
- GlobalFreeMem(Pointer(BackBitImage));
- GlobalFreeMem(Pointer(LogPal));
- end;
- {$IFDEF USEWING}
- FHBitmap := WinGCreateBitmap(FHDIBDC, FPBitMapInfo, @FPSurface);
- {$ELSE}
- FHBitmap := CreateDIBSection(FHDIBDC, FPBitMapInfo^, DIB_RGB_Colors,
- FPSurface, {$IFDEF DELPHI3}0{$ELSE}nil{$ENDIF}, 0);
- {$ENDIF}
- FHOrigBitmap := SelectObject(FHDIBDC, FHBitmap);
- PatBlt(FHDIBDC, 0, 0, FWidth, FHeight, BLACKNESS);
- Handle := FHDIBDC;
- FNeedUpdate := False;
- end;
- {-- TMMDIBCanvas --------------------------------------------------------}
- procedure TMMDIBCanvas.DestroyDIB;
- begin
- if (FHBackGround <> 0) then
- begin
- DeleteObject(FHBackGround);
- FHBackGround := 0;
- FPBackSurface := NIL;
- end;
- if (FHBitmap <> 0) then
- begin
- SelectObject(FHDIBDC, FHOrigBitmap);
- DeleteObject(FHBitmap);
- FHBitmap := 0;
- FPSurface := NIL;
- end;
- if (FHPalette <> 0) then
- begin
- DeleteObject(FHPalette);
- FHPalette := 0;
- end;
- if (FPBitmapInfo <> nil) then
- GlobalFreeMem(Pointer(FPBitmapInfo));
- end;
- {-- TMMDIBCanvas --------------------------------------------------------}
- procedure TMMDIBCanvas.RecreateDIB;
- begin
- if not FCanUpdate then
- raise EMMDIBError.Create(FOwner.ClassName +': Attempt to create new DIB while initialized for drawing');
- DestroyDIB;
- CreateDIB;
- end;
- {-- TMMDIBCanvas --------------------------------------------------------}
- procedure TMMDIBCanvas.DIB_BitBlt(DestDC: THandle; Dest: TRect; X, Y: integer);
- Var
- oldPalette: HPalette;
- begin
- if (Handle <> 0) and (DestDC <> 0) then
- with Dest do
- begin
- if FRealize then
- begin
- oldPalette := SelectPalette(DestDC, FHPalette, not FMapped);
- RealizePalette(DestDC);
- {$IFDEF USEWING}
- WinGBitBlt(DestDC, Left, Top, Right, Bottom, FHDIBDC, X, Y);
- {$ELSE}
- BitBlt(DestDC, Left, Top, Right, Bottom, FHDIBDC, X, Y, SRCCOPY);
- {$ENDIF}
- SelectPalette(DestDC, OldPalette, not FMapped);
- RealizePalette(DestDC);
- end
- else
- begin
- {$IFDEF USEWING}
- WinGBitBlt(DestDC, Left, Top, Right, Bottom, FHDIBDC, X, Y);
- {$ELSE}
- BitBlt(DestDC, Left, Top, Right, Bottom, FHDIBDC, X, Y, SRCCOPY);
- {$ENDIF}
- end;
- {$IFDEF WIN32}
- GDIFlush;
- {$ENDIF}
- end;
- end;
- {-- TMMDIBCanvas --------------------------------------------------------}
- procedure TMMDIBCanvas.DIB_StretchBlt(DestDC: THandle; Dest: TRect; Src: TRect);
- Var
- oldPalette: HPalette;
- begin
- if (Handle <> 0) and (DestDC <> 0) then
- with Dest do
- begin
- if FRealize then
- begin
- oldPalette := SelectPalette(DestDC, FHPalette, not FMapped);
- RealizePalette(DestDC);
- {$IFDEF USEWING}
- WinGStretchBlt(DestDC, Left, Top, Right, Bottom,
- FHDIBDC, Src.Left, Src.Top, Src.Right, Src.Bottom);
- {$ELSE}
- StretchBlt(DestDC, Left, Top, Right, Bottom,
- FHDIBDC, Src.Left, Src.Top, Src.Right, Src.Bottom, SRCCOPY);
- {$ENDIF}
- SelectPalette(DestDC, OldPalette, not FMapped);
- RealizePalette(DestDC);
- end
- else
- begin
- {$IFDEF USEWING}
- WinGStretchBlt(DestDC, Left, Top, Right, Bottom,
- FHDIBDC, Src.Left, Src.Top, Src.Right, Src.Bottom);
- {$ELSE}
- StretchBlt(DestDC, Left, Top, Right, Bottom,
- FHDIBDC, Src.Left, Src.Top, Src.Right, Src.Bottom, SRCCOPY);
- {$ENDIF}
- end;
- {$IFDEF WIN32}
- GDIFlush;
- {$ENDIF}
- end;
- end;
- {-- TMMDIBCanvas --------------------------------------------------------}
- function TMMDIBCanvas.DIB_GetPixelAddress(aSurface: Pointer; X, Y: integer): Pointer;
- var
- biScanWidth,BPP: integer;
- begin
- { make sure it's in range and if not return nil }
- if (X >= FWidth) or (Y >= FHeight) then
- raise EMMDIBError.Create('Attempt to get out of range pixel address');
- BPP := FBits shr 3;
- { Calculate the scan line storage width }
- biScanWidth := (FWidth*BPP + 3) and not 3;
- if (DIB_ORIENT = DIB_TOPDOWN) then
- Result := PChar(aSurface) + (Y * biScanWidth) + (X*BPP)
- else
- Result := PChar(aSurface) + ((FHeight-1-Y) * biScanWidth) + (X*BPP);
- end;
- {-- TMMDIBCanvas --------------------------------------------------------}
- function TMMDIBCanvas.DIB_ColorToIndex(Color: TColor): Longint;
- begin
- Result := ColorToRGB(Color);
- if FBits <= 8 then
- Result := GetNearestPaletteIndex(FHPalette, Result);
- end;
- {-- TMMDIBCanvas --------------------------------------------------------}
- procedure TMMDIBCanvas.DIB_SetClipRect(R: TRect);
- begin
- FClipRect.Left := Max(R.Left,0);
- FClipRect.Top := Max(R.Top,0);
- FClipRect.Right := Min(R.Right,FWidth);
- FClipRect.Bottom:= Min(R.Bottom,FHeight);
- biClipRect := FClipRect;
- end;
- {-- TMMDIBCanvas --------------------------------------------------------}
- function TMMDIBCanvas.DIB_GetClipRect: TRect;
- begin
- Result := FClipRect;
- end;
- {-- TMMDIBCanvas --------------------------------------------------------}
- procedure TMMDIBCanvas.DIB_SetTColor(Color: TColor);
- var
- Temp: Longint;
- begin
- Temp := ColorToRGB(Color);
- if FBits = 24 then
- begin
- biColor := Temp;
- end
- else
- begin
- Temp := GetNearestPaletteIndex(FHPalette, Temp);
- asm
- mov al, Temp.Byte[0]
- mov ah, al
- mov biColor.Word[0], ax
- mov biColor.Word[2], ax
- end;
- end;
- end;
- {-- TMMDIBCanvas --------------------------------------------------------}
- procedure TMMDIBCanvas.DIB_SetColorRef(ColorRef: Longint);
- var
- Temp: integer;
- begin
- if FBits = 24 then
- begin
- biColor := ColorRef;
- end
- else
- begin
- Temp := GetNearestPaletteIndex(FHPalette, ColorRef);
- asm
- mov al, Temp.Byte[0]
- mov ah, al
- mov biColor.Word[0], ax
- mov biColor.Word[2], ax
- end;
- end;
- end;
- {-- TMMDIBCanvas --------------------------------------------------------}
- procedure TMMDIBCanvas.DIB_SetColor(Index: Longint);
- begin
- if FBits = 24 then
- begin
- biColor := Index;
- end
- else
- begin
- asm
- {$IFDEF WIN32}
- mov dh, dl
- mov biColor.Word[0], dx
- mov biColor.Word[2], dx
- {$ELSE}
- mov al, byte ptr [Index]
- mov ah, al
- mov biColor.Word[0], ax
- mov biColor.Word[2], ax
- {$ENDIF}
- end;
- end;
- end;
- {-- TMMDIBCanvas --------------------------------------------------------}
- procedure TMMDIBCanvas.DIB_InitDrawing;
- begin
- EnterCriticalSection(DataSection);
- Changing;
- CheckDIB;
- biPenPos.X := 0;
- biPenPos.Y := 0;
- biBits := FBits;
- biBPP := FBits shr 3;
- biHeight := FHeight;
- biWidth := FWidth;
- biScanWidth := (FWidth*biBPP + 3) and not 3;
- biLineDiff := biScanWidth * -DIB_ORIENT;
- biSurface:= FPSurface;
- biClipRect := FClipRect;
- FCanUpdate := False;
- {$IFDEF WIN32}
- GDIFlush;
- {$ENDIF}
- end;
- {-- TMMDIBCanvas --------------------------------------------------------}
- procedure TMMDIBCanvas.DIB_DoneDrawing;
- begin
- biPenPos.X := 0;
- biPenPos.Y := 0;
- biHeight := 0;
- biWidth := 0;
- biScanWidth := 0;
- biSurface:= nil;
- FCanUpdate := True;
- Changed;
- LeaveCriticalSection(DataSection);
- end;
- const
- MaxAnimColors = 246 - 10;
- {-- TMMDIBCanvas --------------------------------------------------------}
- procedure TMMDIBCanvas.FreeColors;
- begin
- if FAnimColors <> nil then
- FAnimColors.Free;
- FAnimColors := nil;
- end;
- {-- TMMDIBCanvas --------------------------------------------------------}
- function TMMDIBCanvas.GetAnimCount: Integer;
- begin
- if FAnimColors <> nil then
- Result := FAnimColors.Count
- else
- Result := 0;
- end;
- {-- TMMDIBCanvas --------------------------------------------------------}
- procedure TMMDIBCanvas.SetAnimCount(Value: Integer);
- begin
- if (Value < 0) or (Value > MaxAnimColors) then
- { TODO: Should be res id }
- raise EMMDIBError.Create('Invalid count of animated colors');
- if Value <> AnimatedColorCount then
- begin
- FAnimCount := Value;
- RecreateDIB;
- end;
- end;
- {-- TMMDIBCanvas --------------------------------------------------------}
- function TMMDIBCanvas.GetAnimColor(Index: Integer): TColor ;
- begin
- if not InRange(Index,0,AnimatedColorCount-1) then
- { Should be res id }
- raise EMMDIBError.Create('Invalidate animated color index');
- Result := TColorRef(FAnimColors[Index]);
- end;
- {------------------------------------------------------------------------}
- function QuadToColor(Q: TRGBQuad): TColorRef;
- begin
- with Q do Result := RGB(rgbRed,rgbGreen,rgbBlue);
- end;
- {------------------------------------------------------------------------}
- function ColorToQuad(C: TColorRef): TRGBQuad;
- begin
- with Result do
- begin
- rgbRed := GetRValue(C);
- rgbGreen:= GetGValue(C);
- rgbBlue := GetBValue(C);
- end;
- end;
- {-- TMMDIBCanvas --------------------------------------------------------}
- function TMMDIBCanvas.GetAnimColorValue(Index: Integer): TColor;
- var
- Pal: array[0..255] of TRGBQuad;
- begin
- if not InRange(Index,0,AnimatedColorCount-1) then
- { Should be res id }
- raise EMMDIBError.Create('Invalidate animated color index');
- {$IFDEF WIN32}
- if GetDIBColorTable(Handle,0,256,Pal) <> 256 then
- {$ELSE}
- if WinGGetDIBColorTable(Handle,0,256,@Pal) <> 256 then
- {$ENDIF}
- { TODO: Should be res id }
- raise EMMDIBError.Create('Get palette entries failed');
- Result := QuadToColor(Pal[FAnimFirst+Index]);
- end;
- {-- TMMDIBCanvas --------------------------------------------------------}
- procedure TMMDIBCanvas.SetAnimColorValue(Index: Integer; Value: TColor);
- var
- Pal1: array[0..255] of TRGBQuad;
- Pal2: array[0..255] of TPaletteEntry;
- begin
- if not InRange(Index,0,AnimatedColorCount-1) then
- { Should be res id }
- raise EMMDIBError.Create('Invalidate animated color index');
- Value := ColorToRGB(Value);
- if FAnimLock > 0 then
- begin
- FAnimValues[Index] := Pointer(Value);
- Exit;
- end;
- {$IFDEF WIN32}
- if GetDIBColorTable(Handle,0,256,Pal1) <> 256 then
- {$ELSE}
- if WinGGetDIBColorTable(Handle,0,256,@Pal1) <> 256 then
- {$ENDIF}
- { TODO: Should be res id }
- raise EMMDIBError.Create('Get palette entries failed');
- if GetPaletteEntries(FHPalette,0,256,Pal2) <> 256 then
- { TODO: Should be res id }
- raise EMMDIBError.Create('Get palette entries failed');
- Pal1[FAnimFirst+Index] := ColorToQuad(Value);
- Pal2[FAnimFirst+Index] := ColorToPalEntry(Value);
- {$IFDEF WIN32}
- if SetDIBColorTable(Handle,0,256,Pal1) <> 256 then
- {$ELSE}
- if WinGSetDIBColorTable(Handle,0,256,@Pal1) <> 256 then
- {$ENDIF}
- { TODO: Should be res id }
- raise EMMDIBError.Create('Set palette entries failed');
- {$IFDEF WIN32}
- if not AnimatePalette(FHPalette,0,256,@Pal2[0]) then
- { TODO: Should be res id }
- raise EMMDIBError.Create('Animation of palette entries failed');
- {$ELSE}
- AnimatePalette(FHPalette,0,256,Pal2[0]);
- {$ENDIF}
- end;
- {-- TMMDIBCanvas --------------------------------------------------------}
- function TMMDIBCanvas.GetAnimColorIndex(Index: Integer): Integer;
- begin
- Result := FAnimFirst + Index;
- end;
- {-- TMMDIBCanvas --------------------------------------------------------}
- procedure TMMDIBCanvas.BeginAnimate;
- var
- Pal : array[0..255] of TRGBQuad;
- i : Integer;
- begin
- Inc(FAnimLock);
- if (FAnimLock = 1) and (AnimatedColorCount > 0) then
- begin
- {$IFDEF WIN32}
- if GetDIBColorTable(Handle,FAnimFirst,AnimatedColorCount,Pal) <> UINT(AnimatedColorCount) then
- {$ELSE}
- if WinGGetDIBColorTable(Handle,FAnimFirst,AnimatedColorCount,@Pal) <> AnimatedColorCount then
- {$ENDIF}
- { TODO: Should be res id }
- raise EMMDIBError.Create('Get palette entries failed');
- FAnimValues := TList.Create;
- for i := 0 to AnimatedColorCount - 1 do
- FAnimValues.Add(Pointer(QuadToColor(Pal[i])));
- end;
- end;
- {-- TMMDIBCanvas --------------------------------------------------------}
- procedure TMMDIBCanvas.EndAnimate;
- var
- Pal1: array[0..255] of TRGBQuad;
- Pal2: array[0..255] of TPaletteEntry;
- i : Integer;
- begin
- Dec(FAnimLock);
- if (FAnimLock = 0) and (AnimatedColorCount > 0) then
- begin
- for i := 0 to AnimatedColorCount - 1 do
- begin
- Pal1[i] := ColorToQuad(TColorRef(FAnimValues[i]));
- Pal2[i] := ColorToPalEntry(TColorRef(FAnimValues[i]));
- end;
- try
- {$IFDEF WIN32}
- if SetDIBColorTable(Handle,FAnimFirst,AnimatedColorCount,Pal1) <> UINT(AnimatedColorCount) then
- {$ELSE}
- if WinGSetDIBColorTable(Handle,FAnimFirst,AnimatedColorCount,@Pal1) <> AnimatedColorCount then
- {$ENDIF}
- { TODO: Should be res id }
- raise EMMDIBError.Create('Set palette entries failed');
- {$IFDEF WIN32}
- if not AnimatePalette(FHPalette,FAnimFirst,AnimatedColorCount,@Pal2[0]) then
- { TODO: Should be res id }
- raise EMMDIBError.Create('Animation of palette entries failed');
- {$ELSE}
- AnimatePalette(FHPalette,FAnimFirst,AnimatedColorCount,Pal2[0]);
- {$ENDIF}
- finally
- FAnimValues.Free;
- FAnimValues := nil;
- end;
- end;
- end;
- {== TMMDIBGraphicControl ================================================}
- constructor TMMDIBGraphicControl.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FDIBCanvas := TMMDIBCanvas.Create(Self);
- FUseBackDIB := False;
- PaletteRealize := False;
- PaletteMapped := False;
- FBackGround := TBitmap.Create;
- FBackGround.OnChange := BackGroundChanged;
- end;
- {-- TMMDIBGraphicControl ------------------------------------------------}
- destructor TMMDIBGraphicControl.Destroy;
- begin
- FBackGround.Free;
- FDIBCanvas.Free;
- inherited Destroy;
- end;
- {-- TMMDIBGraphicControl ------------------------------------------------}
- procedure TMMDIBGraphicControl.SetBPP(aValue: integer);
- begin
- FDIBCanvas.BitsPerPixel := aValue;
- Invalidate;
- end;
- {-- TMMDIBGraphicControl ------------------------------------------------}
- function TMMDIBGraphicControl.GetBPP: integer;
- begin
- Result := FDIBCanvas.BitsPerPixel;
- end;
- {-- TMMDIBGraphicControl ------------------------------------------------}
- procedure TMMDIBGraphicControl.SetBounds(aLeft, aTop, aWidth, aHeight: integer);
- begin
- inherited SetBounds(aLeft,aTop,aWidth,aHeight);
- FDIBCanvas.SetBounds(aLeft, aTop, aWidth, aHeight);
- end;
- {-- TMMDIBGraphicControl ------------------------------------------------}
- procedure TMMDIBGraphicControl.Loaded;
- begin
- inherited Loaded;
- UseBackgroundDIB := FTempUseDIB;
- end;
- {-- TMMDIBGraphicControl ------------------------------------------------}
- function TMMDIBGraphicControl.GetPalette: HPALETTE;
- begin
- if PaletteRealize then
- Result := FDIBCanvas.Palette
- else
- Result := inherited GetPalette;
- end;
- {-- TMMDIBGraphicControl ------------------------------------------------}
- procedure TMMDIBGraphicControl.SetRealize(aValue: Boolean);
- begin
- if (aValue <> FDIBCanvas.PaletteRealize) then
- begin
- FDIBCanvas.PaletteRealize := aValue;
- Invalidate;
- end;
- end;
- {-- TMMDIBGraphicControl ------------------------------------------------}
- function TMMDIBGraphicControl.GetRealize: Boolean;
- begin
- Result := FDIBCanvas.PaletteRealize;
- end;
- {-- TMMDIBGraphicControl ------------------------------------------------}
- procedure TMMDIBGraphicControl.SetMapped(aValue: Boolean);
- begin
- if (aValue <> FDIBCanvas.PaletteMapped) then
- begin
- FDIBCanvas.PaletteMapped := aValue;
- Invalidate;
- end;
- end;
- {-- TMMDIBGraphicControl ------------------------------------------------}
- function TMMDIBGraphicControl.GetMapped: Boolean;
- begin
- Result := FDIBCanvas.PaletteMapped;
- end;
- {-- TMMDIBGraphicControl ------------------------------------------------}
- procedure TMMDIBGraphicControl.SetBackGround(aBitmap: TBitmap);
- begin
- FBackGround.Assign(aBitmap);
- end;
- {-- TMMDIBGraphicControl ------------------------------------------------}
- procedure TMMDIBGraphicControl.BackGroundChanged(Sender: TObject);
- begin
- if not (csLoading in ComponentState) then
- begin
- if (csDesigning in ComponentState) then
- begin
- if (FBackGround.Empty) then
- begin
- PaletteRealize := False;
- PaletteMapped := False;
- FUseBackDIB := False;
- end
- else
- begin
- PaletteRealize := True;
- FUseBackDIB := True;
- end;
- end;
- if FUseBackDIB then
- FDIBCanvas.BackGroundBitmap := FBackGround
- else
- FDIBCanvas.BackGroundBitmap := NIL;
- Invalidate;
- end;
- end;
- {-- TMMDIBGraphicControl ------------------------------------------------}
- procedure TMMDIBGraphicControl.SetUseBackDIB(aValue: Boolean);
- begin
- if csLoading in ComponentState then
- begin
- FTempUseDIB := aValue;
- Exit;
- end;
- if (aValue <> FUseBackDIB) then
- begin
- if aValue And (NOT FBackGround.Empty) then
- FUseBackDIB := True
- else
- FUseBackDIB := False;
- if (not (csLoading in ComponentState)) then
- begin
- PaletteRealize := FUseBackDIB;
- if FUseBackDIB then FDIBCanvas.BackGroundBitmap := FBackGround
- else FDIBCanvas.BackGroundBitmap := NIL;
- end;
- Invalidate;
- end;
- end;
- {-- TMMDIBGraphicControl ------------------------------------------------}
- procedure TMMDIBGraphicControl.DrawBackGround;
- begin
- with FDIBCanvas do
- begin { copy background DIB }
- if (FPSurface <> NIL) AND (FPBackSurface <> NIL) then
- DIB_CopyDIBBits(FPBackSurface,0,0,FWidth,FHeight,0,0)
- else
- begin
- DIB_SetTColor(Color);
- DIB_Clear; { clear background }
- end;
- end;
- end;
- {-- TMMDIBGraphicControl ------------------------------------------------}
- procedure TMMDIBGraphicControl.FastDraw(DrawProc: TMMDIBDrawProc; Clear: Boolean);
- var
- DC: HDC;
- Control: TWinControl;
- begin
- {$IFDEF BUILD_ACTIVEX}
- Control := Self;
- {$ELSE}
- Control := Parent;
- {$ENDIF}
- if Visible and (Control <> nil) and Control.HandleAllocated then
- begin
- DC := GetDC(Control.Handle);
- try
- {$IFDEF DELPHI3}
- Canvas.Lock;
- {$ENDIF}
- {$IFNDEF BUILD_ACTIVEX}
- if RectVisible(DC, Rect(Left, Top, Left + Width, Top + Height)) then
- begin
- MoveWindowOrg(DC, Left, Top);
- IntersectClipRect(DC, 0, 0, Width, Height);
- {$ELSE}
- if RectVisible(DC, Rect(0, 0, Width, Height)) then
- begin
- {$ENDIF}
- Canvas.Handle := DC;
- DrawProc(Clear);
- end;
- finally
- Canvas.Handle := 0;
- ReleaseDC(Control.Handle, DC);
- {$IFDEF DELPHI3}
- Canvas.Unlock;
- {$ENDIF}
- end;
- end;
- end;
- initialization
- InitializeCriticalSection(DataSection);
- finalization
- DeleteCriticalSection(DataSection);
- end.