您的位置:首页 > 其它

GDI+ font rendering (and layered windows)

2015-05-20 12:09 323 查看
原址: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 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: