2017-08-19 42 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消息处理部分。