2015-06-27 50 views
3

我有這樣做的擴展畫面的窗口:在擴展幀繪製給人奇怪的顏色

​​

但任何在擴展幀繪製具有非常奇怪的顏色(除了白色,唯一的顏色即保持不變),像這樣(忽略在在市中心凌亂內容和凌亂的工具欄。

Screenshot

粉紅色的矩形(0xFFC9FF)的應該是0x8000FF。如果我將DirectX11內容(中心事物)放在擴展幀中,我的FPS計數器的alpha混合會變得混亂。如果我對正確的對話框做同樣的事情,也會發生同樣的情況。

所以,我該怎麼辦這是否正確?我已經試過先畫到內存DC,然後使用BitBlt。我使用GDI +(加CreateCompatibleDCCreateCompatibleBitmap等功能來處理內存DC)。

PS:因爲你問,這裏是WndProc

LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 
{ 
    LRESULT ReturnValue; 
    if (DwmDefWindowProc(hWnd, uMsg, wParam, lParam, &ReturnValue)) return ReturnValue; 

    switch (uMsg) 
    { 
    case WM_CREATE: 
    { 
     // ... 

     RECT rcClient; 
     GetWindowRect(hWnd, &rcClient); 

     SetWindowPos(hWnd, 
      NULL, 
      rcClient.left, rcClient.top, 
      rcClient.right - rcClient.left, rcClient.bottom - rcClient.top, 
      SWP_FRAMECHANGED); 

     return 0; 
    } 
    case WM_ACTIVATE: 
    { 
     MARGINS Margins; 
     Margins.cxLeftWidth = LEFT_BORDER; 
     Margins.cxRightWidth = RIGHT_BORDER; 
     Margins.cyTopHeight = TOP_BORDER; 
     Margins.cyBottomHeight = BOTTOM_BORDER; 
     if (DwmExtendFrameIntoClientArea(hWnd, &Margins) != S_OK) 
     { 
      MessageBox(hWnd, L"Erro ao configurar janela.", NULL, MB_ICONERROR); 
      PostQuitMessage(WM_QUIT); 
     } 

     if (LOWORD(wParam)) 
     { 
      fActive = true; 
     } 
     else 
     { 
      fActive = false; 
     } 
     InvalidateRect(hWnd, NULL, false); 

     return 0; 
    } 

    case WM_SIZE: 
     /* ... */ 

    case WM_NCCALCSIZE: 
     return 0; 

    case WM_NCHITTEST: 
     /* ... */ 

    case WM_GETMINMAXINFO: 
     ((LPMINMAXINFO)lParam)->ptMinTrackSize = { 640, 400 }; 
     return 0; 

    case WM_PAINT: 
    { 
     using namespace Gdiplus; 

     PAINTSTRUCT ps; 
     HDC hDC = BeginPaint(hWnd, &ps); 

     RECT rcWindow; 
     GetWindowRect(hWnd, &rcWindow); 
     POINT ptSize = { rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top }; 

     HDC hBuffer = CreateCompatibleDC(hDC); 
     HBITMAP hBitmap = CreateCompatibleBitmap(hDC, ptSize.x, ptSize.y); 
     SelectObject(hBuffer, hBitmap); 

     Graphics graphics(hBuffer); 
     Pen Outline(Color(128, 128, 128)); 
     SolidBrush Selected(Color(128, 0, 255)); 
     Rect Tab1(10, 10, 200, 50); 

     graphics.FillRectangle(&Selected, Tab1); 
     graphics.DrawRectangle(&Outline, Tab1); 

     /* ... */ 

     BitBlt(hDC, 0, 0, ptSize.x, ptSize.y, hBuffer, 0, 0, SRCCOPY); 

     EndPaint(hWnd, &ps); 
     return 0; 
    } 

    /* ... */ 

    default: 
     return DefWindowProc(hWnd, uMsg, wParam, lParam); 
    } 
} 
+0

在我看來是毫無意義的詢問程序,但不會顯示你的程序。 –

+0

@DavidHeffernan是的,你是對的。我應該發佈它。 – LHLaurini

+0

總是很高興看到噸的蘇珊娜模型! 'AlphaBlend'是你完成這項任務的朋友。 – enhzflep

回答

3

正如我所說,你幾乎沒有用的AlphaBlend。我沒有記住/意識到的是,你需要使用32位DibSection來保存紫色矩形。您還需要確保使用32位感知繪圖功能。這意味着你要麼必須直接寫入到DIB的位,具有的GetDIBits調用檢索它們後(或創建一些位DIB之前)你需要使用GDI +繪製矩形紫色。你可以在WM_INITDIALOG處理程序中看到我註釋掉的代碼。這給出了第二張圖片中顯示的結果。

嘗試一些意見,我在回答中因爲我已經刪除了之後,我認識到一個熟悉的問題。紫色矩形的顏色取決於我窗口顯示的窗口顏色。

這裏是一個已經過測試,根據Win7s實施DWM的另一個工作代碼示例。我不確定Glass是否在這裏有所作爲,或者如果Win 8的行爲類似。

以下是圖像:(畫時,顏色是正確的,使得8位索引的一個形象有所改變了它)

enter image description hereenter image description here

注意,在編輯框中的文本是有點時髦的,從好的變化到不好,因爲背景的窗口從黑色變爲白色。這與使用GDI繪製它時紫色矩形表現出的效果相同。當我使用GDI +時,問題就消失了。快速拖動窗口可以使紫色框的邊緣顯得有點奇怪。我認爲這是Windows7中DWM實施的許多缺陷中的另一個。

下面是此窗口的完整代碼:

#define _WIN32_IE 0x0501 
#define _WIN32_WINNT 0x0501 
#define WINVER 0x0510 

#include <windows.h> 
#include <commctrl.h> 
#include <stdio.h> 
#include "resource.h" 
#include <dwmapi.h> 
#include <gdiplus.h> 
#include <wingdi.h> 
using namespace Gdiplus; 
HINSTANCE hInst; 

// BMP, GIF, JPEG, PNG, TIFF, Exif, WMF, and EMF 
HBITMAP mLoadImageFile(wchar_t *filename) 
{ 
    HBITMAP result = NULL; 
    Bitmap bitmap(filename, false); 
    Color colBkg(0,0,0,0); 
    bitmap.GetHBITMAP(colBkg, &result); 
    return result; 
} 

HBITMAP zCreateDibSection(HDC hdc, int width, int height, int bitCount) 
{ 
    BITMAPINFO bi; 
    ZeroMemory(&bi, sizeof(bi)); 
    bi.bmiHeader.biSize = sizeof(bi.bmiHeader); 
    bi.bmiHeader.biWidth = width; 
    bi.bmiHeader.biHeight = height; 
    bi.bmiHeader.biPlanes = 1; 
    bi.bmiHeader.biBitCount = bitCount; 
    bi.bmiHeader.biCompression = BI_RGB; 
    return CreateDIBSection(hdc, &bi, DIB_RGB_COLORS, 0,0,0); 
} 

HRESULT ExtendGlassIntoClient(HWND hwnd, int left, int right, int top, int bottom) 
{ 
    MARGINS margins = {left,right,top,bottom}; 
    HRESULT hr = S_OK; 

    hr = DwmExtendFrameIntoClientArea(hwnd,&margins); 
    if (SUCCEEDED(hr)) 
    { 
     // ... 
    } 
    return hr; 
} 

HBITMAP mImg, mStackOverflowBitmap; 
HDC memDC, memDC2; 
HBITMAP oldBmp, oldBmp2; 
LRESULT CALLBACK DlgMain(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 
{ 
    switch(uMsg) 
    { 
    case WM_INITDIALOG: 
    { 
     ExtendGlassIntoClient(hwndDlg, 0,0,50,0); 
     mImg = mLoadImageFile(L"girl.png"); 
     mStackOverflowBitmap = zCreateDibSection(NULL, 200, 50, 32); 

     memDC = CreateCompatibleDC(NULL); 
     memDC2 = CreateCompatibleDC(NULL); 

     oldBmp = (HBITMAP)SelectObject(memDC, mImg); 
     oldBmp2 = (HBITMAP)SelectObject(memDC2, mStackOverflowBitmap); 

// ** DOESNT WORK ** - produces a washed-out pink rectangle ***** 
//  HBRUSH mBrush = CreateSolidBrush(RGB(128,0,255)); 
//  RECT mRect = {0,0,200,50}; 
//  FillRect(memDC2, &mRect, mBrush); 
//  DeleteObject(mBrush); 

      Color mCol(255,128,0,255); 
      SolidBrush mBrush(mCol); 
      Graphics graphics(memDC2); 
      graphics.FillRectangle(&mBrush, (int)0, (int)0, 200, 50); 

    } 
    return TRUE; 

    case WM_ERASEBKGND: 
     { 
      HDC hdc; 
      RECT mRect, topRect; 
      hdc = (HDC)wParam; 
      GetClientRect(hwndDlg, &mRect); 
      topRect = mRect; 
      topRect.bottom = 50; 
      FillRect(hdc, &topRect, (HBRUSH)GetStockObject(BLACK_BRUSH)); 
      mRect.top += 50; 
      FillRect(hdc, &mRect, (HBRUSH)GetStockObject(WHITE_BRUSH)); 

      BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA}; 
      AlphaBlend(hdc, 0,0, 55,96, memDC, 0, 0, 55,96, bf); 

      AlphaBlend(hdc, 100,32,200,50, memDC2, 0,0,200,50, bf); 

      return 1; 
     } 


    case WM_CLOSE: 
    { 
     EndDialog(hwndDlg, 0); 
    } 
    return TRUE; 

    case WM_COMMAND: 
    { 
     switch(LOWORD(wParam)) 
     { 
     } 
    } 
    return TRUE; 
    } 
    return FALSE; 
} 


int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) 
{ 
    GdiplusStartupInput gdiplusStartupInput; 
    ULONG_PTR   gdiplusToken; 
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); 

     hInst=hInstance; 
     InitCommonControls(); 
     int retVal = DialogBox(hInst, MAKEINTRESOURCE(DLG_MAIN), NULL, (DLGPROC)DlgMain); 

    GdiplusShutdown(gdiplusToken); 
    return retVal; 
} 
+1

非常感謝!解決方案其實很簡單。我已經在使用GDI +,它使用32位顏色。然後我改變'CreateCompatitleBitmap'到'CreateDIBSection'就像你告訴我做的那樣,它工作的很好!使用'AlphaBlend'而不是'BitBlt'雖然沒有什麼區別。 PS:我認爲W7和W8繪製窗戶的方式是一樣的,除了玻璃效果。 – LHLaurini

+1

你是最受歡迎的。很高興聽到這是你做出的一個快速簡單的改變。感謝關於使用'AlphaBlend'和'BitBlt'的提示。我有點生疏,現在有一段時間沒有觸及32位圖像代碼。希望你能像我一樣受益! – enhzflep