http://bugs.winehq.org/show_bug.cgi?id=6842
Summary: DrawFocusRect code correction Product: Wine Version: 0.9 Platform: Other OS/Version: other Status: UNCONFIRMED Severity: enhancement Priority: P5 Component: wine-user AssignedTo: wine-bugs@winehq.org ReportedBy: wine.severach@spamgourmet.com
Here are the code excerpts for the most correct and fastest implementation of DrawFocusRect. The performance is not substantially slower with caching disabled so for simplicity you may not want to implement caching right away.
#define HBR_CACHE (TRUE) // set to TRUE to enable caching, FALSE to disable caching #if HBR_CACHE HBRUSH g_hbrushFocus=NULL; #else #define g_hbrushFocus hbrushFocus // Define this to disable caching #endif
// ...
BOOL fResult=FALSE; #if 1 HBRUSH hbrushOld; #if !HBR_CACHE HBRUSH hbrushFocus; #endif if (!HBR_CACHE || !g_hbrushFocus) { // caching the pattern allows us to exactly match the performance of DrawFocusRect(). static const unsigned char aBitPixels[]={0x55,0,0xAA,0,0x55,0,0xAA,0,0x55,0,0xAA,0,0x55,0,0xAA,0}; HBITMAP hbitmapFocus=CreateBitmap(8,8,1,1,&aBitPixels); // sizes other than 8x8 are always slower and can be less compatible g_hbrushFocus=CreatePatternBrush(hbitmapFocus); // SetTextColor/SetBkColor are what's used here DeleteBitmap(hbitmapFocus); } hbrushOld=SelectObject(hdc,g_hbrushFocus); if (hbrushOld) { HRGN hrgnFocus=CreateRectRgn(prc->left,prc->top,prc->right,prc->bottom); // this can't be cached because every caller has a different size rectangle. Besides we're already matching the speed of the real DrawFocusRect HRGN hrgnInner=CreateRectRgn(prc->left+1,prc->top+1,prc->right-1,prc->bottom-1); CombineRgn(hrgnFocus,hrgnFocus,hrgnInner,RGN_DIFF); DeleteRgn(hrgnInner); SelectObject(hdc,hrgnFocus); fResult=PatBlt(hdc, prc->left, prc->top, prc->right-prc->left, prc->bottom-prc->top,PATINVERT); // 4 PatBlt without a clip region are slower and will not produce the correct right/bottom transitions DeleteRgn(hrgnFocus); SelectObject(hdc,hbrushOld); SelectClipRgn(hdc,NULL); } #if !HBR_CACHE DeleteBrush(hbrushFocus); // for caching this is done in WM_DESTROY #endif
// ...
#if HBR_CACHE case WM_DESTROY: if (g_hbrushFocus) DeleteBrush(g_hbrushFocus); break; #endif