2011-04-13 105 views
8

這是我的朋友,是一個將是漫長的...GDI +字體渲染,尤其是在分層窗口

我得到了一些非常奇怪的行爲,當我試圖呈現分層窗口的文本。

奇怪的是,對於font/font-style/font-size的某些組合,GDI +更改了渲染方法。對於尺寸爲之間的Tahoma-Bold字體,在 8.49和16.49(像素單位)之間,包括「失敗」。對於其他字體和樣式,我會以不同的尺寸「失敗」。

output from code below

爲清楚起見我提供了一個完整的可執行例子進一步下跌。一起玩的兩個關鍵參數是在23行:

Color g_oTextColor(255, 240, 0, 0); // Simply change Color to (254, 240, 0, 0) [to add slight transparency] and everything will work! 
#define USE_LAYERED_WINDOW // or just comment this line out [to use a regular window], and everything will work! 

當使用分層的窗口和完全不透明的字體繪製背景透明的「洞」。但是,如果我爲文本顏色(alpha通道= 254)添加了一點透明度,字體就變得不透明。或者,如果我使用常規(非分層)窗口,字體呈現不透明。 這裏發生了什麼?

即使沒有分層/透明度問題,很明顯這裏發生了一些奇怪的事情。字體大小8.49 - 16.48獲得渲染像素完美,其他字體有輕微模糊的質量,特別是小的。所以看起來系統採用不同的方法來渲染這些中等尺寸。 有人可以解釋這一點,我怎麼可能渲染例如字體大小8.0像素沒有上面的模糊?我已經試過各種設置SetTextRenderingHint()SetTextContrast()但沒有對我試圖宋體&大小爲8的字體宋體只有...


邊問題1看着脆: 我想用純粹的GDI +用於屏幕外繪圖,但我無法通過簡單地創建對象來獲得它的工作。我仍然不得不使用舊的GDI東西來創建一個DC並選擇HBitmap。我如何在GDI +中做到這一切?

邊問題2(怪才只): 我也試圖將字體繪製在良好的老GDI但我得到了一些更離奇的效果:(1)在分層窗口中的文本變得透明但在添加劑的方式。 (所以如果後面的窗口很暗,紅色的文字看起來會很好,但如果窗口後面的窗口是白色的,文本就會完全消失!)另外,如果我用自己的半透明正方形填充自己的窗口,那麼表現會像預期的那樣。 (如果它後面的窗口是黑色的,紅色方塊會變成深紅色,並且方塊會在白色窗口上變成淺紅色)。我可以在一個分層窗口中同時觀察這兩種行爲。和(2)作爲一個非常不受歡迎的獎金的繪製文本失去了它的命中測試,併成爲無法點擊? 有什麼解釋嗎?

如果你已經閱讀了這麼多,感謝你的忍耐,謝謝你的答案!

// Create as a console application project 
// + Unicode charset 
// + Precompiled headers off 
// + make sure to add linker input: gdiplus.lib 

#ifndef _WIN32_WINNT  // Allow use of features specific to Windows XP or later.     
#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows. 
#endif      

// Standard and GDI+ stuffstuff 
#include <stdio.h> 
#include <tchar.h> 
#include <windows.h> 
#include <iostream> 
#include <cassert> 
#include <Gdiplus.h> 
using namespace Gdiplus; 
GdiplusStartupInput g_oGdiPlusStartupInput; 
ULONG_PTR g_pGdiPlusToken = NULL; 


// #*#*#*#*#*#*#*#*# LINES TO CHANGE ---------->---------->----------> 
Color g_oTextColor(255, 240, 0, 0); // Simply change Color to (254, 240, 0, 0) [to add slight transparency] and everything will work! 
#define USE_LAYERED_WINDOW // or just comment this line out [to use a regular window], and everything will work! 


// Forward declarations 
void RegWndClass(); 
LRESULT CALLBACK WndProc(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam); 
void CreateWindows(); 
void Draw(); 
void MsgLoop(); 

// Other Globals 
ATOM g_iWndClass = 0; 
HWND g_hWndGdiPlus = NULL; 
HWND g_hWndGdi = NULL; 
const wchar_t* g_pWndClass = L"TST"; 
int g_iWidth = 200; 
int g_iHeight = 200; 

// Main entry-point 
int _tmain(int argc, _TCHAR* argv[]) 
{ 
    GdiplusStartup(&g_pGdiPlusToken, &g_oGdiPlusStartupInput, NULL); 

    RegWndClass(); 
    CreateWindows(); 
    Draw(); 

    MsgLoop(); 

    ::UnregisterClass(g_pWndClass, NULL); 
    ::Sleep(500); 


    GdiplusShutdown(g_pGdiPlusToken); 

    return 0; 
} // _tmain 

void CreateWindows() 
{ 
#ifdef USE_LAYERED_WINDOW 
     // The key trick is to create a window with style WS_EX_LAYERED, but WITHOUT any subsequent calls to SetLayeredWindowAttributes() 
     // This gives us a magic window that must be updated with UpdateLayeredWindow() (and it does NOT recieve any WM_PAINT messages) 
     // as brilliantly described in: http://alexkr.com/source-code/50/layered-windows-and-updatelayeredwindow/ 
     g_hWndGdiPlus = ::CreateWindowEx(WS_EX_LAYERED, g_pWndClass, L"", WS_POPUP | WS_VISIBLE, 1000, 200, g_iWidth, g_iHeight, NULL, NULL, NULL, NULL); 
#else 
     g_hWndGdiPlus = ::CreateWindowEx(0, g_pWndClass, L"", WS_OVERLAPPEDWINDOW | WS_POPUP | WS_VISIBLE, 1000, 200, g_iWidth, g_iHeight, NULL, NULL, NULL, NULL); 
#endif 

    //g_hWndGdi = ::CreateWindowEx(WS_EX_LAYERED, g_pWndClass, L"", WS_POPUP | WS_VISIBLE, 720, 500, 200, 200, NULL, NULL, NULL, NULL); 

} // CreateWindows 

void Draw() 
{ 
    // Init GDI+ surface 
    HDC hOff = ::CreateCompatibleDC(NULL); 
    Bitmap oDaBigOne(g_iWidth, g_iHeight, PixelFormat32bppARGB); 
    HBITMAP hBMit = NULL; 
    Color oCol(0, 0, 0, 0); 
    oDaBigOne.GetHBITMAP(oCol, &hBMit); 
    HGDIOBJ hSave = ::SelectObject(hOff, hBMit); 

#ifdef USE_LAYERED_WINDOW 
     Graphics oGraph(hOff); 
#else 
     Graphics oGraph(g_hWndGdiPlus); 
#endif 

    oGraph.Clear(Color(255, 55, 155, 255)); 

    // Draw text 
    oGraph.SetTextRenderingHint(TextRenderingHintAntiAliasGridFit); 
    oGraph.SetTextContrast(0xffffffff); 
    oGraph.SetCompositingMode(CompositingModeSourceOver); 
    oGraph.SetCompositingQuality(CompositingQualityHighQuality); 
    oGraph.SetPixelOffsetMode(PixelOffsetModeHighQuality); 

    const FontFamily oFamily(L"Tahoma", NULL); 

#if 1 // Use bold 
    Font oF600(&oFamily, 6.00, FontStyle::FontStyleBold, Unit::UnitPixel); 
    Font oF800(&oFamily, 8.00, FontStyle::FontStyleBold, Unit::UnitPixel); 
    Font oF848(&oFamily, 8.48, FontStyle::FontStyleBold, Unit::UnitPixel); 
    Font oF849(&oFamily, 8.49, FontStyle::FontStyleBold, Unit::UnitPixel); 
    Font oF1200(&oFamily, 12.00, FontStyle::FontStyleBold, Unit::UnitPixel); 
    Font oF1500(&oFamily, 15.00, FontStyle::FontStyleBold, Unit::UnitPixel); 
    Font oF1648(&oFamily, 16.48, FontStyle::FontStyleBold, Unit::UnitPixel); 
    Font oF1649(&oFamily, 16.49, FontStyle::FontStyleBold, Unit::UnitPixel); 
#else // Use regular 
    Font oF600(&oFamily, 6.00, FontStyle::FontStyleRegular, Unit::UnitPixel); 
    Font oF800(&oFamily, 8.00, FontStyle::FontStyleRegular, Unit::UnitPixel); 
    Font oF848(&oFamily, 8.48, FontStyle::FontStyleRegular, Unit::UnitPixel); 
    Font oF849(&oFamily, 8.49, FontStyle::FontStyleRegular, Unit::UnitPixel); 
    Font oF1200(&oFamily, 12.00, FontStyle::FontStyleRegular, Unit::UnitPixel); 
    Font oF1500(&oFamily, 15.00, FontStyle::FontStyleRegular, Unit::UnitPixel); 
    Font oF1648(&oFamily, 16.48, FontStyle::FontStyleRegular, Unit::UnitPixel); 
    Font oF1649(&oFamily, 16.49, FontStyle::FontStyleRegular, Unit::UnitPixel); 
#endif 

    assert(oF600.GetLastStatus() == Ok); // Make sure font is OK 

    SolidBrush oBrush(g_oTextColor); 

    double dy = 1.0; 
    oGraph.DrawString(L"Size 6.00", -1, &oF600, PointF(30.0, dy += 18.0), &oBrush); 
    oGraph.DrawString(L"Size 8.00", -1, &oF800, PointF(30.0, dy += 18.0), &oBrush); 
    oGraph.DrawString(L"Size 8.48", -1, &oF848, PointF(30.0, dy += 18.0), &oBrush); 
    oGraph.DrawString(L"Size 8.49", -1, &oF849, PointF(30.0, dy += 18.0), &oBrush); 
    oGraph.DrawString(L"Size 12.00", -1, &oF1200, PointF(30.0, dy += 18.0), &oBrush); 
    oGraph.DrawString(L"Size 15.00", -1, &oF1500, PointF(30.0, dy += 18.0), &oBrush); 
    oGraph.DrawString(L"Size 16.48", -1, &oF1648, PointF(30.0, dy += 18.0), &oBrush); 
    oGraph.DrawString(L"Size 16.49", -1, &oF1649, PointF(30.0, dy += 18.0), &oBrush); 

#ifndef USE_LAYERED_WINDOW 
    return; 
#endif 

    // Do da layered window magic stuff 
    BLENDFUNCTION oBF = { 0 }; 
    oBF.BlendOp = AC_SRC_OVER; 
    oBF.BlendFlags = 0; 
    oBF.SourceConstantAlpha = 255; 
    oBF.AlphaFormat = AC_SRC_ALPHA; 

    SIZE oSize = { 0 }; 
    oSize.cx = g_iWidth; 
    oSize.cy = g_iHeight; 

    POINT oPTZero = { 0 }; 

    RECT oRect = { 0 }; 
    ::GetWindowRect(g_hWndGdiPlus, &oRect); 

    POINT oPTWnd = { 0 }; 

    oPTWnd.x = oRect.left; 
    oPTWnd.y = oRect.top; 

    //HDC hDC = oGraph.GetHDC(); 
    BOOL bOK = ::UpdateLayeredWindow(g_hWndGdiPlus, 
     NULL, //HDC hdcDst, 
     &oPTWnd, // POINT &oPtNull, 
     &oSize, // SIZE *psize, 
     hOff, // HDC hdcSrc, 
     &oPTZero, // POINT *pptSrc, 
     RGB(255,255,255), // COLORREF crKey, 
     &oBF, // BLENDFUNCTION *pblend, 
     ULW_ALPHA // DWORD dwFlags 
    ); 
} // Draw 

void MsgLoop() 
{ 
    ::SetTimer(g_hWndGdiPlus, 0, 19999, NULL); // Self-destruct timer 

    MSG msg = { 0 }; 
    while (::GetMessage(&msg, NULL, 0, 0)) 
    { 
      ::TranslateMessage(&msg); 
      ::DispatchMessage(&msg); 
    } 
} // MsgLoop 

void RegWndClass() 
{ 

     WNDCLASSEX wcex = { 0 }; 

     wcex.cbSize   = sizeof(WNDCLASSEX); 
     wcex.style   = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; 
     wcex.lpfnWndProc  = WndProc; 
     wcex.cbClsExtra  = 0; 
     wcex.cbWndExtra  = 8; // 8 bytes, to allow for 64-bit architecture 
     wcex.hInstance  = NULL; // CHECK 
     wcex.hIcon   = NULL; 
     wcex.hCursor   = ::LoadCursor(NULL, IDC_ARROW); 
     wcex.hbrBackground = (HBRUSH)NULL_BRUSH; // CHECK 
     wcex.lpszMenuName = NULL; 
     wcex.lpszClassName = g_pWndClass; 
     wcex.hIconSm   = NULL; 

     g_iWndClass = ::RegisterClassEx(&wcex); 
} // RegWndClass 

LRESULT CALLBACK WndProc(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam) 
{ 
    switch(uiMsg) 
    { 
     case WM_TIMER: 
     { 
      std::wstring s; 
      std::wcout << L"Let´s quit" ; 
      ::PostQuitMessage(0); 
      return 0; 
     } 
     case WM_PAINT: 
      Draw(); 
      break; 

     default: 
     { 
      return DefWindowProc(hWnd, uiMsg, wParam, lParam); 
     } 
    } 
    return DefWindowProc(hWnd, uiMsg, wParam, lParam); 
} // WndProc 

[編輯]問題解決了! 以下代碼根據Rodrogo´s優秀建議。 榮譽和對他的巨大感謝。我很感激。

所有編輯都標有//#MOD

// Create as a console application project 
// + Unicode charset 
// + Precompiled headers off 
// + make sure to add linker input: gdiplus.lib 

#ifndef _WIN32_WINNT  // Allow use of features specific to Windows XP or later.     
#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows. 
#endif      

// Standard stuff 
#include <stdio.h> 
#include <tchar.h> 
#include <windows.h> 
#include <iostream> 
#include <cassert> 

// GDI+ stuff 
#include <Gdiplus.h> 
using namespace Gdiplus; 
GdiplusStartupInput g_oGdiPlusStartupInput; 
ULONG_PTR g_pGdiPlusToken = NULL; 




// #*#*#*#*#*#*#*#*# LINES TO CHANGE ---------->---------->----------> 
Color g_oTextColor(255, 240, 0, 0); // Simply change Color to (254, 240, 0, 0) [to add slight transparency] and everything will work! 
#define USE_LAYERED_WINDOW // or just omment this line [to use a regular window], and everything will work! 






// Forward declarations 
void RegWndClass(); 
LRESULT CALLBACK WndProc(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam); 
void CreateWindows(); 
void Draw(); 
void MsgLoop(); 

// Other Globals 
ATOM g_iWndClass = 0; 
HWND g_hWndGdiPlus = NULL; 
HWND g_hWndGdi = NULL; 
const wchar_t* g_pWndClass = L"TST"; 
int g_iWidth = 200; 
int g_iHeight = 200; 

// Main entry-point 
int _tmain(int argc, _TCHAR* argv[]) 
{ 
    GdiplusStartup(&g_pGdiPlusToken, &g_oGdiPlusStartupInput, NULL); 

    RegWndClass(); 
    CreateWindows(); 
    Draw(); 

    MsgLoop(); 

    ::UnregisterClass(g_pWndClass, NULL); 
    ::Sleep(500); 


    GdiplusShutdown(g_pGdiPlusToken); 

    return 0; 
} // _tmain 

void CreateWindows() 
{ 
#ifdef USE_LAYERED_WINDOW 
     // The key trick is to create a window with style WS_EX_LAYERED, but WITHOUT any subsequent calls to SetLayeredWindowAttributes() 
     // This gives us a magic window that must be updated with UpdateLayeredWindow() (and it does NOT recieve any WM_PAINT messages) 
     // as brilliantly described in: http://alexkr.com/source-code/50/layered-windows-and-updatelayeredwindow/ 
     g_hWndGdiPlus = ::CreateWindowEx(WS_EX_LAYERED, g_pWndClass, L"", WS_POPUP | WS_VISIBLE, 1000, 200, g_iWidth, g_iHeight, NULL, NULL, NULL, NULL); 
#else 
     g_hWndGdiPlus = ::CreateWindowEx(0, g_pWndClass, L"", WS_OVERLAPPEDWINDOW | WS_POPUP | WS_VISIBLE, 1000, 200, g_iWidth, g_iHeight, NULL, NULL, NULL, NULL); 
#endif 

    //g_hWndGdi = ::CreateWindowEx(WS_EX_LAYERED, g_pWndClass, L"", WS_POPUP | WS_VISIBLE, 720, 500, 200, 200, NULL, NULL, NULL, NULL); 

} // CreateWindows 

void Draw() 
{ 
    // Init GDI+ surface 
    HDC hOff = ::CreateCompatibleDC(NULL); 
    Bitmap oDaBigOne(g_iWidth, g_iHeight, PixelFormat32bppARGB); 
    HBITMAP hBMit = NULL; 
    Color oCol(0, 0, 0, 0); 
    // oDaBigOne.GetHBITMAP(oCol, &hBMit); //#MOD 
    // HGDIOBJ hSave = ::SelectObject(hOff, hBMit); //#MOD 


    { // Limit oGraph scope //#MOD 
#ifdef USE_LAYERED_WINDOW 
     //Graphics oGraph(hOff); //#MOD 
     Graphics oGraph(&oDaBigOne); //#MOD 
#else 
     Graphics oGraph(g_hWndGdiPlus); 
#endif 

    oGraph.Clear(Color(255, 55, 155, 255)); 

    // Draw text 
    oGraph.SetTextRenderingHint(TextRenderingHintAntiAliasGridFit); 
    oGraph.SetCompositingMode(CompositingModeSourceOver); 
    oGraph.SetCompositingQuality(CompositingQualityHighQuality); 
    oGraph.SetPixelOffsetMode(PixelOffsetModeHighQuality); 

    const FontFamily oFamily(L"Tahoma", NULL); 

#if 1 // Use bold 
    Font oF600(&oFamily, 6.00, FontStyle::FontStyleBold, Unit::UnitPixel); 
    Font oF848(&oFamily, 8.48, FontStyle::FontStyleBold, Unit::UnitPixel); 
    Font oF849(&oFamily, 8.49, FontStyle::FontStyleBold, Unit::UnitPixel); 
    Font oF1200(&oFamily, 12.00, FontStyle::FontStyleBold, Unit::UnitPixel); 
    Font oF1500(&oFamily, 15.00, FontStyle::FontStyleBold, Unit::UnitPixel); 
    Font oF1648(&oFamily, 16.48, FontStyle::FontStyleBold, Unit::UnitPixel); 
    Font oF1649(&oFamily, 16.49, FontStyle::FontStyleBold, Unit::UnitPixel); 
#else // Use regular 
    Font oF600(&oFamily, 6.00, FontStyle::FontStyleRegular, Unit::UnitPixel); 
    Font oF848(&oFamily, 8.48, FontStyle::FontStyleRegular, Unit::UnitPixel); 
    Font oF849(&oFamily, 8.49, FontStyle::FontStyleRegular, Unit::UnitPixel); 
    Font oF1200(&oFamily, 12.00, FontStyle::FontStyleRegular, Unit::UnitPixel); 
    Font oF1500(&oFamily, 15.00, FontStyle::FontStyleRegular, Unit::UnitPixel); 
    Font oF1648(&oFamily, 16.48, FontStyle::FontStyleRegular, Unit::UnitPixel); 
    Font oF1649(&oFamily, 16.49, FontStyle::FontStyleRegular, Unit::UnitPixel); 
#endif 

    assert(oF600.GetLastStatus() == Ok); // Make sure font is OK 

    SolidBrush oBrush(g_oTextColor); 

    double dy = 10.0; 
    oGraph.DrawString(L"Size 6.00", -1, &oF600, PointF(30.0, dy += 18.0), &oBrush); 
    oGraph.DrawString(L"Size 8.48", -1, &oF848, PointF(30.0, dy += 18.0), &oBrush); 
    oGraph.DrawString(L"Size 8.49", -1, &oF849, PointF(30.0, dy += 18.0), &oBrush); 
    oGraph.DrawString(L"Size 12.00", -1, &oF1200, PointF(30.0, dy += 18.0), &oBrush); 
    oGraph.DrawString(L"Size 15.00", -1, &oF1500, PointF(30.0, dy += 18.0), &oBrush); 
    oGraph.DrawString(L"Size 16.48", -1, &oF1648, PointF(30.0, dy += 18.0), &oBrush); 
    oGraph.DrawString(L"Size 16.49", -1, &oF1649, PointF(30.0, dy += 18.0), &oBrush); 

#ifndef USE_LAYERED_WINDOW 
    return; 
#endif 
    } // Limit oGraph scope //#MOD 

    // Do da layered window magic stuff 
    BLENDFUNCTION oBF = { 0 }; 
    oBF.BlendOp = AC_SRC_OVER; 
    oBF.BlendFlags = 0; 
    oBF.SourceConstantAlpha = 255; 
    oBF.AlphaFormat = AC_SRC_ALPHA; 

    SIZE oSize = { 0 }; 
    oSize.cx = g_iWidth; 
    oSize.cy = g_iHeight; 

    POINT oPTZero = { 0 }; 

    RECT oRect = { 0 }; 
    ::GetWindowRect(g_hWndGdiPlus, &oRect); 

    POINT oPTWnd = { 0 }; 

    oPTWnd.x = oRect.left; 
    oPTWnd.y = oRect.top; 

    oDaBigOne.GetHBITMAP(oCol, &hBMit); //#MOD 
    HGDIOBJ hSave = ::SelectObject(hOff, hBMit); //#MOD 

    //HDC hDC = oGraph.GetHDC(); 
    BOOL bOK = ::UpdateLayeredWindow(g_hWndGdiPlus, 
     NULL, //HDC hdcDst, 
     &oPTWnd, // POINT &oPtNull, 
     &oSize, // SIZE *psize, 
     hOff, // HDC hdcSrc, 
     &oPTZero, // POINT *pptSrc, 
     RGB(255,255,255), // COLORREF crKey, 
     &oBF, // BLENDFUNCTION *pblend, 
     ULW_ALPHA // DWORD dwFlags 
    ); 
} // Draw 

void MsgLoop() 
{ 
    ::SetTimer(g_hWndGdiPlus, 0, 19999, NULL); // Self-destruct timer 

    MSG msg = { 0 }; 
    while (::GetMessage(&msg, NULL, 0, 0)) 
    { 
      ::TranslateMessage(&msg); 
      ::DispatchMessage(&msg); 
    } 
} // MsgLoop 

void RegWndClass() 
{ 

     WNDCLASSEX wcex = { 0 }; 

     wcex.cbSize   = sizeof(WNDCLASSEX); 
     wcex.style   = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; 
     wcex.lpfnWndProc  = WndProc; 
     wcex.cbClsExtra  = 0; 
     wcex.cbWndExtra  = 8; // 8 bytes, to allow for 64-bit architecture 
     wcex.hInstance  = NULL; // CHECK 
     wcex.hIcon   = NULL; 
     wcex.hCursor   = ::LoadCursor(NULL, IDC_ARROW); 
     wcex.hbrBackground = (HBRUSH)NULL_BRUSH; // CHECK 
     wcex.lpszMenuName = NULL; 
     wcex.lpszClassName = g_pWndClass; 
     wcex.hIconSm   = NULL; 

     g_iWndClass = ::RegisterClassEx(&wcex); 
} // RegWndClass 

LRESULT CALLBACK WndProc(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam) 
{ 
    switch(uiMsg) 
    { 
     case WM_TIMER: 
     { 
      std::wstring s; 
      std::wcout << L"Let´s quit" ; 
      ::PostQuitMessage(0); 
      return 0; 
     } 
     case WM_PAINT: 
      Draw(); 
      break; 

     default: 
     { 
      return DefWindowProc(hWnd, uiMsg, wParam, lParam); 
     } 
    } 
    return DefWindowProc(hWnd, uiMsg, wParam, lParam); 
} // WndProc 

回答

6

我覺得現在的問題是,GDI(不+)不支持Alpha透明度很好。充其量,它保持alpha通道不變。

當您使用具有alpha通道的選定位圖的HDC構建圖形對象時......事情會混淆不清。我的猜測是,GDI +字體柵格化決定了基於大量參數使用哪種方法進行渲染;那麼,如果這個方法恰好在GDI中被支持,它將被使用(並且alpha通道被忽略)。如果渲染方法在GDI中不受支持,則它將回退到逐像素渲染或類似方式,並且Alpha通道將正確使用。

因此,要獲得正確的結果,您不應該使用HDC來修改Alpha通道。請嘗試以下變化:

  • 使用位圖來創建圖形對象,而不是HDC:

    Graphics oGraph(&oDaBigOne); 
    
  • 選擇位圖到HDC霍夫渲染已經完成之後。可以肯定的是,Graphics對象被銷燬會更好,它的範圍限制在{...}之內。

[編輯]

新代碼後,該解決方案很簡單:不僅是你應該圖紙後移動調用選擇對象(),也GetBitmap()。也就是說,這兩個功能建議立即進行刪除只是調用之前:UpdateLayeredWindow():

oDaBigOne.GetHBITMAP(oCol, &hBMit); 
HGDIOBJ hSave = ::SelectObject(hOff, hBMit); 
+0

THX!聽起來不錯。恐怕本週不能嘗試這個,但我會遲一點。併發布反饋。乾杯。 – Adam 2011-08-09 06:30:18

+0

羅德里戈,其實我找了一點時間來嘗試一下。對不起,沒有雪茄......如果我沒有選擇DC,則GDI +操作將呈現:無。 (事實上​​ - 我意識到 - 很久以前,我已經嘗試了這一點,正如上面的「側面問題#1」所暗示的那樣)。所以我仍然有問題的GDI +渲染出錯的一些字體大小的Tahoma。還有待嘗試的是一種純粹的GDI方法,如以下答覆中所述:http://www.gamedev.net/topic/333453-32-bit-alpha-bitmaps-and-gdi-fun-alert/ – Adam 2011-08-09 08:00:54

+0

好奇,但我試過了,它爲我工作。你能用這種方法發佈代碼嗎?或者,如果你願意,我可以發佈我的;-) – rodrigo 2011-08-09 13:45:28

0

嘗試用PixelFormat32bppPARGB更換PixelFormat32bppARGBBLENDFUNCTION結構的文檔聲明它需要在源中預乘alpha。

+0

非常感謝,但我已經嘗試過了。不幸的是,那裏運氣不好。 – Adam 2011-08-01 09:50:45

1

我一時無法找到這種奇怪行爲的解釋。不過,我也發現,使用默認渲染值給出了一些字體效果好得多,具有以下設置嘗試Arial字體:

oGraph.SetTextRenderingHint(TextRenderingHintAntiAliasGridFit); 
oGraph.SetPixelOffsetMode(PixelOffsetModeDefault); 
oGraph.SetCompositingMode(CompositingModeSourceOver); 
oGraph.SetCompositingQuality(CompositingQualityDefault); 
2

我想,我找到了一個(部分)解決了這個昨天,這可能是更容易實現,一個比由rodrigo建議:您可以簡單地指定StringFormatFlags::StringFormatFlagsBypassGDI作爲StringFormat中的格式標誌 - 您傳遞給DrawString的例程中,並且瞧:所有內容都使用具有alpha功能的font-renderer繪製。這修復了alpha通道問題,至少...