2017-08-19 82 views
0

我正在使用標準Windows API在C++中編寫應用程序。它使用按鈕做一些簡單的註冊表修改。當按下按鈕時,它會更改顯示在底部的標籤。要更改它,我需要重新繪製窗口(根據需要自動更改標籤)。但是當我重畫窗口時,它開始出現毛刺。靜態標籤開始閃爍,並且按鈕完全丟失,但在移動窗口後停止。這裏是它的一個GIF發生:使用RedrawWindow或SendMessage重繪後的窗口故障(WM_PAINT)

Glitching window

這裏是我的WndProc功能:

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { 
    static HFONT s_hFont = NULL; 
    HWND drive; 
    switch (message) 
    { 
     case WM_COMMAND: 
      { 
       int wmId = LOWORD(wParam); 
       // Parse the menu selections: 
       switch (wmId) 
       { 
        case IDM_ABOUT: 
         DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); 
         break; 
        case IDM_EXIT: 
         DestroyWindow(hWnd); 
         break; 
        case APPLY_BUTTON: 
         SetRegistryValues(hWnd); 
         break; 
        case CDRIVE_BUTTON: 
         newDriveSelection = 0; 
         RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE); // tried both this... 
         break; 
        case DDRIVE_BUTTON: 
         newDriveSelection = 1; 
         InvalidateRect(hWnd, hWndSize, NULL); // ...and this 
         break; 
        default: 
         return DefWindowProc(hWnd, message, wParam, lParam); 
       } 
      } 
      break; 
    case WM_CREATE: 
     { 
     const TCHAR* fontName = _T("Tahoma"); 
     const long nFontSize = 10; 

     HDC hdc = GetDC(hWnd); 

     LOGFONT logFont = {0}; 
     logFont.lfHeight = -MulDiv(nFontSize, GetDeviceCaps(hdc, LOGPIXELSY), 72); 
     logFont.lfWeight = FW_MEDIUM; 
     _tcscpy_s(logFont.lfFaceName, fontName); 

     s_hFont = CreateFontIndirect(&logFont); 
     ReleaseDC(hWnd, hdc); 
     //s_hFont = (HFONT)GetStockObject(); 
    } 
    break; 
    case WM_PAINT: 
     { 
      PAINTSTRUCT ps; 
      HDC hdc = BeginPaint(hWnd, &ps); 
      HWND CDrvButton = CreateWindow(
       L"BUTTON", // Predefined class; Unicode assumed 
       L"Set to C: Drive",  // Button text 
       WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, // Styles 
       20,   // x position 
       20,   // y position 
       156,  // Button width 
       21,  // Button height 
       hWnd,  // Parent window 
       (HMENU)CDRIVE_BUTTON,  // No menu. 
       (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), 
       NULL); 
      HWND DDrvButton = CreateWindow(
       L"BUTTON", // Predefined class; Unicode assumed 
       L"Set to D: Drive",  // Button text 
       WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, // Styles 
       20,   // x position 
       53,   // y position 
       156,  // Button width 
       21,  // Button height 
       hWnd,  // Parent window 
       (HMENU)DDRIVE_BUTTON,  // No menu. 
       (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), 
       NULL); 
      HWND quit = CreateWindow(
       L"BUTTON", // Predefined class; Unicode assumed 
       L"Quit",  // Button text 
       WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, // Styles 
       20,   // x position 
       125,   // y position 
       54,  // Button width 
       21,  // Button height 
       hWnd,  // Parent window 
       (HMENU)IDM_EXIT,  // No menu. 
       (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), 
       NULL); 
      HWND apply = CreateWindow(
       L"BUTTON", // Predefined class; Unicode assumed 
       L"Apply",  // Button text 
       WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, // Styles 
       220,   // x position 
       125,   // y position 
       63,  // Button width 
       21,  // Button height 
       hWnd,  // Parent window 
       (HMENU)APPLY_BUTTON,  // No menu. 
       (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), 
       NULL); 
      HWND the = CreateWindow(
       L"static", 
       L"ST_U", 
       WS_CHILD | WS_VISIBLE | WS_TABSTOP, 
       35, 
       82, 
       28, 
       17, 
       hWnd, 
       (HMENU)(501), 
       (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), 
       NULL); 
      drive = CreateWindow(
       L"static", 
       L"ST_U", 
       WS_CHILD | WS_VISIBLE | WS_TABSTOP, 
       66, 
       82, 
       18, 
       17, 
       hWnd, 
       (HMENU)(501), 
       (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), 
       NULL); 
      HWND selected = CreateWindow(
       L"static", 
       L"ST_U", 
       WS_CHILD | WS_VISIBLE | WS_TABSTOP, 
       87, 
       82, 
       196, 
       17, 
       hWnd, 
       (HMENU)(501), 
       (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), 
       NULL); 
      HWND newdrv = CreateWindow(
       L"static", 
       L"ST_U", 
       WS_CHILD | WS_VISIBLE | WS_TABSTOP, 
       25, 
       99, 
       276, 
       23, 
       hWnd, 
       (HMENU)(501), 
       (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), 
       NULL); 
      SetWindowText(the, L"The"); 
      SetWindowText(drive, GetDriveLetter()); 
      SetWindowText(selected, L"drive is set as the current drive."); 
      switch (newDriveSelection) { 
       case 0: 
        SetWindowText(newdrv, L"The C: drive will be when you click Apply."); 
        break; 
       case 1: 
        SetWindowText(newdrv, L"The D: drive will be when you click Apply."); 
        break; 
       default: 
        SetWindowText(newdrv, L""); 
        break; 
      } 
      SendMessage(CDrvButton, WM_SETFONT, (WPARAM)s_hFont, (LPARAM)MAKELONG(TRUE, 0)); 
      SendMessage(DDrvButton, WM_SETFONT, (WPARAM)s_hFont, (LPARAM)MAKELONG(TRUE, 0)); 
      SendMessage(apply, WM_SETFONT, (WPARAM)s_hFont, (LPARAM)MAKELONG(TRUE, 0)); 
      SendMessage(quit, WM_SETFONT, (WPARAM)s_hFont, (LPARAM)MAKELONG(TRUE, 0)); 
      SendMessage(the, WM_SETFONT, (WPARAM)s_hFont, (LPARAM)MAKELONG(TRUE, 0)); 
      SendMessage(drive, WM_SETFONT, (WPARAM)s_hFont, (LPARAM)MAKELONG(TRUE, 0)); 
      SendMessage(selected, WM_SETFONT, (WPARAM)s_hFont, (LPARAM)MAKELONG(TRUE, 0)); 
      SendMessage(newdrv, WM_SETFONT, (WPARAM)s_hFont, (LPARAM)MAKELONG(TRUE, 0)); 
      EndPaint(hWnd, &ps); 
     } 
     break; 
    case WM_DESTROY: 
     DeleteObject(s_hFont); 
      PostQuitMessage(0); 
      break; 
     default: 
      return DefWindowProc(hWnd, message, wParam, lParam); 
    } 
    return 0; 
} 

什麼引起我的代碼的問題?我認爲這是WM_PAINT處理程序的問題,因爲這有時也會在未最小化程序時發生。

+4

你爲什麼在'WM_PAINT'上創建窗口? – VTT

+1

除此之外,在這裏調用RedrawWindow是不必要的,失效可能更乾淨。你絕不能發送WM_PAINT。 –

+0

你需要養成閱讀文檔的習慣。 [WM_PAINT](https://msdn.microsoft.com/en-us/library/windows/desktop/dd145213.aspx)相當簡潔。如果這還不夠,[WM_PAINT消息](https://msdn.microsoft.com/en-us/library/dd145137.aspx)提供了更多信息。 – IInspectable

回答

7

您正在創建組件,每次應用程序重新繪製 - 處理WM_PAINT消息,這就是爲什麼有閃爍。移動從:

HDC hdc = BeginPaint(hWnd, &ps); 
// move everything in here to WM_CREATE message handling section 
EndPaint(hWnd, &ps); 

塊到WM_CREATE部分。繪畫事件用於繪畫,而不是創建窗口(組件),發送消息或處理輸入。聲明:

switch (newDriveSelection) 

更適合於WM_COMMAND消息處理部分。