首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

Delphi 取得圖片透明區域建立不規則視窗

     編輯:Delphi

在 Delphi 開發中,建立非矩形、不規則形狀的視窗(如圓形、多邊形或任意剪影視窗)是常見需求。關鍵在於從圖片中提取透明區域,構建 Windows 區域(HRGN),再套用至視窗。本文提供一個高效的掃描線演算法實作,並示範如何套用至無框視窗。

核心演算法:GraphicToRGN

函式 GraphicToRGN(mGraphic: TGraphic; mTransPoint: TPoint): HRGN 接收圖形物件與一個透明色參考點,回傳對應的非透明區域組合而成的 HRGN。其核心邏輯為:

  1. 建立與圖片等大的 24/32-bit Bitmap,繪製圖片內容。
  2. 以 mTransPoint 取得的像素顏色作為透明色。
  3. 逐行掃描每一掃描線,尋找「非透明色」的連續像素段(Run)。
  4. 每發現一段,建立矩形區域 CreateRectRgn(x1, y, x2, y+1),並以 CombineRgn(..., RGN_OR) 合併至結果區域。
  5. 採用「線段合併」而非「逐點合併」,大幅減少 CombineRgn 呼叫次數,顯著提升大圖處理速度。

完整函式實作

function GraphicToRGN(mGraphic: TGraphic; mTransPoint: TPoint): HRGN;
var
  I, J: Integer;
  vStart: Integer;
  vHandle: HRGN;
  vTransColor: TColor;
begin
  Result := 0;
  if not Assigned(mGraphic) then Exit;
  Result := CreateRectRgn(0, 0, 0, 0); // 空區域
  with TBitmap.Create do
  try
    Width := mGraphic.Width;
    Height := mGraphic.Height;
    Canvas.Draw(0, 0, mGraphic);
    vTransColor := Canvas.Pixels[mTransPoint.X, mTransPoint.Y];
    for I := 0 to Height - 1 do
    begin
      vStart := -1; // -1 表示尋找段起點
      for J := 0 to Width do // 故意多跑一個 Width 以便在行尾關閉段
      begin
        // 判斷是否為非透明像素且未越界
        if (J < Width) and (Canvas.Pixels[J, I] <> vTransColor) then
        begin
          if vStart < 0 then vStart := J; // 記錄段起點
        end
        else if vStart >= 0 then // 遇到透明色或行尾,且已有起點 -> 區段結束
        begin
          vHandle := CreateRectRgn(vStart, I, J, I + 1);
          try
            CombineRgn(Result, Result, vHandle, RGN_OR);
          finally
            DeleteObject(vHandle);
          end;
          vStart := -1; // 重置
        end;
      end;
    end;
  finally
    Free;
  end;
end;

套用至視窗範例

在無框視窗(BorderStyle := bsNone)中,於按鈕點擊事件呼叫:

procedure TForm1.Button1Click(Sender: TObject);
var
  vRGN: HRGN;
begin
  BorderStyle := bsNone;
  Image1.Left := 0;
  Image1.Top := 0;
  // 以 Image1 左上角 (0,0) 顏色為透明色
  vRGN := GraphicToRGN(Image1.Picture.Graphic, Point(0, 0));
  try
    // 將區域套用至視窗,True 表示重繪
    SetWindowRgn(Handle, vRGN, True);
  finally
    // 套用成功後系統會擁有區域,這裡仍建議釋放以防萬一
    DeleteObject(vRGN);
  end;
end;

效能優化重點

  • 掃描線 + 線段合併:將 O(Width×Height) 次區域合併降為 O(非透明線段數),對大圖效能提升數倍。
  • Canvas.Pixels 存取較慢,極大圖建議用 Scanline 屬性直接操作像素記憶體。
  • 若圖片含 Alpha 通道,可改判斷 Alpha = 0 為透明。

應用場景

  • 自訂形狀視窗(音樂播放器皮膚、異形工具箱)。
  • 遊戲角色剪影點擊測試區域。
  • 螢幕標記、截圖工具的不規則選取框。

掌握此技巧,即可在 Delphi 中輕鬆打破矩形視窗限制,創造極具視覺特色的應用程式介面。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved