GDI+ font rendering (and layered windows)

来源:互联网 发布:star走心机编程 编辑:程序博客网 时间:2024/05/22 16:16

原址:http://www.codeproject.com/Questions/182071/GDI-font-rendering-and-layered-windows


使用GDI+绘制字体并使用UpdateLayeredWindow更新窗口时,半透明问题,解决方案是将alpha设置为254

// 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; #pragma comment(lib, "gdiplus.lib")// #*#*#*#*#*#*#*#*# 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 declarationsvoid RegWndClass();LRESULT CALLBACK WndProc( HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam );void CreateWindows();void Draw();void MsgLoop(); // Other GlobalsATOM 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-pointint _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;} // _tmainvoid 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 ); } // CreateWindowsvoid 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    );} // Drawvoid MsgLoop(){    ::SetTimer( g_hWndGdiPlus, 0, 19999, NULL ); // Self-destruct timer    MSG msg = { 0 };    while ( ::GetMessage( &msg, NULL, 0, 0 ) )    {            ::TranslateMessage(&msg);            ::DispatchMessage(&msg);    }} // MsgLoopvoid 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);} // RegWndClassLRESULT 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


0 0
原创粉丝点击