

win32apiの勉強中です。透明なサイズが可変なウィンドウを作成しようとしています。

透明化はCreateWindowEx関数にてスタイルにWS_EX_LAYEREDを指定する事で実現出来たのですが、マウスで大きさの変更を行うと以降ウィンドウ縁をマウスで操作出来なくなります。WS_EX_LAYEREDを指定しない場合と同じ動作をさせたいのですがどのようにすれば良いでしょうか。

[code]

    #include <windows.h>
    
    LRESULT CALLBACK WndProc( HWND hwnd , UINT msg , WPARAM wp , LPARAM lp ){
        switch (msg) {
        case WM_CREATE:
            SetLayeredWindowAttributes(hwnd, RGB(255,255,255), 0, LWA_COLORKEY);
            return 0;
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        }
        return DefWindowProc(hwnd , msg , wp , lp);
    }
    
    int WINAPI WinMain( HINSTANCE hInstance , HINSTANCE hPrevInstance , PSTR lpCmdLine , int nCmdShow ){
        HWND hwnd;
        MSG msg;
        WNDCLASS winc;
    
        winc.style          = CS_HREDRAW | CS_VREDRAW;
        winc.lpfnWndProc    = WndProc;
        winc.cbClsExtra     = winc.cbWndExtra   = 0;
        winc.hInstance      = hInstance;
        winc.hIcon          = LoadIcon(NULL , IDI_APPLICATION);
        winc.hCursor        = LoadCursor(NULL , IDC_ARROW);
        winc.hbrBackground  = (HBRUSH)GetStockObject(WHITE_BRUSH);
        winc.lpszMenuName   = NULL;
        winc.lpszClassName  = TEXT("Test");
    
        if (!RegisterClass(&winc)) return -1;
    
        hwnd = CreateWindowEx(
    #if 1
            WS_EX_LAYERED | WS_EX_TOOLWINDOW,
    #else
            WS_EX_TOOLWINDOW,
    #endif
            TEXT("Test") , TEXT("Test") ,
            WS_OVERLAPPEDWINDOW | WS_VISIBLE ,
            CW_USEDEFAULT , CW_USEDEFAULT ,
            300, 200,
            NULL , NULL ,
            hInstance , NULL
            );
        if (hwnd == NULL) return -1;
    
    
        while(GetMessage(&msg , NULL , 0 , 0)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        return msg.wParam;
    }
    
[/code]


CC BY-SA 3.0
2016-04-04T08:34:57.913
23732
2016-05-21T15:18:14.803
14103
question
c++ winapi
レイヤードウィンドウの大きさ変更時の挙動について


[MSDNのSetLayeredWindowAttributesのリファレンス](https://msdn.microsoft.com/ja-
jp/library/cc411043.aspx)に

> 特定のレイヤードウィンドウを指定して SetLayeredWindowAttributes
> 関数を呼び出すと、そのウィンドウでは、多層化スタイルビットをいったんクリアしてもう一度セットするまで、UpdateLayeredWindow
> 関数を呼び出しても失敗します。

という記述がありますが、この辺が怪しいのではないでしょうか？


CC BY-SA 3.0
2016-04-12T10:11:14.527
23953
2016-04-12T10:11:14.527
9515
23732
answer


操作できなくなる原因は、ウィンドウの背景色が`SetLayeredWindowAttributes`で指定しているカラーキーと同じだからのようです。

  1. `SetLayeredWindowAttributes`のカラーキーとウィンドウの背景ブラシを異なる色にする。
  2. クライアント領域のみカラーキーで塗り潰すようにする。

としたところ、おそらく期待どおりの動きになりました。

[code]

    #include <windows.h>
    
    LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
        switch (msg) {
        case WM_CREATE:
            SetLayeredWindowAttributes(hwnd, RGB(255, 255, 255), 0, LWA_COLORKEY);
            return 0;
        case WM_PAINT:
            {
                PAINTSTRUCT ps;
                BeginPaint(hwnd, &ps);
                auto hbr = CreateSolidBrush(RGB(255, 255, 255));
                FillRect(ps.hdc, &ps.rcPaint, hbr);
                DeleteObject(hbr);
                EndPaint(hwnd, &ps);
                return 0;
            }
        case WM_NCHITTEST:
        {
            auto l = DefWindowProc(hwnd, msg, wp, lp);
            OutputDebugStringA(std::to_string(l).c_str());
            return l;
        }
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        }
        return DefWindowProc(hwnd, msg, wp, lp);
    }
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, int nCmdShow) {
    {
        HWND hwnd;
        MSG msg;
        WNDCLASS winc;
    
        winc.style = CS_HREDRAW | CS_VREDRAW;
        winc.lpfnWndProc = WndProc;
        winc.cbClsExtra = winc.cbWndExtra = 0;
        winc.hInstance = hInstance;
        winc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        winc.hCursor = LoadCursor(NULL, IDC_ARROW);
        winc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
        winc.lpszMenuName = NULL;
        winc.lpszClassName = TEXT("Test");
    
        if (!RegisterClass(&winc)) return -1;
    
        hwnd = CreateWindowEx(
    #if 1
            WS_EX_LAYERED | WS_EX_TOOLWINDOW,
    #else
            WS_EX_TOOLWINDOW,
    #endif
            TEXT("Test"), TEXT("Test"),
            WS_OVERLAPPEDWINDOW | WS_VISIBLE,
            CW_USEDEFAULT, CW_USEDEFAULT,
            300, 200,
            NULL, NULL,
            hInstance, NULL
        );
        if (hwnd == NULL) return -1;
    
    
        while (GetMessage(&msg, NULL, 0, 0)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        return msg.wParam;
    }
    
[/code]


CC BY-SA 3.0
2016-05-21T15:18:14.803
25067
2016-05-21T15:18:14.803
8616
23732
answer