2015-08-10 1 views
1

Я пытаюсь сделать окно со стеклянным фоном, но оно не работает. Смотрите мой код:Как сделать окно со стеклянным фоном?

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { 
    switch (message) { 
     case WM_ERASEBKGND: { 
      RECT rect; 
      GetClientRect(hWnd, &rect); 
      FillRect(GetDC(hWnd), &rect, (HBRUSH)GetStockObject(BLACK_BRUSH)); 
      return(0); 
     } case WM_PAINT: { 
      RECT rect; 
      GetClientRect(hWnd, &rect); 
      rect.bottom = 262; 
      FillRect(GetDC(hWnd), &rect, (HBRUSH)COLOR_WINDOW); 
      return(0); 
     } case WM_CREATE: { 
      if (IsWindowsVistaOrGreater()) { 
       BOOL IsCompositionEnabled = FALSE; 
       DwmIsCompositionEnabled(&IsCompositionEnabled); 
       if (IsCompositionEnabled) { 
        MARGINS margins = {0, 0, 0, 0}; 
        margins.cyBottomHeight = 100; 

        HRESULT hr = DwmExtendFrameIntoClientArea(hWnd, &margins); 
        if (SUCCEEDED(hr)) { 

        } 
       } 
      } 
      return(0); 
     } case WM_CLOSE: { 
      DestroyWindow(hWnd); 
      return(0); 
     } case WM_DESTROY: { 
      PostQuitMessage(0); 
      return(0); 
     } default: { 
      return(DefWindowProc(hWnd, message, wParam, lParam)); 
     } 
    } 
} 

Этот код делает следующее окно: See the image

Это окно, что я пытаюсь сделать, но есть проблема. Когда я перемещаю окно, он моргает. Почему он моргает?

+0

Заполнение фона как в 'WM_ERASEBKGND', так и' WM_PAINT', безусловно, вызовет мерцание. Верните 0 из 'WM_ERASEBKGND', а затем просто заполните обработчик краски. Также каждому вызову 'GetDC' нужен соответствующий вызов для' ReleaseDC', или вы скоро закончите ресурсы GDI. См. Ответ ниже для примера, как правильно обрабатывать 'WM_PAINT'. –

+0

Неисправность [BeginPaint] (https://msdn.microsoft.com/en-us/library/dd183362.aspx)/[EndPaint] (https://msdn.microsoft.com/en-us/library/dd162598 .aspx) в обработчике 'WM_PAINT' приведет к тому, что недопустимая область никогда не будет сброшена. Как следствие, ваше окно будет постоянно обновляться, как только какая-либо его часть станет недействительной. – IInspectable

+0

Теперь он работает. Спасибо вам всем. –

ответ

4

Есть несколько вещей, которые вы должны изменить:

При обращении WM_PAINT, вы должны позвонить BeginPaint, чтобы получить DC и другую информацию для вашей картины, а затем вызвать EndPaint, когда вы закончите. Это дает вам DC, который ограничивает вашу картину нужной областью отсечения и предотвращает мерцание.

case WM_PAINT: { 
    PAINTSTRUCT ps; 
    HDC hdc = BeginPaint(hWnd, &ps); 
    RECT rect; 
    GetClientRect(hWnd, &rect); 
    rect.bottom = 262; 
    FillRect(hdc, &rect, (HBRUSH)COLOR_WINDOW); 
    EndPaint(hWnd, &ps); 
    return(0); 
} 

Вы также должны возвращать 1 из WM_ERASEBKGND, как вы сделали стирания.

HDC использовать при стирании в wParam, поэтому используйте это, а не окно DC.

case WM_ERASEBKGND: { 
    RECT rect; 
    GetClientRect(hWnd, &rect); 
    FillRect((HDC)(wParam), &rect, (HBRUSH)GetStockObject(BLACK_BRUSH)); 
    return(1); 
} 
+0

Вызов «EndPaint» уменьшает мерцание, потому что он сбрасывает недопустимую область, поэтому не требует повторной перерисовки. Обрезка не связана с мерцанием. – IInspectable

+0

Теперь он работает. Спасибо вам всем. –