diff options
| author | Jonas Kümmerlin <jonas@kuemmerlin.eu> | 2020-04-23 15:07:21 +0200 |
|---|---|---|
| committer | Jonas Kümmerlin <jonas@kuemmerlin.eu> | 2020-04-23 15:07:21 +0200 |
| commit | 51daba89072cb66fe5e43015484a554555a40499 (patch) | |
| tree | 372502daebee3c3f3b2cfa68047e03f164f3d95c /alf/alfcombobox.cpp | |
| parent | d17d8f49777d802b56aa332077afbfa83af691e1 (diff) | |
changed DPI handling: dpi is now pushed into every control and saved there
Diffstat (limited to 'alf/alfcombobox.cpp')
| -rw-r--r-- | alf/alfcombobox.cpp | 153 |
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; } |
