# HG changeset patch # User bsmith@81767d24-ef19-dc11-ae90-00e081727c95 # Date 1326388891 0 # Node ID a71ec02f3b70e3ce0869cfd528bd01a084b39240 # Parent 2913bb58f439c5e4f7035aad55c4fb5ed9e9c449 Attempt on Windows using DrawThemeTextEx to nicely display text widgets on glass backgrounds. It mostly works but due to using the transparency key it doesn't really look mixed with the glass. More work needs to be done. diff -r 2913bb58f439 -r a71ec02f3b70 win/dw.c --- a/win/dw.c Wed Jan 11 05:36:00 2012 +0000 +++ b/win/dw.c Thu Jan 12 17:21:31 2012 +0000 @@ -107,9 +107,15 @@ #ifdef AEROGLASS HRESULT (WINAPI *_DwmExtendFrameIntoClientArea)(HWND hWnd, const MARGINS *pMarInset) = 0; HRESULT (WINAPI *_DwmIsCompositionEnabled)(BOOL *pfEnabled) = 0; +HTHEME (WINAPI *_OpenThemeData)(HWND hwnd, LPCWSTR pszClassList); +HPAINTBUFFER (WINAPI *_BeginBufferedPaint)(HDC hdcTarget, const RECT *prcTarget, BP_BUFFERFORMAT dwFormat, BP_PAINTPARAMS *pPaintParams, HDC *phdc); +HRESULT (WINAPI *_BufferedPaintSetAlpha)(HPAINTBUFFER hBufferedPaint, const RECT *prc, BYTE alpha); +HRESULT (WINAPI *_DrawThemeTextEx)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwFlags, LPRECT pRect, const DTTOPTS *pOptions); +HRESULT (WINAPI *_EndBufferedPaint)(HPAINTBUFFER hBufferedPaint, BOOL fUpdateTarget); +HRESULT (WINAPI *_CloseThemeData)(HTHEME hTheme); BOOL _dw_composition = FALSE; COLORREF _dw_transparencykey = RGB(200,201,202); -HANDLE hdwm = 0; +HANDLE hdwm = 0, huxtheme = 0; #endif /* @@ -3266,6 +3272,144 @@ return DefWindowProc(hwnd, msg, mp1, mp2); } +#ifdef AEROGLASS +/* Window procedure to handle drawing themed text when in composited mode */ +BOOL CALLBACK _staticwndproc(HWND hwnd, ULONG msg, WPARAM mp1, LPARAM mp2) +{ + ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(hwnd, GWLP_USERDATA); + WNDPROC pOldProc; + + if (!cinfo) + return DefWindowProc(hwnd, msg, mp1, mp2); + + /* If we don't require themed drawing */ + if(cinfo->back != -1 && !_dw_composition || !(GetWindowLongPtr(_toplevel_window(hwnd), GWL_EXSTYLE) & WS_EX_LAYERED)) + return _colorwndproc(hwnd, msg, mp1, mp2); + + pOldProc = cinfo->pOldProc; + + switch(msg) + { + case WM_PAINT: + { + PAINTSTRUCT ps; + HDC hdc = BeginPaint(hwnd, &ps); + + if(hdc) + { + /* Figure out how to draw */ + HDC hdcPaint = NULL; + RECT rcClient; + LONG_PTR dwStyle = GetWindowLongPtr(hwnd, GWL_STYLE); + LONG_PTR dwStyleEx = GetWindowLongPtr(hwnd, GWL_EXSTYLE); + HTHEME hTheme = _OpenThemeData(NULL, L"ControlPanelStyle"); + + GetClientRect(hwnd, &rcClient); + + if(hTheme) + { + /* Create an in memory image to draw to */ + HPAINTBUFFER hBufferedPaint = _BeginBufferedPaint(hdc, &rcClient, BPBF_TOPDOWNDIB, NULL, &hdcPaint); + + if(hdcPaint) + { + LONG_PTR dwStaticStyle = dwStyle & 0x1F; + HFONT hFontOld = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0); + int iLen = GetWindowTextLength(hwnd), fore = _internal_color(cinfo->fore); + DTTOPTS DttOpts = { sizeof(DTTOPTS) }; + static HBRUSH hbrush = 0; + + /* Make sure we have a transparency brush */ + if(!hbrush) + hbrush = CreateSolidBrush(_dw_transparencykey); + + /* Fill the background with the transparency color */ + FillRect(hdcPaint, &rcClient, hbrush); + _BufferedPaintSetAlpha(hBufferedPaint, &ps.rcPaint, 0x00); + + /* Setup how we will draw the text */ + DttOpts.dwFlags = DTT_COMPOSITED | DTT_GLOWSIZE | DTT_TEXTCOLOR; + DttOpts.crText = cinfo->fore == -1 ? RGB(255, 255, 255) : RGB(DW_RED_VALUE(fore), DW_GREEN_VALUE(fore), DW_BLUE_VALUE(fore)); + DttOpts.iGlowSize = 12; + + SetBkMode(hdcPaint, TRANSPARENT); + + if(hFontOld) + hFontOld = (HFONT)SelectObject(hdcPaint, hFontOld); + + /* Make sure there is text to draw */ + if(iLen) + { + LPWSTR szText = (LPWSTR)_alloca(sizeof(WCHAR)*(iLen+5)); + + if(szText) + { + iLen = GetWindowTextW(hwnd, szText, iLen+5); + if(iLen) + { + DWORD dwFlags = DT_WORDBREAK; + + switch (dwStaticStyle) + { + case SS_CENTER: + dwFlags |= DT_CENTER; + break; + case SS_RIGHT: + dwFlags |= DT_RIGHT; + break; + case SS_LEFTNOWORDWRAP: + dwFlags &= ~DT_WORDBREAK; + break; + } + + if(dwStyle & SS_CENTERIMAGE) + { + dwFlags |= DT_VCENTER; + dwFlags &= ~DT_WORDBREAK; + } + + + if(dwStyle & SS_ENDELLIPSIS) + dwFlags |= DT_END_ELLIPSIS|DT_MODIFYSTRING; + else if(dwStyle & SS_PATHELLIPSIS) + dwFlags |= DT_PATH_ELLIPSIS|DT_MODIFYSTRING; + else if(dwStyle & SS_WORDELLIPSIS) + dwFlags |= DT_WORD_ELLIPSIS|DT_MODIFYSTRING; + + if (dwStyleEx&WS_EX_RIGHT) + dwFlags |= DT_RIGHT; + + if(dwStyle & SS_NOPREFIX) + dwFlags |= DT_NOPREFIX; + + /* Draw the text! */ + _DrawThemeTextEx(hTheme, hdcPaint, 0, 0, + szText, -1, dwFlags, &rcClient, &DttOpts); + } + } + } + + /* Cleanup */ + if (hFontOld) + SelectObject(hdcPaint, hFontOld); + _EndBufferedPaint(hBufferedPaint, TRUE); + } + _CloseThemeData(hTheme); + } + } + + EndPaint(hwnd, &ps); + return TRUE; + } + break; + } + + if ( !pOldProc ) + return DefWindowProc(hwnd, msg, mp1, mp2); + return CallWindowProc(pOldProc, hwnd, msg, mp1, mp2); +} +#endif + /* Function: _BtProc * Abstract: Subclass procedure for buttons */ @@ -3715,15 +3859,25 @@ #endif #ifdef AEROGLASS - /* Attempt to load the Desktop Window Manager library */ - if((hdwm = LoadLibrary("dwmapi"))) + /* Attempt to load the Desktop Window Manager and Theme library */ + if((hdwm = LoadLibrary("dwmapi")) && (huxtheme = LoadLibrary("uxtheme"))) { _DwmExtendFrameIntoClientArea = (HRESULT (WINAPI *)(HWND, const MARGINS *))GetProcAddress(hdwm, "DwmExtendFrameIntoClientArea"); if((_DwmIsCompositionEnabled = (HRESULT (WINAPI *)(BOOL *))GetProcAddress(hdwm, "DwmIsCompositionEnabled"))) _DwmIsCompositionEnabled(&_dw_composition); - - } - + _OpenThemeData = (HTHEME (WINAPI *)(HWND, LPCWSTR))GetProcAddress(huxtheme, "OpenThemeData"); + _BeginBufferedPaint = (HPAINTBUFFER (WINAPI *)(HDC, const RECT *, BP_BUFFERFORMAT, BP_PAINTPARAMS *, HDC *))GetProcAddress(huxtheme, "BeginBufferedPaint"); + _BufferedPaintSetAlpha = (HRESULT (WINAPI *)(HPAINTBUFFER, const RECT *, BYTE))GetProcAddress(huxtheme, "BufferedPaintSetAlpha"); + _DrawThemeTextEx = (HRESULT (WINAPI *)(HTHEME, HDC, int, int, LPCWSTR, int, DWORD, LPRECT, const DTTOPTS *))GetProcAddress(huxtheme, "DrawThemeTextEx"); + _EndBufferedPaint = (HRESULT (WINAPI *)(HPAINTBUFFER, BOOL))GetProcAddress(huxtheme, "EndBufferedPaint"); + _CloseThemeData = (HRESULT (WINAPI *)(HTHEME))GetProcAddress(huxtheme, "CloseThemeData"); + } + /* In case of error close the library if needed */ + else if(hdwm) + { + FreeLibrary(hdwm); + hdwm = 0; + } #endif return 0; } @@ -5492,14 +5646,21 @@ { HWND tmp = CreateWindow(STATICCLASSNAME, text, - SS_NOPREFIX | SS_NOTIFY | - BS_TEXT | WS_VISIBLE | + SS_NOPREFIX | SS_NOTIFY | WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN, 0,0,0,0, DW_HWND_OBJECT, (HMENU)id, DWInstance, NULL); +#ifdef AEROGLASS + ColorInfo *cinfo = calloc(1, sizeof(ColorInfo)); + + cinfo->back = cinfo->fore = -1; + + cinfo->pOldProc = SubclassWindow(tmp, _staticwndproc); + SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)cinfo); +#endif dw_window_set_font(tmp, DefaultFont); dw_window_set_color(tmp, DW_CLR_DEFAULT, DW_RGB_TRANSPARENT); return tmp; @@ -5515,8 +5676,7 @@ { HWND tmp = CreateWindow(StatusbarClassName, text, - BS_TEXT | WS_VISIBLE | - WS_CHILD | WS_CLIPCHILDREN, + WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN, 0,0,0,0, DW_HWND_OBJECT, (HMENU)id, @@ -10379,6 +10539,7 @@ #ifdef AEROGLASS /* Free any in use libraries */ FreeLibrary(hdwm); + FreeLibrary(huxtheme); #endif exit(exitcode); }