簡體   English   中英

使用圖像的Alpha通道將PNG圖像繪制到畫布上

[英]Getting PNG images drawn to canvas using image's Alpha channel

我正在制作一個程序,以顯示抽獎結果的歷史記錄和結果數據中的統計數據。 我想顯示球的圖像而不是數字,所以我制作了一組3D外觀的png圖像,上面有數字,小的是32x32,更大的是48x48。 如:

彩票球的形象

這些顯然是圓形的,即使在alpha通道上也具有抗鋸齒的邊緣。 我不能將它們加載到TImageList中並顯示在畫布上而不失去alpha透明度,我得到的最好的是一個硬蒙版。 相反,我在設計時為每個裝有球的png圖像的球創建了一個TImage。 為了通過球號輕松地引用它們,我聲明了var Balls: array[1..59] of TImage; ,我將其連接到表單的OnCreate中的每個TImage,它們只是Balls[1] := Image01; Balls[2] := Image02; Balls[1] := Image01; Balls[2] := Image02; 等等。 我使用這些TImage的OnMouseEnter / OnMouseLeave / OnClick事件來突出顯示並選擇它們。 實際上,我還有另一個TImage表示選擇高光,它比球稍大,當鼠標懸停在球上方時,它會出現在Ball的TImage后面。 所有這些工作正常,但是現在我想在TDrawGrid中使用相同的圖像,該圖像將所有結果數據主要顯示為文本,但是我希望使用OnDrawCell事件將球號顯示為圖像。

問題出在這里:我找不到將帶有Alpha通道的圖像復制到DrawGrid畫布上的方法-使用CopyRect時出現錯誤消息:“只能在包含位圖的情況下修改圖像”,所以我在線找到了解決方案創建一個TBitmap並復制Ball的TImage,但它丟失了alpha混合,背景為黑色。 我只希望能夠將alphachannel圖像復制到背景可以是任何顏色的任何畫布(例如,clBtnFace)。

const
  CellPadding = 4;
  Colnames: array [0..15] of string = ('Draw','Day','Date','Month','Year','1st','2nd','3rd','4th','5th','6th','B','Jackpot','Wins','Machine','Ball set');

procedure TLottoResults.DrawGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);
var
  dcBall: Integer;
  dcRect: TRect;
  dcBmp: TBitmap;
begin
  DrawGrid1.Canvas.Brush.Style := bsClear;
  if ARow = 0 then
  begin
    DrawGrid1.Canvas.Font.Name := 'Tahoma';
    DrawGrid1.Canvas.Font.Size := 12;
    DrawGrid1.Canvas.Font.Style := [fsBold];
    DrawGrid1.Canvas.TextRect(Rect, Rect.Left+CellPadding, Rect.Top,  Colnames[ACol])
  end
  else
  begin
    if gdSelected in State then DrawGrid1.Canvas.Brush.Color := clGreen
    else DrawGrid1.Canvas.Brush.Color := clNavy;
    DrawGrid1.Canvas.FillRect(Rect);
    DrawGrid1.Canvas.Font.Color := clWhite;
    if ACol in [5..11] then  // columns to display images instead of text
    begin
      // StringGrid1 is what the raw CSV data is loaded into first and is kept invisible,
      // and it's contents are copied to DrawGrid1 for actual display.
      if TryStrToInt(StringGrid1.Cells[ACol, ARow-1], dcBall)then
      begin
        if dcBall in [1..59] then
        begin
          dcBmp := TBitmap.Create;
//          Following disabled code is what has been tried in various combinations
//          dcBmp.PixelFormat := pf32bit;
//          dcBmp.TransparentMode := tmFixed;
//          dcBmp.TransparentColor := clBtnFace;
//          dcBmp.AlphaFormat := afDefined;
//          Balls[dcBall].Picture.Graphic.Transparent := True;
          dcBmp.Assign(Balls[dcBall].Picture.Graphic);
          Balls[dcBall].Picture.Bitmap := dcBmp;
//          FreeAndNil(dcBmp);

          dcRect := TRect.Create(0,0,32,32);
          if DataLoaded then
            DrawGrid1.Canvas.CopyRect(TRect.Create(Rect.Left+2, Rect.Top+2, Rect.Left+32+2, Rect.Top+32+2), Balls[dcBall].Canvas, dcRect);
