LRESULT CALLBACK THEMING_ScrollbarSubclassProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, ULONG_PTR dwRefData) { TRACE("(%p, 0x%x, %lu, %lu, %lu)\n", hwnd, msg, wParam, lParam, dwRefData); return THEMING_CallOriginalClass (hwnd, msg, wParam, lParam); }
/********************************************************************** * The edit control subclass window proc. */ LRESULT CALLBACK THEMING_EditSubclassProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, ULONG_PTR dwRefData) { const WCHAR* themeClass = WC_EDITW; HTHEME theme; LRESULT result; switch (msg) { case WM_CREATE: result = THEMING_CallOriginalClass (hwnd, msg, wParam, lParam); OpenThemeData( hwnd, themeClass ); return result; case WM_DESTROY: theme = GetWindowTheme( hwnd ); CloseThemeData ( theme ); return THEMING_CallOriginalClass (hwnd, msg, wParam, lParam); case WM_THEMECHANGED: theme = GetWindowTheme( hwnd ); CloseThemeData ( theme ); OpenThemeData( hwnd, themeClass ); break; case WM_SYSCOLORCHANGE: theme = GetWindowTheme( hwnd ); if (!theme) return THEMING_CallOriginalClass (hwnd, msg, wParam, lParam); /* Do nothing. When themed, a WM_THEMECHANGED will be received, too, * which will do the repaint. */ break; case WM_NCPAINT: theme = GetWindowTheme( hwnd ); if (!theme) return THEMING_CallOriginalClass (hwnd, msg, wParam, lParam); nc_paint (theme, hwnd, (HRGN)wParam); break; case WM_ENABLE: case WM_KILLFOCUS: case WM_SETFOCUS: theme = GetWindowTheme( hwnd ); if (theme) RedrawWindow (hwnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW); return THEMING_CallOriginalClass (hwnd, msg, wParam, lParam); default: /* Call old proc */ return THEMING_CallOriginalClass (hwnd, msg, wParam, lParam); } return 0; }
/********************************************************************** * The dialog subclass window proc. */ LRESULT CALLBACK THEMING_DialogSubclassProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, ULONG_PTR dwRefData) { HTHEME theme = GetWindowTheme ( hWnd ); static const WCHAR themeClass[] = { 'W','i','n','d','o','w',0 }; BOOL themingActive = IsThemeDialogTextureEnabled (hWnd); BOOL doTheming = themingActive && (theme != NULL); LRESULT result; switch (msg) { case WM_CREATE: result = THEMING_CallOriginalClass (hWnd, msg, wParam, lParam); theme = OpenThemeData( hWnd, themeClass ); return result; case WM_DESTROY: CloseThemeData ( theme ); SetWindowTheme( hWnd, NULL, NULL ); OpenThemeData( hWnd, NULL ); return THEMING_CallOriginalClass (hWnd, msg, wParam, lParam); case WM_THEMECHANGED: CloseThemeData ( theme ); OpenThemeData( hWnd, themeClass ); InvalidateRect( hWnd, NULL, TRUE ); return 0; case WM_SYSCOLORCHANGE: if (!doTheming) return THEMING_CallOriginalClass (hWnd, msg, wParam, lParam); /* Do nothing. When themed, a WM_THEMECHANGED will be received, too, * which will do the repaint. */ break; case WM_ERASEBKGND: if (!doTheming) return THEMING_CallOriginalClass (hWnd, msg, wParam, lParam); { RECT rc; WNDPROC dlgp = (WNDPROC)GetWindowLongPtrW (hWnd, DWLP_DLGPROC); if (!CallWindowProcW(dlgp, hWnd, msg, wParam, lParam)) { /* Draw background*/ GetClientRect (hWnd, &rc); if (IsThemePartDefined (theme, WP_DIALOG, 0)) /* Although there is a theme for the WINDOW class/DIALOG part, * but I[res] haven't seen Windows using it yet... Even when * dialog theming is activated, the good ol' BTNFACE * background seems to be used. */ #if 0 DrawThemeBackground (theme, (HDC)wParam, WP_DIALOG, 0, &rc, NULL); #endif return THEMING_CallOriginalClass (hWnd, msg, wParam, lParam); else /* We might have gotten a TAB theme class, so check if we can * draw as a tab page. */ if (IsThemePartDefined (theme, TABP_BODY, 0)) DrawThemeBackground (theme, (HDC)wParam, TABP_BODY, 0, &rc, NULL); else return THEMING_CallOriginalClass (hWnd, msg, wParam, lParam); } return 1; }
/********************************************************************** * The button control subclass window proc. */ LRESULT CALLBACK THEMING_ButtonSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, ULONG_PTR dwRefData) { const WCHAR* themeClass = WC_BUTTONW; HTHEME theme; LRESULT result; switch (msg) { case WM_CREATE: result = THEMING_CallOriginalClass(hwnd, msg, wParam, lParam); OpenThemeData(hwnd, themeClass); return result; case WM_DESTROY: theme = GetWindowTheme(hwnd); CloseThemeData (theme); return THEMING_CallOriginalClass(hwnd, msg, wParam, lParam); case WM_THEMECHANGED: theme = GetWindowTheme(hwnd); CloseThemeData (theme); OpenThemeData(hwnd, themeClass); break; case WM_SYSCOLORCHANGE: theme = GetWindowTheme(hwnd); if (!theme) return THEMING_CallOriginalClass(hwnd, msg, wParam, lParam); /* Do nothing. When themed, a WM_THEMECHANGED will be received, too, * which will do the repaint. */ break; case WM_PAINT: theme = GetWindowTheme(hwnd); if (theme && BUTTON_Paint(theme, hwnd, (HDC)wParam)) return 0; else return THEMING_CallOriginalClass(hwnd, msg, wParam, lParam); case WM_ENABLE: theme = GetWindowTheme(hwnd); if (theme) RedrawWindow(hwnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW); return THEMING_CallOriginalClass(hwnd, msg, wParam, lParam); case WM_MOUSEMOVE: { TRACKMOUSEEVENT mouse_event; mouse_event.cbSize = sizeof(TRACKMOUSEEVENT); mouse_event.dwFlags = TME_QUERY; if(!TrackMouseEvent(&mouse_event) || !(mouse_event.dwFlags&(TME_HOVER|TME_LEAVE))) { mouse_event.dwFlags = TME_HOVER|TME_LEAVE; mouse_event.hwndTrack = hwnd; mouse_event.dwHoverTime = 1; TrackMouseEvent(&mouse_event); } break; } case WM_MOUSEHOVER: { int state = (int)SendMessageW(hwnd, BM_GETSTATE, 0, 0); SetWindowLongW(hwnd, 0, state|BST_HOT); InvalidateRect(hwnd, NULL, FALSE); break; } case WM_MOUSELEAVE: { int state = (int)SendMessageW(hwnd, BM_GETSTATE, 0, 0); SetWindowLongW(hwnd, 0, state&(~BST_HOT)); InvalidateRect(hwnd, NULL, FALSE); break; } default: /* Call old proc */ return THEMING_CallOriginalClass(hwnd, msg, wParam, lParam); } return 0; }
/********************************************************************** * The combo control subclass window proc. */ LRESULT CALLBACK THEMING_ComboSubclassProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, ULONG_PTR dwRefData) { const WCHAR* themeClass = WC_COMBOBOXW; HTHEME theme; LRESULT result; switch (msg) { case WM_CREATE: result = THEMING_CallOriginalClass (hwnd, msg, wParam, lParam); OpenThemeData( hwnd, themeClass ); return result; case WM_DESTROY: theme = GetWindowTheme( hwnd ); CloseThemeData ( theme ); return THEMING_CallOriginalClass (hwnd, msg, wParam, lParam); case WM_THEMECHANGED: theme = GetWindowTheme( hwnd ); CloseThemeData ( theme ); OpenThemeData( hwnd, themeClass ); break; case WM_SYSCOLORCHANGE: theme = GetWindowTheme( hwnd ); if (!theme) return THEMING_CallOriginalClass (hwnd, msg, wParam, lParam); /* Do nothing. When themed, a WM_THEMECHANGED will be received, too, * which will do the repaint. */ break; case WM_PAINT: theme = GetWindowTheme( hwnd ); if (!theme) return THEMING_CallOriginalClass (hwnd, msg, wParam, lParam); return paint (theme, hwnd, (HDC)wParam, dwRefData); case WM_SETREDRAW: /* Since there doesn't seem to be WM_GETREDRAW, do redraw tracking in * the subclass as well. */ if( wParam ) dwRefData &= ~STATE_NOREDRAW; else dwRefData |= STATE_NOREDRAW; THEMING_SetSubclassData (hwnd, dwRefData); return THEMING_CallOriginalClass (hwnd, msg, wParam, lParam); case WM_MOUSEMOVE: { /* Dropdown button hot-tracking */ COMBOBOXINFO cbi; POINT pt; pt.x = (short)LOWORD(lParam); pt.y = (short)HIWORD(lParam); cbi.cbSize = sizeof (cbi); SendMessageW (hwnd, CB_GETCOMBOBOXINFO, 0, (LPARAM)&cbi); if (cbi.stateButton != STATE_SYSTEM_INVISIBLE) { if (PtInRect (&cbi.rcButton, pt)) { if (!(dwRefData & STATE_HOT)) { dwRefData |= STATE_HOT; THEMING_SetSubclassData (hwnd, dwRefData); RedrawWindow (hwnd, &cbi.rcButton, 0, RDW_INVALIDATE | RDW_UPDATENOW); } } else { if (dwRefData & STATE_HOT) { dwRefData &= ~STATE_HOT; THEMING_SetSubclassData (hwnd, dwRefData); RedrawWindow (hwnd, &cbi.rcButton, 0, RDW_INVALIDATE | RDW_UPDATENOW); } } } } return THEMING_CallOriginalClass (hwnd, msg, wParam, lParam); default: /* Call old proc */ return THEMING_CallOriginalClass (hwnd, msg, wParam, lParam); } return 0; }