/********************************************************************** * 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; }
/*********************************************************************** * UPDOWN_Draw * * Draw the arrows. The background need not be erased. */ static LRESULT UPDOWN_Draw (const UPDOWN_INFO *infoPtr, HDC hdc) { BOOL uPressed, uHot, dPressed, dHot; RECT rect; HTHEME theme = GetWindowTheme (infoPtr->Self); int uPart = 0, uState = 0, dPart = 0, dState = 0; BOOL needBuddyBg = FALSE; uPressed = (infoPtr->Flags & FLAG_PRESSED) && (infoPtr->Flags & FLAG_INCR); uHot = (infoPtr->Flags & FLAG_INCR) && (infoPtr->Flags & FLAG_MOUSEIN); dPressed = (infoPtr->Flags & FLAG_PRESSED) && (infoPtr->Flags & FLAG_DECR); dHot = (infoPtr->Flags & FLAG_DECR) && (infoPtr->Flags & FLAG_MOUSEIN); if (theme) { uPart = (infoPtr->dwStyle & UDS_HORZ) ? SPNP_UPHORZ : SPNP_UP; uState = (infoPtr->dwStyle & WS_DISABLED) ? DNS_DISABLED : (uPressed ? DNS_PRESSED : (uHot ? DNS_HOT : DNS_NORMAL)); dPart = (infoPtr->dwStyle & UDS_HORZ) ? SPNP_DOWNHORZ : SPNP_DOWN; dState = (infoPtr->dwStyle & WS_DISABLED) ? DNS_DISABLED : (dPressed ? DNS_PRESSED : (dHot ? DNS_HOT : DNS_NORMAL)); needBuddyBg = IsWindow (infoPtr->Buddy) && (IsThemeBackgroundPartiallyTransparent (theme, uPart, uState) || IsThemeBackgroundPartiallyTransparent (theme, dPart, dState)); } /* Draw the common border between ourselves and our buddy */ if (UPDOWN_HasBuddyBorder(infoPtr) || needBuddyBg) { if (!theme || !UPDOWN_DrawBuddyBackground (infoPtr, hdc)) { GetClientRect(infoPtr->Self, &rect); DrawEdge(hdc, &rect, EDGE_SUNKEN, BF_BOTTOM | BF_TOP | (infoPtr->dwStyle & UDS_ALIGNLEFT ? BF_LEFT : BF_RIGHT)); } } /* Draw the incr button */ UPDOWN_GetArrowRect (infoPtr, &rect, FLAG_INCR); if (theme) { DrawThemeBackground(theme, hdc, uPart, uState, &rect, NULL); } else { DrawFrameControl(hdc, &rect, DFC_SCROLL, (infoPtr->dwStyle & UDS_HORZ ? DFCS_SCROLLRIGHT : DFCS_SCROLLUP) | ((infoPtr->dwStyle & UDS_HOTTRACK) && uHot ? DFCS_HOT : 0) | (uPressed ? DFCS_PUSHED : 0) | (infoPtr->dwStyle & WS_DISABLED ? DFCS_INACTIVE : 0) ); } /* Draw the decr button */ UPDOWN_GetArrowRect(infoPtr, &rect, FLAG_DECR); if (theme) { DrawThemeBackground(theme, hdc, dPart, dState, &rect, NULL); } else { DrawFrameControl(hdc, &rect, DFC_SCROLL, (infoPtr->dwStyle & UDS_HORZ ? DFCS_SCROLLLEFT : DFCS_SCROLLDOWN) | ((infoPtr->dwStyle & UDS_HOTTRACK) && dHot ? DFCS_HOT : 0) | (dPressed ? DFCS_PUSHED : 0) | (infoPtr->dwStyle & WS_DISABLED ? DFCS_INACTIVE : 0) ); } return 0; }
/* update theme after a WM_THEMECHANGED message */ static LRESULT theme_changed (const STATUS_INFO* infoPtr) { HTHEME theme = GetWindowTheme (infoPtr->Self); CloseThemeData (theme); OpenThemeData (infoPtr->Self, themeClass); return 0; }
static void STATUSBAR_RefreshPart (const STATUS_INFO *infoPtr, HDC hdc, const STATUSWINDOWPART *part, int itemID) { HBRUSH hbrBk; HTHEME theme; TRACE("item %d\n", itemID); if (part->bound.right < part->bound.left) return; if (!RectVisible(hdc, &part->bound)) return; if ((theme = GetWindowTheme (infoPtr->Self))) { RECT cr; GetClientRect (infoPtr->Self, &cr); DrawThemeBackground(theme, hdc, 0, 0, &cr, &part->bound); } else { if (infoPtr->clrBk != CLR_DEFAULT) hbrBk = CreateSolidBrush (infoPtr->clrBk); else hbrBk = GetSysColorBrush (COLOR_3DFACE); FillRect(hdc, &part->bound, hbrBk); if (infoPtr->clrBk != CLR_DEFAULT) DeleteObject (hbrBk); } STATUSBAR_DrawPart (infoPtr, hdc, part, itemID); }
static LRESULT STATUSBAR_WMDestroy (STATUS_INFO *infoPtr) { unsigned int i; TRACE("\n"); for (i = 0; i < infoPtr->numParts; i++) { if (!(infoPtr->parts[i].style & SBT_OWNERDRAW)) Free (infoPtr->parts[i].text); } if (!(infoPtr->part0.style & SBT_OWNERDRAW)) Free (infoPtr->part0.text); Free (infoPtr->parts); /* delete default font */ if (infoPtr->hDefaultFont) DeleteObject (infoPtr->hDefaultFont); /* delete tool tip control */ if (infoPtr->hwndToolTip) DestroyWindow (infoPtr->hwndToolTip); CloseThemeData (GetWindowTheme (infoPtr->Self)); SetWindowLongPtrW(infoPtr->Self, 0, 0); Free (infoPtr); return 0; }
static UINT STATUSBAR_ComputeHeight(STATUS_INFO *infoPtr) { HTHEME theme; UINT height; TEXTMETRICW tm; int margin; COMCTL32_GetFontMetrics(infoPtr->hFont ? infoPtr->hFont : infoPtr->hDefaultFont, &tm); margin = (tm.tmInternalLeading ? tm.tmInternalLeading : 2); height = max(tm.tmHeight + margin + 2*GetSystemMetrics(SM_CYBORDER), infoPtr->minHeight) + infoPtr->verticalBorder; if ((theme = GetWindowTheme(infoPtr->Self))) { /* Determine bar height from theme such that the content area is * textHeight pixels large */ HDC hdc = GetDC(infoPtr->Self); RECT r; SetRect(&r, 0, 0, 0, max(infoPtr->minHeight, tm.tmHeight)); if (SUCCEEDED(GetThemeBackgroundExtent(theme, hdc, SP_PANE, 0, &r, &r))) { height = r.bottom - r.top; } ReleaseDC(infoPtr->Self, hdc); } TRACE(" textHeight=%d+%d, final height=%d\n", tm.tmHeight, tm.tmInternalLeading, height); return height; }
/*********************************************************************** * UPDOWN_DrawBuddyBackground * * Draw buddy background for visual integration. */ static BOOL UPDOWN_DrawBuddyBackground (const UPDOWN_INFO *infoPtr, HDC hdc) { RECT br; HTHEME buddyTheme = GetWindowTheme (infoPtr->Buddy); if (!buddyTheme) return FALSE; GetClientRect (infoPtr->Buddy, &br); MapWindowPoints (infoPtr->Buddy, infoPtr->Self, (POINT*)&br, 2); /* FIXME: take disabled etc. into account */ DrawThemeBackground (buddyTheme, hdc, 0, 0, &br, NULL); return TRUE; }
/* Helper to obtain gap between progress bar chunks */ static inline int get_led_gap ( PROGRESS_INFO *infoPtr ) { HTHEME theme = GetWindowTheme (infoPtr->Self); if (theme) { int spaceSize; if (SUCCEEDED( GetThemeInt( theme, 0, 0, TMT_PROGRESSSPACESIZE, &spaceSize ))) return spaceSize; } return LED_GAP; }
static void STATUSBAR_DrawPart (const STATUS_INFO *infoPtr, HDC hdc, const STATUSWINDOWPART *part, int itemID) { RECT r = part->bound; UINT border = BDR_SUNKENOUTER; HTHEME theme = GetWindowTheme (infoPtr->Self); int themePart = SP_PANE; int x = 0; TRACE("part bound %s\n", wine_dbgstr_rect(&r)); if (part->style & SBT_POPOUT) border = BDR_RAISEDOUTER; else if (part->style & SBT_NOBORDERS) border = 0; if (theme) { if ((GetWindowLongW (infoPtr->Self, GWL_STYLE) & SBARS_SIZEGRIP) && (infoPtr->simple || (itemID == (infoPtr->numParts-1)))) themePart = SP_GRIPPERPANE; DrawThemeBackground(theme, hdc, themePart, 0, &r, NULL); } else DrawEdge(hdc, &r, border, BF_RECT|BF_ADJUST); if (part->hIcon) { INT cy = r.bottom - r.top; DrawIconEx (hdc, r.left + 2, r.top, part->hIcon, cy, cy, 0, 0, DI_NORMAL); x = 2 + cy; } if (part->style & SBT_OWNERDRAW) { DRAWITEMSTRUCT dis; dis.CtlID = GetWindowLongPtrW (infoPtr->Self, GWLP_ID); dis.itemID = itemID; dis.hwndItem = infoPtr->Self; dis.hDC = hdc; dis.rcItem = r; dis.itemData = (ULONG_PTR)part->text; SendMessageW (infoPtr->Notify, WM_DRAWITEM, dis.CtlID, (LPARAM)&dis); } else { r.left += x; #ifdef __REACTOS__ if (!theme) DrawStatusTextW (hdc, &r, part->text, SBT_NOBORDERS); else DrawThemeText(theme, hdc, SP_PANE, 0, part->text, -1, DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX, 0, &r); #else DrawStatusTextW (hdc, &r, part->text, SBT_NOBORDERS); #endif } }
/* Get client rect. Takes into account that theming needs no adjustment. */ static inline void get_client_rect (HWND hwnd, RECT* rect) { HTHEME theme = GetWindowTheme (hwnd); GetClientRect (hwnd, rect); if (!theme) InflateRect(rect, -1, -1); else { DWORD dwStyle = GetWindowLongW (hwnd, GWL_STYLE); int part = (dwStyle & PBS_VERTICAL) ? PP_BARVERT : PP_BAR; GetThemeBackgroundContentRect (theme, 0, part, 0, rect, rect); } }
static LRESULT STATUSBAR_Refresh (STATUS_INFO *infoPtr, HDC hdc) { RECT rect; HBRUSH hbrBk; HFONT hOldFont; HTHEME theme; TRACE("\n"); if (!IsWindowVisible(infoPtr->Self)) return 0; STATUSBAR_SetPartBounds(infoPtr); GetClientRect (infoPtr->Self, &rect); if ((theme = GetWindowTheme (infoPtr->Self))) { DrawThemeBackground(theme, hdc, 0, 0, &rect, NULL); } else { if (infoPtr->clrBk != CLR_DEFAULT) hbrBk = CreateSolidBrush (infoPtr->clrBk); else hbrBk = GetSysColorBrush (COLOR_3DFACE); FillRect(hdc, &rect, hbrBk); if (infoPtr->clrBk != CLR_DEFAULT) DeleteObject (hbrBk); } hOldFont = SelectObject (hdc, infoPtr->hFont ? infoPtr->hFont : infoPtr->hDefaultFont); if (infoPtr->simple) { STATUSBAR_RefreshPart (infoPtr, hdc, &infoPtr->part0, 0); } else { unsigned int i; for (i = 0; i < infoPtr->numParts; i++) { STATUSBAR_RefreshPart (infoPtr, hdc, &infoPtr->parts[i], i); } } SelectObject (hdc, hOldFont); if ((GetWindowLongW (infoPtr->Self, GWL_STYLE) & SBARS_SIZEGRIP) && !(GetWindowLongW (infoPtr->Notify, GWL_STYLE) & WS_MAXIMIZE)) STATUSBAR_DrawSizeGrip (theme, hdc, &rect); return 0; }
HRESULT CMenuToolbarBase::ShowDW(BOOL fShow) { ShowWindow(fShow ? SW_SHOW : SW_HIDE); // Ensure that the right image list is assigned to the toolbar UpdateImageLists(); // For custom-drawing if (IsAppThemed()) GetThemeSysBool(GetWindowTheme(m_hWnd), TMT_FLATMENUS); else SystemParametersInfo(SPI_GETFLATMENU, 0, &m_useFlatMenus, 0); return S_OK; }
/* Helper to obtain size of a progress bar chunk ("led"). */ static inline int get_led_size ( PROGRESS_INFO *infoPtr, LONG style, const RECT* rect ) { HTHEME theme = GetWindowTheme (infoPtr->Self); if (theme) { int chunkSize; if (SUCCEEDED( GetThemeInt( theme, 0, 0, TMT_PROGRESSCHUNKSIZE, &chunkSize ))) return chunkSize; } if (style & PBS_VERTICAL) return MulDiv (rect->right - rect->left, 2, 3); else return MulDiv (rect->bottom - rect->top, 2, 3); }
/*********************************************************************** * UPDOWN_GetArrowRect * wndPtr - pointer to the up-down wnd * rect - will hold the rectangle * arrow - FLAG_INCR to get the "increment" rect (up or right) * FLAG_DECR to get the "decrement" rect (down or left) * If both flags are present, the envelope is returned. */ static void UPDOWN_GetArrowRect (const UPDOWN_INFO* infoPtr, RECT *rect, int arrow) { HTHEME theme = GetWindowTheme (infoPtr->Self); const int border = theme ? DEFAULT_BUDDYBORDER_THEMED : DEFAULT_BUDDYBORDER; const int spacer = theme ? DEFAULT_BUDDYSPACER_THEMED : DEFAULT_BUDDYSPACER; GetClientRect (infoPtr->Self, rect); /* * Make sure we calculate the rectangle to fit even if we draw the * border. */ if (UPDOWN_HasBuddyBorder(infoPtr)) { if (infoPtr->dwStyle & UDS_ALIGNLEFT) rect->left += border; else rect->right -= border; InflateRect(rect, 0, -border); } /* now figure out if we need a space away from the buddy */ if (IsWindow(infoPtr->Buddy) ) { if (infoPtr->dwStyle & UDS_ALIGNLEFT) rect->right -= spacer; else rect->left += spacer; } /* * We're calculating the midpoint to figure-out where the * separation between the buttons will lay. We make sure that we * round the uneven numbers by adding 1. */ if (infoPtr->dwStyle & UDS_HORZ) { int len = rect->right - rect->left + 1; /* compute the width */ if (arrow & FLAG_INCR) rect->left = rect->left + len/2; if (arrow & FLAG_DECR) rect->right = rect->left + len/2 - (theme ? 0 : 1); } else { int len = rect->bottom - rect->top + 1; /* compute the height */ if (arrow & FLAG_INCR) rect->bottom = rect->top + len/2 - (theme ? 0 : 1); if (arrow & FLAG_DECR) rect->top = rect->top + len/2; } }
/*********************************************************************** * UPDOWN_DrawBuddyBackground * * Draw buddy background for visual integration. */ static BOOL UPDOWN_DrawBuddyBackground (const UPDOWN_INFO *infoPtr, HDC hdc) { RECT br, r; HTHEME buddyTheme = GetWindowTheme (infoPtr->Buddy); if (!buddyTheme) return FALSE; GetWindowRect (infoPtr->Buddy, &br); MapWindowPoints (NULL, infoPtr->Self, (POINT*)&br, 2); GetClientRect (infoPtr->Self, &r); if (infoPtr->dwStyle & UDS_ALIGNLEFT) br.left = r.left; else if (infoPtr->dwStyle & UDS_ALIGNRIGHT) br.right = r.right; /* FIXME: take disabled etc. into account */ DrawThemeBackground (buddyTheme, hdc, 0, 0, &br, NULL); return TRUE; }
/********************************************************************** * 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 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; }
HRESULT CMenuToolbarBase::CreateToolbar(HWND hwndParent, DWORD dwFlags) { LONG tbStyles = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TBSTYLE_TOOLTIPS | TBSTYLE_TRANSPARENT | TBSTYLE_REGISTERDROP | TBSTYLE_LIST | TBSTYLE_FLAT | TBSTYLE_CUSTOMERASE | CCS_NODIVIDER | CCS_NOPARENTALIGN | CCS_NORESIZE | CCS_TOP; LONG tbExStyles = TBSTYLE_EX_DOUBLEBUFFER | WS_EX_TOOLWINDOW; if (dwFlags & SMINIT_VERTICAL) { // Activate vertical semantics tbStyles |= CCS_VERT; #if USE_TBSTYLE_EX_VERTICAL tbExStyles |= TBSTYLE_EX_VERTICAL; #endif } m_initFlags = dwFlags; // Get a temporary rect to use while creating the toolbar window. // Ensure that it is not a null rect. RECT rc; if (!::GetClientRect(hwndParent, &rc) || (rc.left == rc.right) || (rc.top == rc.bottom)) { rc.left = 0; rc.top = 0; rc.right = 1; rc.bottom = 1; } SubclassWindow(CToolbar::Create(hwndParent, tbStyles, tbExStyles)); SetWindowTheme(m_hWnd, L"", L""); if (IsAppThemed()) GetThemeSysBool(GetWindowTheme(m_hWnd), TMT_FLATMENUS); else SystemParametersInfo(SPI_GETFLATMENU, 0, &m_useFlatMenus, 0); m_menuBand->AdjustForTheme(m_useFlatMenus); // If needed, create the pager. if (m_usePager) { LONG pgStyles = PGS_VERT | WS_CHILD | WS_VISIBLE; LONG pgExStyles = 0; HWND hwndPager = CreateWindowEx( pgExStyles, WC_PAGESCROLLER, NULL, pgStyles, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, hwndParent, NULL, _AtlBaseModule.GetModuleInstance(), 0); m_pager.SubclassWindow(hwndPager); ::SetParent(m_hWnd, hwndPager); m_pager.SendMessageW(PGM_SETCHILD, 0, reinterpret_cast<LPARAM>(m_hWnd)); } // Configure the image lists UpdateImageLists(); return S_OK; }
/********************************************************************** * 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; }
/*********************************************************************** * UpDownWndProc */ static LRESULT WINAPI UpDownWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { UPDOWN_INFO *infoPtr = UPDOWN_GetInfoPtr (hwnd); static const WCHAR themeClass[] = {'S','p','i','n',0}; HTHEME theme; TRACE("hwnd=%p msg=%04x wparam=%08lx lparam=%08lx\n", hwnd, message, wParam, lParam); if (!infoPtr && (message != WM_CREATE)) return DefWindowProcW (hwnd, message, wParam, lParam); switch(message) { case WM_CREATE: infoPtr = Alloc (sizeof(UPDOWN_INFO)); SetWindowLongPtrW (hwnd, 0, (DWORD_PTR)infoPtr); /* initialize the info struct */ infoPtr->Self = hwnd; infoPtr->Notify = ((LPCREATESTRUCTW)lParam)->hwndParent; infoPtr->dwStyle = ((LPCREATESTRUCTW)lParam)->style; infoPtr->AccelCount = 0; infoPtr->AccelVect = 0; infoPtr->AccelIndex = -1; infoPtr->CurVal = 0; infoPtr->MinVal = 100; infoPtr->MaxVal = 0; infoPtr->Base = 10; /* Default to base 10 */ infoPtr->Buddy = 0; /* No buddy window yet */ infoPtr->Flags = 0; /* And no flags */ SetWindowLongW (hwnd, GWL_STYLE, infoPtr->dwStyle & ~WS_BORDER); /* Do we pick the buddy win ourselves? */ if (infoPtr->dwStyle & UDS_AUTOBUDDY) UPDOWN_SetBuddy (infoPtr, GetWindow (hwnd, GW_HWNDPREV)); OpenThemeData (hwnd, themeClass); TRACE("UpDown Ctrl creation, hwnd=%p\n", hwnd); break; case WM_DESTROY: Free (infoPtr->AccelVect); if(infoPtr->Buddy) RemovePropW(infoPtr->Buddy, BUDDY_UPDOWN_HWND); Free (infoPtr); SetWindowLongPtrW (hwnd, 0, 0); theme = GetWindowTheme (hwnd); CloseThemeData (theme); TRACE("UpDown Ctrl destruction, hwnd=%p\n", hwnd); break; case WM_ENABLE: if (wParam) { infoPtr->dwStyle &= ~WS_DISABLED; } else { infoPtr->dwStyle |= WS_DISABLED; UPDOWN_CancelMode (infoPtr); } InvalidateRect (infoPtr->Self, NULL, FALSE); break; case WM_STYLECHANGED: if (wParam == GWL_STYLE) { infoPtr->dwStyle = ((LPSTYLESTRUCT)lParam)->styleNew; InvalidateRect (infoPtr->Self, NULL, FALSE); } break; case WM_THEMECHANGED: theme = GetWindowTheme (hwnd); CloseThemeData (theme); OpenThemeData (hwnd, themeClass); InvalidateRect (hwnd, NULL, FALSE); break; case WM_TIMER: /* is this the auto-press timer? */ if(wParam == TIMER_AUTOPRESS) { KillTimer(hwnd, TIMER_AUTOPRESS); infoPtr->Flags &= ~(FLAG_PRESSED | FLAG_ARROW); InvalidateRect(infoPtr->Self, NULL, FALSE); } /* if initial timer, kill it and start the repeat timer */ if(wParam == TIMER_AUTOREPEAT) { int temp; KillTimer(hwnd, TIMER_AUTOREPEAT); /* if no accel info given, used default timer */ if(infoPtr->AccelCount==0 || infoPtr->AccelVect==0) { infoPtr->AccelIndex = -1; temp = REPEAT_DELAY; } else { infoPtr->AccelIndex = 0; /* otherwise, use it */ temp = infoPtr->AccelVect[infoPtr->AccelIndex].nSec * 1000 + 1; } SetTimer(hwnd, TIMER_ACCEL, temp, 0); } /* now, if the mouse is above us, do the thing...*/ if(infoPtr->Flags & FLAG_MOUSEIN) { int temp; temp = infoPtr->AccelIndex == -1 ? 1 : infoPtr->AccelVect[infoPtr->AccelIndex].nInc; UPDOWN_DoAction(infoPtr, temp, infoPtr->Flags & FLAG_ARROW); if(infoPtr->AccelIndex != -1 && infoPtr->AccelIndex < infoPtr->AccelCount-1) { KillTimer(hwnd, TIMER_ACCEL); infoPtr->AccelIndex++; /* move to the next accel info */ temp = infoPtr->AccelVect[infoPtr->AccelIndex].nSec * 1000 + 1; /* make sure we have at least 1ms intervals */ SetTimer(hwnd, TIMER_ACCEL, temp, 0); } } break; case WM_CANCELMODE: return UPDOWN_CancelMode (infoPtr); case WM_LBUTTONUP: if (GetCapture() != infoPtr->Self) break; if ( (infoPtr->Flags & FLAG_MOUSEIN) && (infoPtr->Flags & FLAG_ARROW) ) { SendMessageW( infoPtr->Notify, (infoPtr->dwStyle & UDS_HORZ) ? WM_HSCROLL : WM_VSCROLL, MAKELONG(SB_ENDSCROLL, infoPtr->CurVal), (LPARAM)hwnd); if (UPDOWN_IsBuddyEdit(infoPtr)) SendMessageW(infoPtr->Buddy, EM_SETSEL, 0, MAKELONG(0, -1)); } UPDOWN_CancelMode(infoPtr); break; case WM_LBUTTONDOWN: case WM_MOUSEMOVE: case WM_MOUSELEAVE: if(UPDOWN_IsEnabled(infoPtr)) UPDOWN_HandleMouseEvent (infoPtr, message, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam)); break; case WM_MOUSEWHEEL: UPDOWN_MouseWheel(infoPtr, wParam); break; case WM_KEYDOWN: if((infoPtr->dwStyle & UDS_ARROWKEYS) && UPDOWN_IsEnabled(infoPtr)) return UPDOWN_KeyPressed(infoPtr, (int)wParam); break; case WM_PRINTCLIENT: case WM_PAINT: return UPDOWN_Paint (infoPtr, (HDC)wParam); case UDM_GETACCEL: if (wParam==0 && lParam==0) return infoPtr->AccelCount; if (wParam && lParam) { int temp = min(infoPtr->AccelCount, wParam); memcpy((void *)lParam, infoPtr->AccelVect, temp*sizeof(UDACCEL)); return temp; } return 0; case UDM_SETACCEL: { unsigned temp; TRACE("UDM_SETACCEL\n"); if(infoPtr->AccelVect) { Free (infoPtr->AccelVect); infoPtr->AccelCount = 0; infoPtr->AccelVect = 0; } if(wParam==0) return TRUE; infoPtr->AccelVect = Alloc (wParam*sizeof(UDACCEL)); if(infoPtr->AccelVect == 0) return FALSE; memcpy(infoPtr->AccelVect, (void*)lParam, wParam*sizeof(UDACCEL)); infoPtr->AccelCount = wParam; for (temp = 0; temp < wParam; temp++) TRACE("%d: nSec %u nInc %u\n", temp, infoPtr->AccelVect[temp].nSec, infoPtr->AccelVect[temp].nInc); return TRUE; } case UDM_GETBASE: return infoPtr->Base; case UDM_SETBASE: TRACE("UpDown Ctrl new base(%ld), hwnd=%p\n", wParam, hwnd); if (wParam==10 || wParam==16) { WPARAM temp = infoPtr->Base; infoPtr->Base = wParam; return temp; } break; case UDM_GETBUDDY: return (LRESULT)infoPtr->Buddy; case UDM_SETBUDDY: return (LRESULT)UPDOWN_SetBuddy (infoPtr, (HWND)wParam); case UDM_GETPOS: { int temp = UPDOWN_GetBuddyInt (infoPtr); return MAKELONG(infoPtr->CurVal, temp ? 0 : 1); } case UDM_SETPOS: { int temp = (short)LOWORD(lParam); TRACE("UpDown Ctrl new value(%d), hwnd=%p\n", temp, hwnd); if(!UPDOWN_InBounds(infoPtr, temp)) { if(temp < infoPtr->MinVal) temp = infoPtr->MinVal; if(temp > infoPtr->MaxVal) temp = infoPtr->MaxVal; } wParam = infoPtr->CurVal; infoPtr->CurVal = temp; UPDOWN_SetBuddyInt (infoPtr); return wParam; /* return prev value */ } case UDM_GETRANGE: return MAKELONG(infoPtr->MaxVal, infoPtr->MinVal); case UDM_SETRANGE: /* we must have: */ infoPtr->MaxVal = (short)(lParam); /* UD_MINVAL <= Max <= UD_MAXVAL */ infoPtr->MinVal = (short)HIWORD(lParam); /* UD_MINVAL <= Min <= UD_MAXVAL */ /* |Max-Min| <= UD_MAXVAL */ TRACE("UpDown Ctrl new range(%d to %d), hwnd=%p\n", infoPtr->MinVal, infoPtr->MaxVal, hwnd); break; case UDM_GETRANGE32: if (wParam) *(LPINT)wParam = infoPtr->MinVal; if (lParam) *(LPINT)lParam = infoPtr->MaxVal; break; case UDM_SETRANGE32: infoPtr->MinVal = (INT)wParam; infoPtr->MaxVal = (INT)lParam; if (infoPtr->MaxVal <= infoPtr->MinVal) infoPtr->MaxVal = infoPtr->MinVal + 1; TRACE("UpDown Ctrl new range(%d to %d), hwnd=%p\n", infoPtr->MinVal, infoPtr->MaxVal, hwnd); break; case UDM_GETPOS32: if ((LPBOOL)lParam != NULL) *((LPBOOL)lParam) = TRUE; return infoPtr->CurVal; case UDM_SETPOS32: { int temp; if(!UPDOWN_InBounds(infoPtr, (int)lParam)) { if((int)lParam < infoPtr->MinVal) lParam = infoPtr->MinVal; if((int)lParam > infoPtr->MaxVal) lParam = infoPtr->MaxVal; } temp = infoPtr->CurVal; /* save prev value */ infoPtr->CurVal = (int)lParam; /* set the new value */ UPDOWN_SetBuddyInt (infoPtr); return temp; /* return prev value */ } case UDM_GETUNICODEFORMAT: /* we lie a bit here, we're always using Unicode internally */ return infoPtr->UnicodeFormat; case UDM_SETUNICODEFORMAT: { /* do we really need to honour this flag? */ int temp = infoPtr->UnicodeFormat; infoPtr->UnicodeFormat = (BOOL)wParam; return temp; } default: if ((message >= WM_USER) && (message < WM_APP) && !COMCTL32_IsReflectedMessage(message)) ERR("unknown msg %04x wp=%04lx lp=%08lx\n", message, wParam, lParam); return DefWindowProcW (hwnd, message, wParam, lParam); } return 0; }