<menu id="w8yyk"><menu id="w8yyk"></menu></menu>
  • <dd id="w8yyk"><nav id="w8yyk"></nav></dd>
    <menu id="w8yyk"></menu>
    <menu id="w8yyk"><code id="w8yyk"></code></menu>
    <menu id="w8yyk"></menu>
    <xmp id="w8yyk">
    <xmp id="w8yyk"><nav id="w8yyk"></nav>
  • 網站首頁 > 物聯資訊 > 技術分享

    使用Win32 API創建不規則形狀&帶透明色的窗口

    2016-09-28 00:00:00 廣州睿豐德信息科技有限公司 閱讀
    睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接

    前一陣突然想起了9月份電面某公司實習時的二面題,大概就是說怎么用Win32 API實現一個透明的窗口,估計當時我的腦殘答案肯定讓面試官哭笑不得吧。所以本人決定好好研究下這個問題。經過一下午的摸索,基本掌握了使用Win32 API創建各種匪夷所思的窗口的基本思路。

    (以下文字基于本人的個人理解,由于本人技術和經驗原因不保證正確性,希望各位不吝指正)

    首先我們需要了解一些基礎知識。

    1、Layered Windows。這是Windows2000開始引入的新概念,重新定義了窗口的Hit Testing方法,以前都是把窗口按rectangle的方式裁剪,而把窗口加上WS_EX_LAYERED的Style后就可以根據窗口的形狀和像素值進行Hit Testing[1],這樣我們的不規則窗口就變成了真正意義上的獨立窗口,而不是傳統的被一個不可見的矩形窗口所包含。

    Layered Windows支持兩種繪制方式,一種是采用UpdateLayeredWindow函數,優點是是一勞永逸,不需要在窗口函數中響應各種重繪事件,缺點嘛大概就是這高科技玩意讓人一時半會接受不了= =另一種方式就是先用SetLayeredWindowAttributes函數設置關于窗口透明度的信息,然后用傳統方式,在窗口函數中響應各種重繪事件。然而我們其實似乎并不需要關注WM_PAINT,只要在WM_CREATE中初始化一下窗口的全局背景(顏色和SetLayeredWindowAttributes所定義的相同),然后在WM_ERASEBKGND中更新一些顏色與SetLayeredWindowAttributes定義的不同的細節區域之處便可。

    2、SetWindowRgn函數。這個函數用來定義窗口的區域,我們的不規則形狀由此而來。這個函數和它的朋友們十分強大,不僅可以定義獨立的基本形狀的區域,還可以通過運算來組合已有區域從而產生新的區域。下面的實例就通過CombineRgn函數的幫助來產生了一個孔方兄形狀的窗口。

    好了,基本知識我們已經掌握了,下面來看看我做的示例程序的運行效果:

    RFID設備管理軟件

    怎么樣,還算比較cool吧。下面是完整代碼:

    #include <windows.h>

    LRESULT _stdcall WinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        static HDC hDC = GetWindowDC(hWnd);
        static HRGN hRgn = CreateRectRgn(120, 70, 280, 230);

        switch(uMsg)
        {
        case WM_ERASEBKGND:
            {
                DefWindowProc(hWnd, uMsg, wParam, lParam);
                FillRgn(hDC, hRgn, CreateSolidBrush(RGB(255, 165, 0))); // Orange
                SelectObject(hDC, hRgn);
                return 0;
            }

        case WM_CREATE:
            {
                HRGN hRgn1 = CreateEllipticRgn(0, 0, 400, 300);
                HRGN hRgn2 = CreateEllipticRgn(150, 100, 250, 200);
                CombineRgn(hRgn1, hRgn1, hRgn2, RGN_XOR);
                SetWindowRgn(hWnd, hRgn1, TRUE);
                DeleteObject(hRgn1);
                 DeleteObject(hRgn2);          
                 break;
             }
     
        case WM_LBUTTONDOWN:
             {
                SendMessage(hWnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);
                break;
            }

        case WM_DESTROY:
            {
                DeleteObject(hRgn);
                ReleaseDC(hWnd, hDC);
                PostQuitMessage(0);
                break;
             }
        }
        return DefWindowProc(hWnd, uMsg, wParam, lParam);;
    }

    int _stdcall WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, BOOL)
    {
        WNDCLASS wc = {0};
        wc.lpszClassName = L"wndclass";
        wc.hbrBackground = CreateSolidBrush(RGB(255, 99, 71));
        wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        wc.hCursor = LoadCursor(NULL, IDC_ARROW);
        wc.lpfnWndProc = WinProc;
        RegisterClass(&wc);

        HWND hWnd = CreateWindowExW(WS_EX_LAYERED, L"wndclass", L"Window", WS_POPUP|WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 400, 300, 0, 0, hInstance, 0);
        if (hWnd == NULL)
            return 1;

        SetLayeredWindowAttributes(hWnd, NULL, 178, LWA_ALPHA); // Tomato

        MSG msg = {0};
        while (GetMessage(&msg, 0, 0, 0))
        {
            DispatchMessage(&msg);
        }

        return 0;
    }

    參考資料:
    [1] MSDN:Layered Windows
    [2] WindowsAPI_001:創建一個不規則的窗口的方法(用到Region系列API)

    » 轉載請注明來源及鏈接:未來代碼研究所» 本文鏈接地址:http://blog.atelier39.org/winuser/188.html
    RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全