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

C++ Builder 建立透明、可移動、不規則圖形視窗

     編輯:關於C++

從位圖產生不規則視窗區域

利用 SetWindowRgn 配合位圖像素掃描,可建立任意形狀的視窗。本範例示範載入圖片、以左上角像素色作為透明色、掃描建立多邊形區域、移除內凹白色區塊,最後套用至視窗並支援滑鼠拖曳移動。

核心函數 BmpToRgn

void __fastcall TForm1::BmpToRgn()
{
    Image1->AutoSize = true;
    Form1->AutoSize = true;
    Form1->BorderStyle = bsNone; // 移除標題列與邊框
    TColor ColorKey = Image1->Canvas->Pixels[0][0]; // 透明基準色

    int x, y, l, r;
    POINT *a;
    bool lb, rb;
    HRGN wndrgn, temprgn;

    // 分配座標陣列
    if ((a = (POINT *)malloc(Width * 2 * sizeof(POINT))) == NULL) {
        ShowMessage("記憶體配置失敗!"); exit(0);
    }

    l = 0; r = Image1->Height * 2 - 1;
    wndrgn = CreateRectRgn(0, 0, Image1->Width, Image1->Height);

    // 雙向掃描每一列,找出左右邊界非透明色像素
    for (y = 0; y < Image1->Height; y++) {
        lb = true;
        for (x = 0; x < Image1->Width + 1; x++)
            if (Image1->Canvas->Pixels[x][y] != ColorKey) {
                a[l].x = x; a[l].y = y; lb = false; break;
            }
        if (lb) a[l] = a[l-1]; l++;

        rb = true;
        for (x = Image1->Width; x >= 0; x--)
            if (Image1->Canvas->Pixels[x][y] != ColorKey) {
                a[r].x = x; a[r].y = y; rb = false; break;
            }
        if (rb) a[r] = a[r+1]; r--;
    }

    // 移除內凹透明區塊 (逐像素 XOR)
    r = Image1->Height * 2 - 1;
    for (y = 0; y < Image1->Height - 1; y++) {
        for (x = a[y].x; x <= a[r].x; x++)
            if (Image1->Canvas->Pixels[x][y] == ColorKey) {
                temprgn = CreateRectRgn(x, y, x+1, y+1);
                CombineRgn(wndrgn, wndrgn, temprgn, RGN_XOR);
                DeleteObject(temprgn);
            }
        r--;
    }

    // 建立外框多邊形區域並取交集
    temprgn = CreatePolygonRgn(a, Image1->Height * 2, WINDING);
    CombineRgn(wndrgn, wndrgn, temprgn, RGN_AND);
    DeleteObject(temprgn);
    free(a);

    SetWindowRgn(Handle, wndrgn, true); // 套用視窗區域
}

滑鼠拖曳移動視窗

void __fastcall TForm1::Image1MouseDown(TObject *Sender, TMouseButton Button,
    TShiftState Shift, int X, int Y)
{
    if (Button == mbLeft) {
        ReleaseCapture();
        Perform(WM_NCLBUTTONDOWN, HTCAPTION, 0); // 模擬點擊標題列拖曳
    }
}

開啟新圖片重建區域

void __fastcall TForm1::Open1Click(TObject *Sender)
{
    if (OpenPictureDialog1->Execute()) {
        Image1->Picture->LoadFromFile(OpenPictureDialog1->FileName);
        BmpToRgn();
    }
}

注意事項

  • 圖片背景色必須純淨一致,否則透明判斷會失誤。
  • 視窗設為 bsNone 才無標題列、邊框,配合區域呈現不規則外觀。
  • 記憶體配置失敗需妥善處理,避免程式崩潰。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved