⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mmdibcv.pas

📁 一套及时通讯的原码
💻 PAS
📖 第 1 页 / 共 3 页
字号:

{-- 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;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -