繁体   English   中英

用笔在透明窗口上绘制

[英]draw on transparent window using pen

我想用笔在透明的窗口上画画。

画一条线时,黑色区域围绕该线。

此图显示了问题:

在此处输入图片说明

如何解决这个问题呢?

LRESULT __stdcall WindowProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
    HDC hdc, backDC;
    PAINTSTRUCT ps;

    static Point prevPt;

    // Draw or Erase
    static bool isDraw = false;
    static bool isErase = false;

    // Select Pen Color
    static int selectColor = 1;

    // Color Pen(R, G, B) and Current Pen
    static HPEN redPen;
    static HPEN greenPen;
    static HPEN bluePen;
    static HPEN* currentPen = &redPen;

    switch (iMessage)
    {
    case WM_CREATE:
    {
        redPen = CreatePen(PS_SOLID, 4, RGB(255, 0, 0));
        greenPen = CreatePen(PS_SOLID, 4, RGB(0, 255, 0));
        bluePen = CreatePen(PS_SOLID, 4, RGB(0, 0, 255));
        return 0L;
    }
    case WM_DESTROY:
        cout << "\n" << "destroying window" << endl;
        PostQuitMessage(0);
        return 0L;
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        EndPaint(hWnd, &ps);
        return 0L;
    case WM_LBUTTONDOWN:
        prevPt.x = LOWORD(lParam);
        prevPt.y = HIWORD(lParam);
        isDraw = true;
        return 0L;
    case WM_LBUTTONUP:
        isDraw = false;
        return 0L;
    case WM_MOUSEMOVE:
    {
        int x = LOWORD(lParam);
        int y = HIWORD(lParam);
        if (isDraw)
        {
            hdc = GetDC(g_hWnd);

            HPEN OldPen = (HPEN)SelectObject(hdc, *currentPen);
            MoveToEx(hdc, prevPt.x, prevPt.y, NULL);
            LineTo(hdc, x, y);

            prevPt.x = x;
            prevPt.y = y;
            DeleteObject(OldPen);
            ReleaseDC(g_hWnd, hdc);
        }
    }
    return 0L;
    case WM_RBUTTONDOWN:
        isErase = true;
        return 0L;
    case WM_RBUTTONUP:
        isErase = false;
        return 0L;
    case WM_MOUSEWHEEL:
        if (selectColor > 3)
            selectColor = 1;

        if (selectColor == 1)   // Red
            currentPen = &redPen;
        else if (selectColor == 2)
            currentPen = &greenPen;
        else if (selectColor == 3)
            currentPen = &bluePen;

        selectColor++;
        return 0L;
    }

    return DefWindowProc(hWnd, iMessage, wParam, lParam);
}

void main()
{
    HWND window;
    LPCWSTR myclass = L"DrawTest";

    WNDCLASSEX wndclass = { sizeof(WNDCLASSEX), CS_VREDRAW | CS_HREDRAW, WindowProc,
    0, 0, NULL, LoadIcon(0,IDI_APPLICATION), LoadCursor(0,IDC_ARROW), (HBRUSH)WHITE_BRUSH, 0, myclass, LoadIcon(0,IDI_APPLICATION) };
    if (RegisterClassEx(&wndclass))
    {
        window = CreateWindowEx(WS_EX_TRANSPARENT, myclass, L"title", WS_POPUP, 0, 0, GetSystemMetrics(SM_CXFULLSCREEN), GetSystemMetrics(SM_CYFULLSCREEN), 0, 0, NULL, 0);
    }

    VideoCapture* pCapture = nullptr;
    pCapture = new VideoCapture(0);

    if (pCapture)
    {
        if (!pCapture->isOpened())
        {
            cout << "Can not open video file." << endl;
            return;
        }

        int fps = (int)(pCapture->get(CAP_PROP_FPS));

        int delay = 0;
        if (fps == 0)
            fps = 24;

        delay = 1000 / fps;

        Mat colorMat;

        while (1)
        {
            *pCapture >> colorMat;
            if (colorMat.empty())
                break;

            Mat copyColor;
            colorMat.copyTo(copyColor);

            imshow("colorMat", copyColor);

            int ckey = waitKey(delay);
            if (ckey == 27)
                break;

            if (window)
            {
                ShowWindow(window, SW_SHOW);
                MSG msg;
                if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
                {
                    GetMessage(&msg, 0, 0, 0);
                    TranslateMessage(&msg);
                    DispatchMessage(&msg);
                }
            }
        }

        cv::destroyAllWindows();
    }
}

正如我在评论中所说,创建一个分层窗口:

window = CreateWindowEx(WS_EX_LAYERED, myclass, L"title", WS_POPUP, 0, 0,
                        GetSystemMetrics(SM_CXFULLSCREEN), GetSystemMetrics(SM_CYFULLSCREEN),
                        HWND_DESKTOP, NULL, NULL, NULL);

将颜色透明度设置为与背景画笔相同:

SetLayeredWindowAttributes(window, RGB(255, 255, 255), 0, LWA_COLORKEY);

WM_PAINT中

hdc = BeginPaint(hwnd, &ps);

HPEN OldPen = (HPEN)SelectObject(hdc, *currentPen);

//set random values
MoveToEx(hdc, 50, 50, NULL);
LineTo(hdc, 450, 450);

SelectObject(hdc, OldPen);

EndPaint(hwnd, &ps);

return 0;

这段代码有效, 但是您无法获得鼠标消息,因为窗口是透明的。 那是主要问题,而不是图纸。

编辑

问题是如何获取鼠标消息。 解决方案是在主窗口顶部创建第二个窗口,其不透明度几乎为零,因此不可见,但会收到鼠标消息!

window = CreateWindowEx(WS_EX_LAYERED, myclass, L"title", WS_POPUP, 0, 0,
                        GetSystemMetrics(SM_CXFULLSCREEN), GetSystemMetrics(SM_CYFULLSCREEN),
                        HWND_DESKTOP, NULL, NULL, NULL);

windowClone = CreateWindowEx(WS_EX_LAYERED, myclass, L"title", WS_POPUP, 0, 0,
                        GetSystemMetrics(SM_CXFULLSCREEN), GetSystemMetrics(SM_CYFULLSCREEN),
                        window, NULL, NULL, NULL);

使您的主窗口完全透明:

//background color MUST be the same with color Key!
SetLayeredWindowAttributes(window, RGB(255, 255, 255), 0, LWA_COLORKEY);

使几乎透明的克隆窗口

//The transparency is set to 1
SetLayeredWindowAttributes(windowClone, 0, 1, LWA_ALPHA);

LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){
    PAINTSTRUCT ps;
    HDC hdc;
    static int draw = FALSE, startX, startY, endX, endY, posX, posY;


    switch(message){ //handle the messages 
        case WM_PAINT:
            printf("WM_PAINT \n");

            if( hwnd == window && draw == TRUE ){
                HPEN OldPen, redPen;

                redPen = CreatePen(PS_SOLID, 4, RGB(255, 0, 0));

                hdc = BeginPaint(hwnd, &ps);

                OldPen = (HPEN)SelectObject(hdc, redPen);

                MoveToEx(hdc, startX, startY, NULL);
                LineTo(hdc, endX, endY);

                SelectObject(hdc, OldPen);

                EndPaint(hwnd, &ps);

                DeleteObject(redPen);

                return 0;
            }

            break;

        case WM_MOUSEMOVE:
            //printf("WM_MOUSEMOVE \n");

            if( hwnd == windowClone && draw == TRUE ){
                startX = posX;
                startY = posY;
                endX = GET_X_LPARAM(lParam);
                endY = GET_Y_LPARAM(lParam);

                posX = endX;
                posY = endY;

                InvalidateRect(window, NULL, FALSE);
            }

            break;

        case WM_LBUTTONDOWN:
            printf("WM_LBUTTONDOWN \n");

            if( hwnd == windowClone ){
                posX = GET_X_LPARAM(lParam);
                posY = GET_Y_LPARAM(lParam);
                draw = TRUE;
            }

            break;

       case WM_LBUTTONUP:
           printf("WM_LBUTTONUP \n");

           if( hwnd == windowClone && draw == TRUE ){
               draw = FALSE;
           }

           break;

       case WM_CAPTURECHANGED:
           printf("WM_CAPTURECHANGED \n");

           if( hwnd == windowClone && draw == TRUE ){
               draw = FALSE;
           }

           break;

        default:   //for messages that we don't deal with
            return DefWindowProc(hwnd, message, wParam, lParam);
    }

    return DefWindowProc(hwnd, message, wParam, lParam);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM