ClearType会破坏透明度 [英] ClearType ruins transparency
问题描述
我有一个位图,其背景需要替换为另一个位图的一部分。一切正常,直到我在 WindowsXP 上启用 ClearFont 。
为了更好地解释我的问题,让我们将第一个位图标记为 bmpDestination
,然后将第二个位图标记为 bmpSource
。
此处 [ ^ ]是 bmpSource
的样子。
这里 [ ^ ]是 bmpDestination
的样子。
和此处 [ ^ ClearType 打开时,>]是他们合并的错误结果。
ClearType 改变了某些部分文字背景颜色,所以它们不是白色的不再( RGB(255,255,255)
)但是白色和文字颜色的组合。
我我正在使用 BitBlt()
和单色位图来创建掩码,并模拟透明度。我也尝试过使用 TransparentBlt()
,但结果相同。
如何组合 bmpSource
和 bmpDestination
,当启用 ClearType 时,我可以创建正确的结果吗?
感谢您的帮助。
祝你好运。
I have a bitmap which background needs to be replaced with part of another bitmap. Everything works fine until I enable ClearFont on my WindowsXP.
In order to explain my problem better, let us label first bitmap as bmpDestination
and second as bmpSource
.
Here[^] is how the bmpSource
looks like.
Here[^] is how bmpDestination
looks like.
And here[^] is the incorrect result of their combining when ClearType is on.
ClearType alters some parts of the text background color, so they aren't white anymore ( RGB( 255, 255, 255 )
) but a combination of white and text color.
I am using BitBlt()
and monochrome bitmap to create a mask, and to simulate transparency. I have tried using TransparentBlt()
too, but got the same result.
How can I combine bmpSource
and bmpDestination
, when ClearType is enabled, so I can create correct result ?
Thank you for your help.
Best regards.
推荐答案
我把它添加到你以前的帖子里它很乱,所以你可能错过了它。
有很多方法可以解决它但它们都很慢并且有所不同您必须在两者之间进行选择的结果。没有完美的解决方案,因为它是Windows Cleartype实现中的一个错误或过度瞄准。
我玩过,我得出了与此作者完全相同的结论< br $> b $ b
http://theartofdev.wordpress.com/2014/04/21/text-rendering-methods-comparison-or-gdi-vs-gdi-revised/ [ ^ ]
I added this to your previous post it got messy so you probably missed it.
There are ways around it but they are all slow and give different results which you have to choose between. There is no perfect solution because it is a bug or over-sight in windows Cleartype implementation.
I played around and I came to the exact same conclusions as this author
http://theartofdev.wordpress.com/2014/04/21/text-rendering-methods-comparison-or-gdi-vs-gdi-revised/[^]
Conclusions
-GDI text rendering provides the best visual quality but doesn’t support transparent background.
-Native GDI rendering provides the best performance.
-GDI+ with anti-aliasing and typographic format provides the best performance and visual quality for transparent background rendering.
-GraphicsPath rendering method visual quality4 and performance is disappointing.
-Text rendered in each rendering method is visually different.
-As Microsoft will improve their fonts and display resolution (DPI) will raise, GDI+ text rendering will improve to a point where GDI has no significant visual benefit.
>
I have studied carefully the code from your previous answer and managed to handle WM_WINDOWPOSCHANGED properly for multiple windows but I can not handle slight flickering.
造成闪烁的原因是列表框绘制每个项目的方式,你需要自己绘图来解决问题,列表框上有很多文章闪烁并解决它。
如果您需要窗口,可以直接添加字体...所以让我们看看具体的代码。
首先创建一个文本字符串,我们将在FONT中调用该属性
What is causing the flicker is the way the listbox draws each item you need to do you own drawing to solve the problem there are plenty of articles on listbox flicker and solving it.
Ok to do the font simply attach the font if you need to the window .. so lets look at specific code.
First make a text string we are going to call the property in out case "FONT"
//this is the property title of the FONT to attach to our window
#define TEXTPROP TEXT("FONT")
下一个句柄WM_FONT
Next handle WM_FONT
case WM_SETFONT:
LOGFONT lf;
HFONT OldFont, Newfont;
GetObject((HFONT)wParam, sizeof(lf), &lf); // Get proposed font
if (lf.lfQuality != NONANTIALIASED_QUALITY){ // If its antialiased we can't use
lf.lfQuality = NONANTIALIASED_QUALITY; // So change it to non antialiased
Newfont = CreateFontIndirect(&lf); // Create a new font
OldFont = (HFONT) GetProp(hwnd, TEXTPROP); // Get the old font
if (OldFont != 0) DeleteObject(OldFont); // If valid delete it
SetProp(hwnd, TEXTPROP, (HANDLE)Newfont); // Set new font to window property
} else Newfont = (HFONT) wParam; // Use the font provided
return ::DefSubclassProc( hwnd, WM_SETFONT, (WPARAM)Newfont, lParam); // Treat it as usual
你有责任删除在NCDESTROY中创建的任何字体WM_SETFONT
Your responsibility to delete any font WM_SETFONT created in NCDESTROY
case WM_NCDESTROY:
HFONT Font = (HFONT) GetProp(hwnd, TEXTPROP); // Fetch the font property
if (Font != 0) DeleteObject(Font); // If valid delete the font
RemoveProp(hwnd, TEXTPROP); // Remove the window property
::RemoveWindowSubclass(hwnd, TreeProc, 0 );
return ::DefSubclassProc( hwnd, message, wParam, lParam);
它现在像任何普通窗口一样处理WM_FONT 。
最后我将所有创作内容放入辅助函数中
It now handles the WM_FONT like any normal window.
Finally I put all the creation stuff into a helper function
// ** LdB Consolidate function to create a listbox and do all the repeat stuff
HWND CreateListBox (HWND parent, // Parent window to insert this control in
TCHAR* title, // List box title text
int x, int y, // x,y co-ordinate of parent for the insert
int cx, int cy, // Width and Height of the control
int id, // Id of the control
HFONT hFont) { // Handle to any special font (0 = default)
DWORD dwStyle;
HWND TreeView;
TreeView = CreateWindowEx(0, WC_TREEVIEW, title,
WS_VISIBLE | WS_CHILD | WS_BORDER
| TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT,
x, y, cx, cy, parent, (HMENU)id, 0, NULL);
dwStyle = GetWindowLong( TreeView , GWL_STYLE);
dwStyle |= TVS_CHECKBOXES;
SetWindowLongPtr( TreeView , GWL_STYLE, dwStyle );
SetWindowSubclass( TreeView, TreeProc, 0, 0 );
TreeView_SetBkColor(TreeView, RGB(0xFF, 0, 0xFF));
// This checks font is not aliased by our handling of WM_FONT
if (hFont == 0) hFont = (HFONT) SendMessage(TreeView, WM_GETFONT, 0, 0);
SendMessage(TreeView, WM_SETFONT, (WPARAM)hFont, FALSE);
return (TreeView);
};
你的创作现在看起来很简单
Your creation now looks this simple
HWND TreeView = CreateListBox(hwnd, (TCHAR*)TEXT("Tree View"),
50, 10, 200, 200, ID_LISTBOX, 0);
哦,我忘记了我进一步改进了你的重绘并使其符合处理WM_PRINTCLIENT本身。
Oh I forgot I further improved your redraw and made it compliant to handling WM_PRINTCLIENT itself.
case WM_PAINT:
{
// usual stuff
PAINTSTRUCT ps;
HDC hdc = BeginPaint( hwnd, &ps );
// Simply get printclient to paint
::SendMessage(hwnd, WM_PRINTCLIENT,(WPARAM) hdc, (LPARAM)(PRF_CLIENT) );
EndPaint( hwnd, &ps );
}
return 0L;
case WM_PRINTCLIENT:
{
BITMAPINFO bmi;
// Get parent client co-ordinates
RECT rc;
GetClientRect(GetParent(hwnd), &rc);
// Create a memory DC
HDC memDC = CreateCompatibleDC(0);
// Create a DIB header for parent
memset(&bmi, 0, sizeof(bmi));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = rc.right - rc.left;
bmi.bmiHeader.biHeight = rc.bottom - rc.top;
bmi.bmiHeader.biBitCount = 24;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biCompression = BI_RGB;
// Create a DIB bitmap
HBITMAP tempBmp = CreateDIBSection(0, &bmi, DIB_RGB_COLORS, 0, 0, 0);
// Select tempBmp onto DC to force size and DIB change on the DC
SelectObject(memDC, tempBmp );
// Put parent background on our memory DC
::SendMessage( GetParent(hwnd), WM_PRINTCLIENT, (WPARAM) memDC, (LPARAM)(PRF_CLIENT));
// Now we can dispose of the DIB bitmap no longer needed
DeleteObject(tempBmp);
// map tree's coordinates to parent window
POINT ptTreeUL;
ptTreeUL.x = 0;
ptTreeUL.y = 0;
ClientToScreen( hwnd, &ptTreeUL );
ScreenToClient( GetParent(hwnd), &ptTreeUL );
GetClientRect( hwnd, &rc);
// Transfer parent background to given DC
BitBlt((HDC)wParam, 0, 0, rc.right-rc.left, rc.bottom-rc.top,
memDC, ptTreeUL.x, ptTreeUL.y, SRCCOPY );
// Okay get treeview to draw on our memory DC
DefSubclassProc(hwnd, WM_PRINTCLIENT, (WPARAM)memDC, (LPARAM)(PRF_CLIENT));
// Transfer the treeview DC onto finalDC excluding pink
TransparentBlt((HDC)wParam, 0, 0, rc.right - rc.left, rc.bottom - rc.top,
memDC, 0, 0, rc.right - rc.left, rc.bottom - rc.top, RGB(0xFF, 0x00, 0xFF));
// Finished with MemDC
DeleteObject(memDC);
return (0);
}
这篇关于ClearType会破坏透明度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!