aboutsummaryrefslogtreecommitdiff
path: root/Src/Plugins/General/gen_ml/skinnedcombo.cpp
diff options
context:
space:
mode:
authorJean-Francois Mauguit <jfmauguit@mac.com>2024-09-24 09:03:25 -0400
committerGitHub <noreply@github.com>2024-09-24 09:03:25 -0400
commitbab614c421ed7ae329d26bf028c4a3b1d2450f5a (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Plugins/General/gen_ml/skinnedcombo.cpp
parent4bde6044fddf053f31795b9eaccdd2a5a527d21f (diff)
parent20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (diff)
downloadwinamp-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.cpp444
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