//          DrawGrid1.Canvas.Draw(Rect.Top,Rect.Left,Balls[dcBall].Picture.Graphic); // Draw draws in the wrong place, why?
        end
        else
        begin // Display as text if not in range 1 to 59
          DrawGrid1.Canvas.Font.Name := 'Courier New';
          DrawGrid1.Canvas.Font.Size := 12;
          DrawGrid1.Canvas.Font.Style := [];
          DrawGrid1.Canvas.TextRect(Rect, Rect.Left+CellPadding, Rect.Top+(DrawGrid1.RowHeights[ARow] div 2)-(DrawGrid1.Canvas.TextHeight('Ag') div 2), '('+StringGrid1.Cells[ACol, ARow-1]+')');
        end;
      end
    else
    begin // Display as text is TryStrToInt failed
      DrawGrid1.Canvas.Font.Name := 'Courier New';
      DrawGrid1.Canvas.Font.Size := 12;
      DrawGrid1.Canvas.Font.Style := [];
      DrawGrid1.Canvas.TextRect(Rect, Rect.Left+CellPadding, Rect.Top+(DrawGrid1.RowHeights[ARow] div 2)-(DrawGrid1.Canvas.TextHeight('Ag') div 2), StringGrid1.Cells[ACol, ARow-1]);
    end;
    end
    else
    begin // All other columns display as text
      DrawGrid1.Canvas.Font.Name := 'Courier New';
      DrawGrid1.Canvas.Font.Size := 12;
      DrawGrid1.Canvas.Font.Style := [];
      DrawGrid1.Canvas.TextRect(Rect, Rect.Left+CellPadding, Rect.Top+(DrawGrid1.RowHeights[ARow] div 2)-(DrawGrid1.Canvas.TextHeight('Ag') div 2), StringGrid1.Cells[ACol, ARow-1]);
    end;
  end;
end;

更新-我自己解決了。 我再次看了我第一次嘗試的Draw方法(並因為它們出現在錯誤的位置而被放棄了),並意識到我已經弄混了X + Y。 這是清理后的代碼。 我敢肯定它可以進一步簡化。 我還在四處尋找如何制作精美的DrawGrid。 這是結果的屏幕截圖。

procedure TLottoResults.DrawGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);
var
  dcBall: Integer;
begin
  DrawGrid1.Canvas.Brush.Style := bsClear;
  if ARow = 0 then
  begin
    DrawGrid1.Canvas.Font.Name := 'Tahoma';
    DrawGrid1.Canvas.Font.Size := 12;
    DrawGrid1.Canvas.Font.Style := [fsBold];
    DrawGrid1.Canvas.TextRect(Rect, Rect.Left+CellPadding, Rect.Top, Colnames[ACol])
  end
  else
  begin
    if gdSelected in State then DrawGrid1.Canvas.Brush.Color := clGreen
    else DrawGrid1.Canvas.Brush.Color := clNavy;
    DrawGrid1.Canvas.FillRect(Rect);
    DrawGrid1.Canvas.Font.Color := clWhite;
    if ACol in [5..11] then  // columns to display images instead of text
    begin
      // StringGrid1 is what the raw CSV data is loaded into first and is kept invisible,
      // and it's contents are copied to DrawGrid1 for actual display.
      if TryStrToInt(StringGrid1.Cells[ACol, ARow-1], dcBall)then
      begin
        if dcBall in [1..59] then
        begin
          if DataLoaded then
             DrawGrid1.Canvas.Draw(Rect.Left+2,Rect.Top+2,Balls[dcBall].Picture.Graphic); 
        end
        else
        begin // Display as text if not in range 1 to 59
          DrawGrid1.Canvas.Font.Name := 'Courier New';
          DrawGrid1.Canvas.Font.Size := 12;
          DrawGrid1.Canvas.Font.Style := [];
          DrawGrid1.Canvas.TextRect(Rect, Rect.Left+CellPadding, Rect.Top+(DrawGrid1.RowHeights[ARow] div 2)-(DrawGrid1.Canvas.TextHeight('Ag') div 2), '('+StringGrid1.Cells[ACol, ARow-1]+')');
        end;
      end
      else
      begin // Display as text is TryStrToInt failed
        DrawGrid1.Canvas.Font.Name := 'Courier New';
        DrawGrid1.Canvas.Font.Size := 12;
        DrawGrid1.Canvas.Font.Style := [];
        DrawGrid1.Canvas.TextRect(Rect, Rect.Left+CellPadding, Rect.Top+(DrawGrid1.RowHeights[ARow] div 2)-(DrawGrid1.Canvas.TextHeight('Ag') div 2), StringGrid1.Cells[ACol, ARow-1]);
      end;
    end
    else
    begin // All other columns display as text
      DrawGrid1.Canvas.Font.Name := 'Courier New';
      DrawGrid1.Canvas.Font.Size := 12;
      DrawGrid1.Canvas.Font.Style := [];
      DrawGrid1.Canvas.TextRect(Rect, Rect.Left+CellPadding, Rect.Top+(DrawGrid1.RowHeights[ARow] div 2)-(DrawGrid1.Canvas.TextHeight('Ag') div 2), StringGrid1.Cells[ACol, ARow-1]);
    end;
  end;
end;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM