2016-11-11 17 views
0

我想使用筆在透明窗口上繪圖。使用筆在透明窗口上繪圖

在線條周圍繪製線條黑色區域時。

此圖像顯示了問題:

enter image description here

如何解決這個問題呢?

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(); 
    } 
} 
+1

你是如何使窗口透明? – immibis

+0

我認爲提供您所描述的「線條周圍的黑色像素」的截圖會很有用。 – vordhosbn

+0

我聲明WNDCLASSEX結構並使用CreateWindowEx()函數。我在這個函數的第一個參數中分配'WS_EX_TRANSPARENT'選項。 –

回答

0

正如我在我的評論說,創建一個分層的窗口:

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); 
} 
+0

感謝您的回答。我想通過鼠標事件繪製線條,圓圈等。但是你的意見是通過鼠標事件在透明窗口上繪製是不可能的。是嗎? –

+0

@ EthanYoung-JaePark你可以用一個小技巧。請參閱編輯 –

+0

謝謝。我想你的建議和應用我的項目的方式。然後,它工作得很好。謝謝XD –