2017-08-19 2 views
0

Ich schreibe eine Anwendung in C++ mit der Standard-Windows-API. Es macht einige einfache Änderungen der Registrierung mit Schaltflächen. Wenn eine Taste gedrückt wird, ändert sich die Beschriftung unten. Um es zu ändern, muss ich das Fenster neu streichen (das Etikett wird bei Bedarf automatisch geändert). Aber wenn ich das Fenster neu zeichne, fängt es an zu glitchen. Die statischen Beschriftungen beginnen zu flackern, und die Schaltflächen fehlen vollständig, aber nach dem Verschieben des Fensters bleibt sie stehen. Hier ist ein GIF es passiert:Fensterfehler nach dem Redrawing mit RedrawWindow oder SendMessage (WM_PAINT)

Glitching window

hier meine WndProc Funktion ist:

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; 
} 

Was das Problem mit meinem Code verursachen könnte? Ich denke, es ist ein Problem mit dem WM_PAINT-Handler, da dies manchmal auch passiert, wenn das Programm nicht minimiert wird.

+4

Warum erstellen Sie Windows auf 'WM_PAINT'? – VTT

+1

Darüber hinaus ist der Aufruf von RedrawWindow hier unnötig, die Ungültigkeit ist wahrscheinlich sauberer. Und Sie dürfen WM_PAINT niemals senden. –

+0

Sie müssen sich angewöhnen, die Dokumentation zu lesen. [WM_PAINT] (https://msdn.microsoft.com/en-us/library/windows/desktop/dd145213.aspx) ist ziemlich prägnant. Wenn das nicht genug ist, bietet [The WM_PAINT Message] (https://msdn.microsoft.com/en-us/library/dd145137.aspx) weitere Informationen. – IInspectable

Antwort

7

Sie erstellen Komponenten jedes Mal, wenn die Anwendung neu lackiert - behandelt die WM_PAINT Nachricht und deshalb Flicker ist. Bewegen Sie alles von der:

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

Block WM_CREATE Abschnitt. Das Paint-Ereignis dient zum Malen, nicht zum Erstellen der Fenster (Komponenten), zum Senden von Nachrichten oder zur Handhabung der Eingabe. Die Aussage von:

switch (newDriveSelection) 

ist besser geeignet für WM_COMMAND Nachricht Handhabung Abschnitt.