diff options
author | Jean-Francois Mauguit <jfmauguit@mac.com> | 2024-09-24 09:03:25 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-24 09:03:25 -0400 |
commit | bab614c421ed7ae329d26bf028c4a3b1d2450f5a (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Plugins/General/gen_ml/skinnedcombo.cpp | |
parent | 4bde6044fddf053f31795b9eaccdd2a5a527d21f (diff) | |
parent | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (diff) | |
download | winamp-bab614c421ed7ae329d26bf028c4a3b1d2450f5a.tar.gz |
Merge pull request #5 from WinampDesktop/community
Merge to main
Diffstat (limited to 'Src/Plugins/General/gen_ml/skinnedcombo.cpp')
-rw-r--r-- | Src/Plugins/General/gen_ml/skinnedcombo.cpp | 444 |
1 files changed, 444 insertions, 0 deletions
diff --git a/Src/Plugins/General/gen_ml/skinnedcombo.cpp b/Src/Plugins/General/gen_ml/skinnedcombo.cpp new file mode 100644 index 00000000..1473384d --- /dev/null +++ b/Src/Plugins/General/gen_ml/skinnedcombo.cpp @@ -0,0 +1,444 @@ +#include "./skinnedcombo.h" +#include "./skinnedheader.h" +#include "../winamp/wa_dlg.h" +#include "./skinning.h" +#include "../nu/trace.h" +#include <windowsx.h> +#include <strsafe.h> + +#define COMBO_TEXT_MAX 512 + +SkinnedCombobox::SkinnedCombobox(void) : SkinnedWnd(FALSE), activeBorder(TRUE) +{ +} + +SkinnedCombobox::~SkinnedCombobox(void) +{ +} + +BOOL SkinnedCombobox::Attach(HWND hwndCombo) +{ + if(!SkinnedWnd::Attach(hwndCombo)) return FALSE; + SetType(SKINNEDWND_TYPE_COMBOBOX); + activeBorder = TRUE; + COMBOBOXINFO cbi; + ZeroMemory(&cbi, sizeof(COMBOBOXINFO)); + cbi.cbSize = sizeof(COMBOBOXINFO); + if (GetComboBoxInfo(hwnd, &cbi)) + { + if (NULL != cbi.hwndItem) SkinWindowEx(cbi.hwndItem, SKINNEDWND_TYPE_EDIT, style); + if (NULL != cbi.hwndList) + { + SkinWindowEx(cbi.hwndList, SKINNEDWND_TYPE_LISTBOX, style); + } + } + SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED); + return TRUE; +} + +BOOL SkinnedCombobox::SetStyle(UINT newStyle, BOOL bRedraw) +{ + BOOL result = __super::SetStyle(newStyle, bRedraw); + if (hwnd) + { + COMBOBOXINFO cbi; + ZeroMemory(&cbi, sizeof(COMBOBOXINFO)); + cbi.cbSize = sizeof(COMBOBOXINFO); + activeBorder = (0 == (SWCBS_TOOLBAR & style)); + if (GetComboBoxInfo(hwnd, &cbi)) + { + if (NULL != cbi.hwndItem) MLSkinnedWnd_SetStyle(cbi.hwndItem, style); + if (NULL != cbi.hwndList) MLSkinnedWnd_SetStyle(cbi.hwndList, style); + } + } + return result; +} + +BOOL SkinnedCombobox::IsButtonDown(DWORD windowStyle) +{ + if(GetAsyncKeyState((GetSystemMetrics(SM_SWAPBUTTON)) ? VK_RBUTTON : VK_LBUTTON) & 0x8000) + { + if (CBS_DROPDOWNLIST == (0x0F & windowStyle)) + { + POINT pt; + RECT rc; + + if (hwnd == GetFocus() && GetClientRect(hwnd, &rc)) + { + GetCursorPos(&pt); + MapWindowPoints(HWND_DESKTOP, hwnd, &pt, 1); + return PtInRect(&rc, pt); + } + return FALSE; + } + + COMBOBOXINFO cbi; + ZeroMemory(&cbi, sizeof(COMBOBOXINFO)); + cbi.cbSize = sizeof(COMBOBOXINFO); + + if (GetComboBoxInfo(hwnd, &cbi)) + { + //check if in arrow down area + POINT pt; + GetCursorPos(&pt); + MapWindowPoints(HWND_DESKTOP, hwnd, &pt, 1); + return PtInRect(&cbi.rcButton, pt); + } + } + return FALSE; +} + +void SkinnedCombobox::DrawButton(HDC hdc, RECT *prcButton, BOOL bPressed, BOOL bActive) +{ + COLORREF rgbBkOld, rgbBk; + + rgbBk = WADlg_getColor(WADLG_LISTHEADER_BGCOLOR); + rgbBkOld = SetBkColor(hdc, rgbBk); + ExtTextOutW(hdc, 0, 0, ETO_OPAQUE, prcButton, NULL, 0, 0); + + if (bActive) + { + HPEN pen, penOld; + pen = (HPEN)MlStockObjects_Get((bPressed) ? HEADERBOTTOM_PEN : HEADERTOP_PEN); + penOld = (HPEN)SelectObject(hdc, pen); + + MoveToEx(hdc, prcButton->left, prcButton->top, NULL); + LineTo(hdc, prcButton->right, prcButton->top); + MoveToEx(hdc, prcButton->left, prcButton->top, NULL); + LineTo(hdc, prcButton->left, prcButton->bottom); + + if (!bPressed) + { + SelectObject(hdc, penOld); + pen = (HPEN)MlStockObjects_Get(HEADERBOTTOM_PEN); + penOld = (HPEN)SelectObject(hdc, pen); + } + + MoveToEx(hdc, prcButton->right - 1, prcButton->top, NULL); + LineTo(hdc, prcButton->right - 1, prcButton->bottom); + MoveToEx(hdc, prcButton->right - 1, prcButton->bottom - 1, NULL); + LineTo(hdc, prcButton->left - 1, prcButton->bottom - 1); + + if (!bPressed) + { + SelectObject(hdc, penOld); + + pen = (HPEN)MlStockObjects_Get(HEADERMIDDLE_PEN); + penOld = (HPEN)SelectObject(hdc, pen); + + MoveToEx(hdc, prcButton->right - 2, prcButton->top + 1, NULL); + LineTo(hdc, prcButton->right - 2, prcButton->bottom - 2); + MoveToEx(hdc, prcButton->right - 2, prcButton->bottom - 2, NULL); + LineTo(hdc, prcButton->left, prcButton->bottom - 2); + } + SelectObject(hdc, penOld); + } + + RECT r; + DWORD arrowSize = SkinnedHeader::GetSortArrowSize(); + + SetRect(&r, 0, 0, GET_X_LPARAM(arrowSize), GET_Y_LPARAM(arrowSize)); + + OffsetRect(&r, + prcButton->left + (prcButton->right - prcButton->left - r.right)/2 + (prcButton->right - prcButton->left - r.right)%2, + prcButton->top + (prcButton->bottom - prcButton->top - r.bottom)/2); + if (bPressed) OffsetRect(&r, 1, 1); + if (r.left > (prcButton->left + 1) && r.top > (prcButton->top + 1)) + { + SkinnedHeader::DrawSortArrow(hdc, &r, rgbBk, WADlg_getColor(WADLG_LISTHEADER_FONTCOLOR), FALSE); + } + + SetBkColor(hdc, rgbBkOld); +} + +void SkinnedCombobox::OnPaint() +{ + HDC hdc; + PAINTSTRUCT ps; + RECT rc; + COMBOBOXINFO cbi; + BOOL ctrlActive; + + if (!GetClientRect(hwnd, &rc) || rc.bottom <= rc.top || rc.right <= rc.left) return; + + hdc= BeginPaint(hwnd, &ps); + if (NULL == hdc) return; + + ctrlActive = (activeBorder /*|| hwnd == GetFocus()*/); + + if (SWCBS_TOOLBAR & style) + { + DrawBorder(hdc, &rc, BORDER_FLAT, (HPEN)MlStockObjects_Get(WNDBCK_PEN)); + if (ctrlActive) + { + InflateRect(&rc, -1, -1); + DrawBorder(hdc, &rc, BORDER_FLAT, __super::GetBorderPen()); + } + } + else DrawBorder(hdc, &rc, BORDER_FLAT, GetBorderPen()); + + InflateRect(&rc, -1, -1); + + ZeroMemory(&cbi, sizeof(COMBOBOXINFO)); + cbi.cbSize = sizeof(COMBOBOXINFO); + if (GetComboBoxInfo(hwnd, &cbi)) + { + RECT r; + + DWORD ws = GetWindowLongPtrW(hwnd, GWL_STYLE); + + SetBkMode(hdc, OPAQUE); + SetBkColor(hdc, WADlg_getColor(WADLG_ITEMBG)); + + SetRect(&r, rc.left, rc.top, cbi.rcItem.left, rc.bottom); + if (r.left < r.right) ExtTextOutW(hdc, 0, 0, ETO_OPAQUE, &r, L"", 0, NULL); + SetRect(&r, cbi.rcItem.left, rc.top, cbi.rcItem.right, cbi.rcItem.top); + if (r.top < r.bottom) ExtTextOutW(hdc, 0, 0, ETO_OPAQUE, &r, L"", 0, NULL); + SetRect(&r, cbi.rcItem.left, cbi.rcItem.bottom, cbi.rcItem.right, rc.bottom); + if (r.top < r.bottom) ExtTextOutW(hdc, 0, 0, ETO_OPAQUE, &r, L"", 0, NULL); + + if (cbi.rcButton.left != cbi.rcButton.right) + { + SetRect(&r, cbi.rcItem.right, rc.top, cbi.rcButton.left, rc.bottom); + if (r.left < r.right) ExtTextOutW(hdc, 0, 0, ETO_OPAQUE, &r, L"", 0, NULL); + SetRect(&r, cbi.rcButton.right, rc.top, rc.right, rc.bottom); + + if (r.left < r.right) ExtTextOutW(hdc, 0, 0, ETO_OPAQUE, &r, L"", 0, NULL); + SetRect(&r, cbi.rcButton.left, rc.top, cbi.rcButton.right, cbi.rcButton.top); + if (r.top < r.bottom) ExtTextOutW(hdc, 0, 0, ETO_OPAQUE, &r, L"", 0, NULL); + SetRect(&r, cbi.rcButton.left, cbi.rcButton.bottom, cbi.rcButton.right, rc.bottom); + if (r.top < r.bottom) ExtTextOutW(hdc, 0, 0, ETO_OPAQUE, &r, L"", 0, NULL); + + DrawButton(hdc, &cbi.rcButton, IsButtonDown(ws), ctrlActive); + } + else + { + SetRect(&r, cbi.rcItem.right, rc.top, rc.right, rc.bottom); + if (r.left < r.right) ExtTextOutW(hdc, 0, 0, ETO_OPAQUE, &r, L"", 0, NULL); + } + + if (CBS_DROPDOWNLIST == (0x0F & ws)) + { + INT cchText = (INT)SendMessageW(hwnd, WM_GETTEXTLENGTH, 0, 0); + if (cchText) + { + HFONT hFont, hFontOld; + wchar_t szText[COMBO_TEXT_MAX] = {0}; + + SendMessageW(hwnd, WM_GETTEXT, (WPARAM)COMBO_TEXT_MAX, (LPARAM)szText); + hFont = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0L); + if (!hFont) hFont = (HFONT)MlStockObjects_Get(DEFAULT_FONT); + hFontOld = (hFont) ? (HFONT)SelectObject(hdc, hFont) : NULL; + + COLORREF rgbText; + BOOL bFocused = (hwnd == GetFocus() && !SendMessageW(hwnd, CB_GETDROPPEDSTATE, 0, 0L)); + if (bFocused && 0 == (SWCBS_TOOLBAR & style)) + { + rgbText = WADlg_getColor(WADLG_SELBAR_FGCOLOR); + SetBkColor(hdc, WADlg_getColor(WADLG_SELBAR_BGCOLOR)); + } + else rgbText = WADlg_getColor(WADLG_ITEMFG); + if(!IsWindowEnabled(hwnd)) + { + COLORREF rgbBack = GetBkColor(hdc); + rgbText = RGB((GetRValue(rgbText)+GetRValue(rgbBack))/2, + (GetGValue(rgbText)+GetGValue(rgbBack))/2, + (GetBValue(rgbText)+GetBValue(rgbBack))/2); + } + SetTextColor(hdc, rgbText); + ExtTextOutW(hdc, 0, 0, ETO_OPAQUE, &cbi.rcItem, L"", 0, NULL); + if (bFocused && + 0 == (0x01/*UISF_HIDEFOCUS*/ & uiState) && + 0 == (SWCBS_TOOLBAR & style)) + { + COLORREF fg, bk; + fg = SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT)); + bk = SetBkColor(hdc, GetSysColor(COLOR_WINDOW)); + DrawFocusRect(hdc, &cbi.rcItem); + SetTextColor(hdc, fg); + SetBkColor(hdc, bk); + } + + InflateRect(&cbi.rcItem, -1, -1); + DrawTextW(hdc, szText, min(cchText,COMBO_TEXT_MAX), &cbi.rcItem, DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER); + if (hFontOld) SelectObject(hdc, hFontOld); + } + else + { + ExtTextOutW(hdc, 0, 0, ETO_OPAQUE, &cbi.rcItem, L"", 0, NULL); + } + } + } + + EndPaint(hwnd, &ps); +} + +void SkinnedCombobox::OnSkinUpdated(BOOL bNotifyChildren, BOOL bRedraw) +{ + __super::OnSkinUpdated(bNotifyChildren, bRedraw); + + if (SWS_USESKINFONT & style) + { + if (0 == (CBS_OWNERDRAWVARIABLE & GetWindowLongPtrW(hwnd, GWL_STYLE))) + { + HDC hdc = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS); + HFONT hf, hfo; + TEXTMETRIC tm; + hf = (HFONT)SendMessageW(hwnd, WM_GETFONT, 0, 0L); + if (NULL == hf) hf = (HFONT)MlStockObjects_Get(DEFAULT_FONT); + hfo = (HFONT)SelectObject(hdc, hf); + GetTextMetrics(hdc, &tm); + SendMessageW(hwnd, CB_SETITEMHEIGHT, -1, tm.tmHeight + 2); + SendMessageW(hwnd, CB_SETITEMHEIGHT, 0, tm.tmHeight + 2); + SelectObject(hdc, hfo); + ReleaseDC(hwnd, hdc); + + } + } +} +INT SkinnedCombobox::OnNcHitTest(POINTS pts) +{ + INT ht = __super::OnNcHitTest(pts); + + if (ht > 0 && !activeBorder && (SWCBS_TOOLBAR & style) && IsChild(GetActiveWindow(), hwnd)) + { + TRACKMOUSEEVENT track; + track.cbSize = sizeof(TRACKMOUSEEVENT); + track.dwFlags = TME_LEAVE; + track.hwndTrack = hwnd; + TrackMouseEvent(&track); + activeBorder = TRUE; + InvalidateRect(hwnd, NULL, TRUE); + UpdateWindow(hwnd); + } + return ht; +} + + +void SkinnedCombobox::OnMouseLeave(void) +{ + if (!activeBorder) return; + + COMBOBOXINFO cbi; + ZeroMemory(&cbi, sizeof(COMBOBOXINFO)); + cbi.cbSize = sizeof(COMBOBOXINFO); + if (GetComboBoxInfo(hwnd, &cbi) && IsWindowVisible(cbi.hwndList)) + return; + + activeBorder = FALSE; + if (SWCBS_TOOLBAR & style) + { + InvalidateRect(hwnd, NULL, TRUE); + UpdateWindow(hwnd); + } +} +LRESULT SkinnedCombobox::SilenceMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + LRESULT result; + UpdateWindow(hwnd); + CallDefWndProc(WM_SETREDRAW, FALSE, 0L); + result = __super::WindowProc(uMsg, wParam, lParam); + CallDefWndProc(WM_SETREDRAW, TRUE, 0L); + InvalidateRect(hwnd, NULL, TRUE); + return result; +} + +static HWND hwndPreviousFocus = NULL; + +LRESULT SkinnedCombobox::WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (SWCBS_TOOLBAR & style) + { + switch(uMsg) + { + case WM_SETFOCUS: + hwndPreviousFocus = (HWND)wParam; + break; + case REFLECTED_COMMAND: + switch(HIWORD(wParam)) + { + case CBN_CLOSEUP: + { + if (NULL != hwndPreviousFocus && hwnd == GetFocus()) + { + do + { + if (IsWindowVisible(hwndPreviousFocus) && IsWindowEnabled(hwndPreviousFocus)) + { + SetFocus(hwndPreviousFocus); + break; + } + } while (NULL != (hwndPreviousFocus = GetAncestor(hwndPreviousFocus, GA_PARENT))); + + } + hwndPreviousFocus = NULL; + } + + break; + + } + break; + } + } + if (SWS_USESKINCOLORS & style) + { + switch(uMsg) + { + case WM_PAINT: OnPaint(); return 0; + case WM_ERASEBKGND: return 0; + case WM_MOUSELEAVE: OnMouseLeave(); break; + + case WM_KILLFOCUS: + case WM_SETFOCUS: + case WM_COMMAND: + case WM_CAPTURECHANGED: + case 0x0128/*WM_UPDATEUISTATE*/: + SilenceMessage(uMsg, wParam, lParam); + return 0; + case WM_LBUTTONUP: + if (activeBorder && (SWCBS_TOOLBAR & style)) + { + TRACKMOUSEEVENT track; + track.cbSize = sizeof(TRACKMOUSEEVENT); + track.dwFlags = TME_LEAVE; + track.hwndTrack = hwnd; + TrackMouseEvent(&track); + + POINT pt; + pt.x = GET_X_LPARAM(lParam); + pt.y = GET_Y_LPARAM(lParam); + RECT rw; + if (GetWindowRect(hwnd, &rw)) + { + MapWindowPoints(hwnd, HWND_DESKTOP, &pt, 1); + if (!PtInRect(&rw, pt)) + { + INPUT pi[2]; + ZeroMemory(&pi[0], sizeof(INPUT)); + pi[0].type = INPUT_MOUSE; + pi[0].mi.dx = pt.x; + pi[0].mi.dy = pt.y; + pi[0].mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTDOWN; + CopyMemory(&pi[1], &pi[0], sizeof(INPUT)); + pi[1].mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTUP; + SendInput(2, pi, sizeof(INPUT)); + } + } + + } + break; + case WM_LBUTTONDOWN: + if (!activeBorder && (SWCBS_TOOLBAR & style)) + { + TRACKMOUSEEVENT track; + track.cbSize = sizeof(TRACKMOUSEEVENT); + track.dwFlags = TME_LEAVE; + track.hwndTrack = hwnd; + TrackMouseEvent(&track); + activeBorder = TRUE; + } + break; + } + } + return __super::WindowProc(uMsg, wParam, lParam); +}
\ No newline at end of file |