summaryrefslogtreecommitdiff
path: root/alf/alfcombobox.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'alf/alfcombobox.cpp')
-rw-r--r--alf/alfcombobox.cpp153
1 files changed, 94 insertions, 59 deletions
diff --git a/alf/alfcombobox.cpp b/alf/alfcombobox.cpp
index 6d3af5e..994806e 100644
--- a/alf/alfcombobox.cpp
+++ b/alf/alfcombobox.cpp
@@ -17,6 +17,38 @@ typedef struct {
DWORD comboStyle;
} ALFComboCreateParams;
+typedef struct {
+ HWND hwndChild;
+ int dpi;
+} ALFComboPriv;
+
+static ALFComboPriv *
+ALF_Combo_InitializePriv(HWND hwnd, ALFComboCreateParams *params)
+{
+ ALFComboPriv *priv = ALF_New(ALFComboPriv, 1);
+ priv->dpi = 96;
+
+ DWORD comboStyle = params->comboStyle | CBS_OWNERDRAWFIXED | CBS_HASSTRINGS;
+
+ priv->hwndChild = CreateWindowEx(0,
+ TEXT("COMBOBOX"),
+ TEXT(""),
+ WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_TABSTOP | comboStyle,
+ 0, 0, 100, 200 /* FIXME needed for commctl32 v5, what is the best value here? */,
+ hwnd,
+ (HMENU) GetWindowLongPtrW(hwnd, GWLP_ID),
+ ALF_HINSTANCE,
+ NULL);
+
+ return priv;
+}
+
+static void
+ALF_Combo_FreePriv(ALFComboPriv *priv)
+{
+ ALF_Free(priv);
+}
+
static int
ALF__ComboItemHeight(HWND hwnd)
{
@@ -48,83 +80,80 @@ ALF__ComboItemHeight(HWND hwnd)
static LRESULT CALLBACK
ALF__ComboWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
- HWND hwndChild = (HWND)GetWindowLongPtr(hwnd, 0);
+ ALFComboPriv *priv = (ALFComboPriv *)GetWindowLongPtr(hwnd, 0);
if (uMsg == WM_CREATE) {
ALFComboCreateParams *params = (ALFComboCreateParams*)((CREATESTRUCT*)lParam)->lpCreateParams;
- DWORD comboStyle = params->comboStyle | CBS_OWNERDRAWFIXED | CBS_HASSTRINGS;
-
- HWND hwndCombo = CreateWindowEx(0,
- TEXT("COMBOBOX"),
- TEXT(""),
- WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_TABSTOP | comboStyle,
- 0, 0, 100, 200 /* FIXME needed for commctl32 v5, what is the best value here? */,
- hwnd,
- (HMENU) GetWindowLongPtrW(hwnd, GWLP_ID),
- ((CREATESTRUCT*)lParam)->hInstance,
- NULL);
-
- SetWindowLongPtr(hwnd, 0, (LONG_PTR)hwndCombo);
+
+ priv = ALF_Combo_InitializePriv(hwnd, params);
+ SetWindowLongPtr(hwnd, 0, (LONG_PTR)priv);
+ }
+
+ if (uMsg == WM_DESTROY) {
+ ALF_Combo_FreePriv(priv);
+ priv = NULL;
+ SetWindowLongPtr(hwnd, 0, 0);
}
- if (uMsg == WM_ENABLE && hwndChild) {
- EnableWindow(hwndChild, (BOOL)wParam);
+
+ if (uMsg == WM_ENABLE && priv) {
+ EnableWindow(priv->hwndChild, (BOOL)wParam);
return 0;
}
- if (uMsg == WM_SETTEXT && hwndChild) {
- SetWindowText(hwndChild, (TCHAR*)lParam);
+ if (uMsg == WM_SETTEXT && priv) {
+ SetWindowText(priv->hwndChild, (TCHAR*)lParam);
ALF_InvalidateLayout(GetParent(hwnd));
}
- if (uMsg == WM_GETTEXTLENGTH && hwndChild) {
- return (LRESULT)GetWindowTextLength(hwndChild);
+ if (uMsg == WM_GETTEXTLENGTH && priv) {
+ return (LRESULT)GetWindowTextLength(priv->hwndChild);
}
- if (uMsg == WM_GETTEXT && hwndChild) {
- return GetWindowText(hwndChild, (TCHAR*)lParam, (int)wParam);
+ if (uMsg == WM_GETTEXT && priv) {
+ return GetWindowText(priv->hwndChild, (TCHAR*)lParam, (int)wParam);
}
- if (uMsg == WM_SETFONT && hwndChild) {
- SendMessage(hwndChild, WM_SETFONT, wParam, lParam);
- SendMessage(hwndChild, CB_SETITEMHEIGHT, (WPARAM)0, (LPARAM)ALF__ComboItemHeight(hwnd));
+ if (uMsg == WM_SETFONT && priv) {
+ SendMessage(priv->hwndChild, WM_SETFONT, wParam, lParam);
+ SendMessage(priv->hwndChild, CB_SETITEMHEIGHT, (WPARAM)0, (LPARAM)ALF__ComboItemHeight(hwnd));
ALF_InvalidateLayout(GetParent(hwnd));
return 0;
}
- if (uMsg == WM_GETFONT && hwndChild) {
- return SendMessage(hwndChild, WM_GETFONT, wParam, lParam);
+ if (uMsg == WM_GETFONT && priv) {
+ return SendMessage(priv->hwndChild, WM_GETFONT, wParam, lParam);
}
- if (uMsg == ALF_CB_GETSTYLE && hwndChild) {
- return GetWindowLong(hwndChild, GWL_STYLE);
+ if (uMsg == ALF_CB_GETSTYLE && priv) {
+ return GetWindowLong(priv->hwndChild, GWL_STYLE);
}
- if ((uMsg == ALF_CB_FINDSTRINGEXACT || uMsg == CB_FINDSTRINGEXACT) && hwndChild) {
- return SendMessage(hwndChild, CB_FINDSTRINGEXACT, wParam, lParam);
+ if ((uMsg == ALF_CB_FINDSTRINGEXACT || uMsg == CB_FINDSTRINGEXACT) && priv) {
+ return SendMessage(priv->hwndChild, CB_FINDSTRINGEXACT, wParam, lParam);
}
- if ((uMsg == ALF_CB_ADDSTRING || uMsg == CB_ADDSTRING) && hwndChild) {
- return SendMessage(hwndChild, CB_ADDSTRING, wParam, lParam);
+ if ((uMsg == ALF_CB_ADDSTRING || uMsg == CB_ADDSTRING) && priv) {
+ return SendMessage(priv->hwndChild, CB_ADDSTRING, wParam, lParam);
}
- if ((uMsg == ALF_CB_INSERTSTRING || uMsg == CB_INSERTSTRING) && hwndChild) {
- return SendMessage(hwndChild, CB_INSERTSTRING, wParam, lParam);
+ if ((uMsg == ALF_CB_INSERTSTRING || uMsg == CB_INSERTSTRING) && priv) {
+ return SendMessage(priv->hwndChild, CB_INSERTSTRING, wParam, lParam);
}
- if ((uMsg == ALF_CB_DELETESTRING || uMsg == CB_DELETESTRING) && hwndChild) {
- return SendMessage(hwndChild, CB_DELETESTRING, wParam, lParam);
+ if ((uMsg == ALF_CB_DELETESTRING || uMsg == CB_DELETESTRING) && priv) {
+ return SendMessage(priv->hwndChild, CB_DELETESTRING, wParam, lParam);
}
- if ((uMsg == ALF_CB_GETCURSEL || uMsg == CB_GETCURSEL) && hwndChild) {
- return SendMessage(hwndChild, CB_GETCURSEL, wParam, lParam);
+ if ((uMsg == ALF_CB_GETCURSEL || uMsg == CB_GETCURSEL) && priv) {
+ return SendMessage(priv->hwndChild, CB_GETCURSEL, wParam, lParam);
}
- if ((uMsg == ALF_CB_SETCURSEL || uMsg == CB_SETCURSEL) && hwndChild) {
- LRESULT curSel = SendMessage(hwndChild, CB_GETCURSEL, 0, 0);
+ if ((uMsg == ALF_CB_SETCURSEL || uMsg == CB_SETCURSEL) && priv) {
+ LRESULT curSel = SendMessage(priv->hwndChild, CB_GETCURSEL, 0, 0);
if ((WPARAM)curSel != wParam) {
- LRESULT newSel = SendMessage(hwndChild, CB_SETCURSEL, wParam, 0);
- SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(GetWindowLong(hwndChild, GWL_ID), CBN_SELCHANGE), (LPARAM)hwndChild);
+ LRESULT newSel = SendMessage(priv->hwndChild, CB_SETCURSEL, wParam, 0);
+ SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(GetWindowLong(priv->hwndChild, GWL_ID), CBN_SELCHANGE), (LPARAM)priv->hwndChild);
return newSel;
}
}
- if ((uMsg == ALF_CB_GETLBTEXTLEN || uMsg == CB_GETLBTEXTLEN) && hwndChild) {
- return SendMessage(hwndChild, CB_GETLBTEXTLEN, wParam, lParam);
+ if ((uMsg == ALF_CB_GETLBTEXTLEN || uMsg == CB_GETLBTEXTLEN) && priv) {
+ return SendMessage(priv->hwndChild, CB_GETLBTEXTLEN, wParam, lParam);
}
- if ((uMsg == ALF_CB_GETLBTEXT || uMsg == CB_GETLBTEXT) && hwndChild) {
- return SendMessage(hwndChild, CB_GETLBTEXT, wParam, lParam);
+ if ((uMsg == ALF_CB_GETLBTEXT || uMsg == CB_GETLBTEXT) && priv) {
+ return SendMessage(priv->hwndChild, CB_GETLBTEXT, wParam, lParam);
}
- if (uMsg == WM_COMMAND && (HWND)lParam == hwndChild) {
+ if (uMsg == WM_COMMAND && priv && (HWND)lParam == priv->hwndChild) {
// XXX: for whatever reason, Win95 (and only win95 - doesn't happen on NT)
// sends a wrong ID value in WPARAM. We fix it by replacing it with our own id.
return SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(GetWindowLong(hwnd, GWL_ID), HIWORD(wParam)), (LPARAM)hwnd);
@@ -143,12 +172,12 @@ ALF__ComboWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
if (GetTextMetrics(hDc, &tm)) {
SIZE *ps = (SIZE*)lParam;
if (!ps->cx) {
- ps->cx = ALF_CentipointsToPixels(GetParent(hwnd), 12000);
+ ps->cx = ALF_CentipointsToPixels(12000, priv->dpi);
}
if (!ps->cy) {
ps->cy = tm.tmHeight + 2*ALF_Compat_GetSystemMetricsForDpi(
- SM_CYEDGE, (UINT)ALF_CentipointsToPixels(GetParent(hwnd), 7200))
+ SM_CYEDGE, (UINT)priv->dpi)
+ 4 /* padding internal to the edit control */;
}
}
@@ -225,30 +254,36 @@ ALF__ComboWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
return TRUE;
}
- if (uMsg == WM_WINDOWPOSCHANGED && hwndChild) {
+ if (uMsg == WM_WINDOWPOSCHANGED && priv) {
WINDOWPOS *pos = (WINDOWPOS *)lParam;
if (!(pos->flags & SWP_NOSIZE)) {
// XXX: When resizing the combo box, it will improperly draw a selection.
// this appears to be a well-known bug that is still not fixed, even in Win10.
// workaround based on https://stackoverflow.com/questions/49603893/how-to-deal-with-invalidly-painted-combobox-control-in-win32-winapi
- LRESULT sel = SendMessage(hwndChild, CB_GETEDITSEL, 0, 0);
- SendMessage(hwndChild, CB_SETEDITSEL, 0, -1);
+ LRESULT sel = SendMessage(priv->hwndChild, CB_GETEDITSEL, 0, 0);
+ SendMessage(priv->hwndChild, CB_SETEDITSEL, 0, -1);
// SWP_NOCOPYBITS because NT 3.51 doesn't properly repaint the drop-down button
- SetWindowPos(hwndChild, NULL, 0, 0, pos->cx, 200, SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOCOPYBITS);
- SendMessage(hwndChild, CB_SETEDITSEL, 0, (LPARAM)sel);
+ SetWindowPos(priv->hwndChild, NULL, 0, 0, pos->cx, 200, SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOCOPYBITS);
+ SendMessage(priv->hwndChild, CB_SETEDITSEL, 0, (LPARAM)sel);
int heightOffset = 0;
if (ALF_Compat_IsMinWindowsVersion(4, 0)) {
heightOffset = - 2*ALF_Compat_GetSystemMetricsForDpi(
- SM_CYEDGE, (UINT)ALF_CentipointsToPixels(GetParent(hwnd), 7200))
+ SM_CYEDGE, (UINT)priv->dpi)
- 2;
}
- SendMessage(hwndChild, CB_SETITEMHEIGHT, (WPARAM)-1, pos->cy + heightOffset);
- SendMessage(hwndChild, CB_SETITEMHEIGHT, (WPARAM)0, (LPARAM)ALF__ComboItemHeight(hwnd));
+ SendMessage(priv->hwndChild, CB_SETITEMHEIGHT, (WPARAM)-1, pos->cy + heightOffset);
+ SendMessage(priv->hwndChild, CB_SETITEMHEIGHT, (WPARAM)0, (LPARAM)ALF__ComboItemHeight(hwnd));
}
}
+ if (uMsg == ALF_WM_DPICHANGE && priv) {
+ priv->dpi = (int)lParam;
+ ALF_InvalidateLayout(GetParent(hwnd));
+ return TRUE;
+ }
+
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
@@ -295,7 +330,7 @@ ALF_InternalAddComboBox(HWND win, WORD id, int x, int y, DWORD style, const TCHA
if (defaultText)
SetWindowText(hwndCombo, defaultText);
- ALF_AddWidget(win, x, y, hwndCombo, 0, 0, ALF_LAYOUT_SIZE_QUERY | ALF_LAYOUT_INHERITFONT);
+ ALF_AddWidget(win, x, y, hwndCombo, 0, 0, ALF_LAYOUT_SIZE_QUERY | ALF_LAYOUT_INHERITFONT | ALF_LAYOUT_SENDDPICHANGE);
return hwndCombo;
}