From a4a275848f83f3a2a44cdc1f2122cae85e9b71d6 Mon Sep 17 00:00:00 2001 From: Volker Ruppert Date: Mon, 18 Mar 2013 19:08:26 +0000 Subject: [PATCH] initial implementation of scrollable dialog items on WIN32 - scroll window has 16 visible items and the virtual size is not limited - CPUID parameter list now using this feature - FIXME #1: scroll window is not resized if browse button column is present - FIXME #2: only one scroll window per dialog is supported --- bochs/configure.in | 2 +- bochs/gui/scrollwin.cc | 141 +++++++++++++++++++++++++++++++++++++ bochs/gui/scrollwin.h | 27 +++++++ bochs/gui/win32paramdlg.cc | 100 ++++++++++++++++++++++---- 4 files changed, 257 insertions(+), 13 deletions(-) create mode 100644 bochs/gui/scrollwin.cc create mode 100644 bochs/gui/scrollwin.h diff --git a/bochs/configure.in b/bochs/configure.in index 20dd56596..a91d7f921 100644 --- a/bochs/configure.in +++ b/bochs/configure.in @@ -2443,7 +2443,7 @@ case $target in LIBS="$LIBS comctl32.lib" fi fi - DIALOG_OBJS="win32dialog.o win32paramdlg.o" + DIALOG_OBJS="win32dialog.o win32paramdlg.o scrollwin.o" EXPORT_DYNAMIC="" ;; *-cygwin* | *-mingw*) diff --git a/bochs/gui/scrollwin.cc b/bochs/gui/scrollwin.cc new file mode 100644 index 000000000..fd098d192 --- /dev/null +++ b/bochs/gui/scrollwin.cc @@ -0,0 +1,141 @@ +///////////////////////////////////////////////////////////////////////// +// $Id$ +///////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2013 Volker Ruppert +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +#include +#include + +LRESULT CALLBACK ScrollWinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + SCROLLINFO si; + BOOL pull = FALSE, redraw = FALSE; + static int vsize = 0, wsize = 0; + static int starty = 0, scrolly = 0; + int oldy = 0; + RECT R; + + switch (msg) { + case WM_CREATE: + GetClientRect(hwnd, &R); + wsize = R.bottom; + vsize = wsize; + si.cbSize = sizeof(SCROLLINFO); + si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE | SIF_DISABLENOSCROLL; + si.nMin = 0; + si.nMax = vsize - 1; + si.nPage = wsize; + si.nPos = starty; + SetScrollInfo(hwnd, SB_VERT, &si, TRUE); + break; + case WM_VSCROLL: + oldy = starty; + switch (LOWORD(wParam)) { + case SB_LINEDOWN: + if (starty < (vsize - wsize)) { + starty++; + redraw = TRUE; + } + break; + case SB_LINEUP: + if (starty > 0) { + starty--; + redraw = TRUE; + } + break; + case SB_PAGEDOWN: + if (starty < (vsize - wsize)) { + starty += wsize; + if (starty > (vsize - wsize)) { + starty = vsize - wsize; + } + redraw = TRUE; + } + break; + case SB_PAGEUP: + if (starty > 0) { + starty -= wsize; + if (starty < 0) starty = 0; + redraw = TRUE; + } + break; + case SB_TOP: + if (starty > 0) { + starty = 0; + redraw = TRUE; + } + break; + case SB_BOTTOM: + starty = vsize - wsize; + redraw = TRUE; + break; + case SB_THUMBPOSITION: + redraw = TRUE; + break; + case SB_THUMBTRACK: + starty = HIWORD(wParam); + SetScrollPos(hwnd, SB_VERT, starty, TRUE); + pull = TRUE; + redraw = (starty != oldy); + break; + } + break; + case WM_USER: + if (wParam == 0x1234) { + vsize = (int)lParam; + si.cbSize = sizeof(SCROLLINFO); + si.fMask = SIF_RANGE | SIF_DISABLENOSCROLL; + si.nMin = 0; + si.nMax = vsize - 1; + SetScrollInfo(hwnd, SB_VERT, &si, TRUE); + redraw = TRUE; + } + break; + } + if (redraw) { + if (!pull) { + SetScrollPos(hwnd, SB_VERT, starty, TRUE); + } + scrolly = oldy - starty; + if (scrolly != 0) { + ScrollWindowEx(hwnd, 0, scrolly, NULL, NULL, NULL, NULL, SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN); + } + return 0; + } else { + return DefWindowProc(hwnd, msg, wParam,lParam); + } +} + +BOOL RegisterScrollWindow(HINSTANCE hinst) +{ + WNDCLASS wc; + + memset(&wc,0,sizeof(WNDCLASS)); + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = (WNDPROC)ScrollWinProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hinst; + wc.hIcon = NULL; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE); + wc.lpszMenuName = NULL; + wc.lpszClassName = "ScrollWin"; + + return (RegisterClass(&wc) != 0); +} diff --git a/bochs/gui/scrollwin.h b/bochs/gui/scrollwin.h new file mode 100644 index 000000000..4b502bca7 --- /dev/null +++ b/bochs/gui/scrollwin.h @@ -0,0 +1,27 @@ +///////////////////////////////////////////////////////////////////////// +// $Id$ +///////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2013 Volker Ruppert +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +#ifndef SCROLLWIN_H + +#define SCROLLWIN_H + +BOOL RegisterScrollWindow(HINSTANCE hinst); + +#endif diff --git a/bochs/gui/win32paramdlg.cc b/bochs/gui/win32paramdlg.cc index 0d0750d72..8bdf84247 100644 --- a/bochs/gui/win32paramdlg.cc +++ b/bochs/gui/win32paramdlg.cc @@ -24,6 +24,7 @@ #include "bochs.h" #include "win32res.h" +#include "scrollwin.h" #define ID_LABEL 100 #define ID_PARAM 1000 @@ -363,6 +364,14 @@ LRESULT CALLBACK EditHexWndProc(HWND Window, UINT msg, WPARAM wParam, LPARAM lPa return CallWindowProc(DefEditWndProc, Window, msg, wParam, lParam); } +BOOL IsScrollWindow(HWND hwnd) +{ + char classname[80]; + + GetClassName(hwnd, classname, 80); + return (!lstrcmp(classname, "ScrollWin")); +} + HWND CreateLabel(HWND hDlg, UINT cid, UINT xpos, UINT ypos, UINT width, BOOL hide, const char *text) { HWND Label; @@ -374,7 +383,11 @@ HWND CreateLabel(HWND hDlg, UINT cid, UINT xpos, UINT ypos, UINT width, BOOL hid r.top = ypos + 2; r.right = r.left + width; r.bottom = r.top + 16; - MapDialogRect(hDlg, &r); + if (IsScrollWindow(hDlg)) { + MapDialogRect(GetParent(hDlg), &r); + } else { + MapDialogRect(hDlg, &r); + } Label = CreateWindow("STATIC", text, WS_CHILD, r.left, r.top, r.right-r.left+1, r.bottom-r.top+1, hDlg, (HMENU)code, NULL, NULL); SendMessage(Label, WM_SETFONT, (WPARAM)DlgFont, TRUE); ShowWindow(Label, hide ? SW_HIDE : SW_SHOW); @@ -446,7 +459,11 @@ HWND CreateBrowseButton(HWND hDlg, UINT cid, UINT xpos, UINT ypos, BOOL hide) r.top = ypos; r.right = r.left + 50; r.bottom = r.top + 14; - MapDialogRect(hDlg, &r); + if (IsScrollWindow(hDlg)) { + MapDialogRect(GetParent(hDlg), &r); + } else { + MapDialogRect(hDlg, &r); + } Button = CreateWindow("BUTTON", "Browse...", WS_CHILD, r.left, r.top, r.right-r.left+1, r.bottom-r.top+1, hDlg, (HMENU)code, NULL, NULL); SendMessage(Button, WM_SETFONT, (WPARAM)DlgFont, TRUE); ShowWindow(Button, hide ? SW_HIDE : SW_SHOW); @@ -464,7 +481,11 @@ HWND CreateCheckbox(HWND hDlg, UINT cid, UINT xpos, UINT ypos, BOOL hide, bx_par r.top = ypos; r.right = r.left + 20; r.bottom = r.top + 14; - MapDialogRect(hDlg, &r); + if (IsScrollWindow(hDlg)) { + MapDialogRect(GetParent(hDlg), &r); + } else { + MapDialogRect(hDlg, &r); + } Checkbox = CreateWindow("BUTTON", "", BS_AUTOCHECKBOX | WS_CHILD | WS_TABSTOP, r.left, r.top, r.right-r.left+1, r.bottom-r.top+1, hDlg, (HMENU)code, NULL, NULL); @@ -510,7 +531,11 @@ HWND CreateInput(HWND hDlg, UINT cid, UINT xpos, UINT ypos, BOOL hide, bx_param_ r.top = ypos; r.right = r.left + 100; r.bottom = r.top + 14; - MapDialogRect(hDlg, &r); + if (IsScrollWindow(hDlg)) { + MapDialogRect(GetParent(hDlg), &r); + } else { + MapDialogRect(hDlg, &r); + } Input = CreateWindowEx(WS_EX_CLIENTEDGE | WS_EX_NOPARENTNOTIFY, "EDIT", buffer, style, r.left, r.top, r.right-r.left+1, r.bottom-r.top+1, hDlg, (HMENU)code, NULL, NULL); @@ -541,7 +566,11 @@ HWND CreateCombobox(HWND hDlg, UINT cid, UINT xpos, UINT ypos, BOOL hide, bx_par r.top = ypos; r.right = r.left + 100; r.bottom = r.top + 14 * ((int)(eparam->get_max() - eparam->get_min()) + 1); - MapDialogRect(hDlg, &r); + if (IsScrollWindow(hDlg)) { + MapDialogRect(GetParent(hDlg), &r); + } else { + MapDialogRect(hDlg, &r); + } Combo = CreateWindow("COMBOBOX", "", WS_CHILD | WS_TABSTOP | WS_VSCROLL | CBS_DROPDOWNLIST, r.left, r.top, r.right-r.left+1, r.bottom-r.top+1, hDlg, (HMENU)code, NULL, NULL); j = 0; @@ -557,6 +586,25 @@ HWND CreateCombobox(HWND hDlg, UINT cid, UINT xpos, UINT ypos, BOOL hide, bx_par return Combo; } + +HWND CreateScrollWindow(HWND hDlg, int xpos, int ypos, int width, int height) +{ + RECT r; + HWND scrollwin; + + r.left = xpos; + r.top = ypos; + r.right = r.left + width; + r.bottom = r.top + height; + MapDialogRect(hDlg, &r); + scrollwin = CreateWindowEx(WS_EX_CLIENTEDGE | WS_EX_CONTROLPARENT, "ScrollWin", + "scrollwin", WS_CHILD | WS_CLIPCHILDREN | WS_TABSTOP | WS_VSCROLL, + r.left, r.top, r.right-r.left+1, r.bottom-r.top+1, + hDlg, NULL, NULL, NULL); + ShowWindow(scrollwin, SW_SHOW); + return scrollwin; +} + void EnableParam(HWND hDlg, UINT cid, bx_param_c *param, BOOL val) { HWND Button, Updown; @@ -617,6 +665,8 @@ SIZE CreateParamList(HWND hDlg, UINT lid, UINT xpos, UINT ypos, BOOL hide, bx_li int options; UINT cid, i, items, lw, w1, x0, x1, x2, y; BOOL ihide; + HWND scrollwin = NULL, hParent; + RECT vrect; items = list->get_size(); options = list->get_options(); @@ -626,6 +676,10 @@ SIZE CreateParamList(HWND hDlg, UINT lid, UINT xpos, UINT ypos, BOOL hide, bx_li if (options & list->USE_TAB_WINDOW) { y = ypos + 15; size.cy = 18; + } else if (options & list->USE_SCROLL_WINDOW) { + x0 = 5; + y = 5; + size.cy = 8; } else { y = ypos + 10; size.cy = 13; @@ -649,6 +703,16 @@ SIZE CreateParamList(HWND hDlg, UINT lid, UINT xpos, UINT ypos, BOOL hide, bx_li if (size.cx < (int)(x2 + 5)) { size.cx = x2 + 5; } + if ((items > 16) && (options & list->USE_SCROLL_WINDOW)) { + size.cx += 20; + scrollwin = CreateScrollWindow(hDlg, xpos, ypos, size.cx, 325); + vrect.left = vrect.top = 0; + vrect.right = size.cx; + vrect.bottom = size.cy; + hParent = scrollwin; + } else { + hParent = hDlg; + } // create controls for (i = 0; i < items; i++) { param = list->get(i); @@ -669,18 +733,18 @@ SIZE CreateParamList(HWND hDlg, UINT lid, UINT xpos, UINT ypos, BOOL hide, bx_li } } else { lw = GetLabelText(param, list, buffer); - /* HWND ltext = */ CreateLabel(hDlg, cid, x0, y, w1, hide, buffer); + CreateLabel(hParent, cid, x0, y, w1, hide, buffer); if (param->get_type() == BXT_PARAM_BOOL) { - /* HWND control = */ CreateCheckbox(hDlg, cid, x1, y, hide, (bx_param_bool_c*)param); + CreateCheckbox(hParent, cid, x1, y, hide, (bx_param_bool_c*)param); } else if (param->get_type() == BXT_PARAM_ENUM) { - /* HWND control = */ CreateCombobox(hDlg, cid, x1, y, hide, (bx_param_enum_c*)param); + CreateCombobox(hParent, cid, x1, y, hide, (bx_param_enum_c*)param); } else if (param->get_type() == BXT_PARAM_NUM) { - /* HWND control = */ CreateInput(hDlg, cid, x1, y, hide, param); + CreateInput(hParent, cid, x1, y, hide, param); } else if (param->get_type() == BXT_PARAM_STRING) { - /* HWND control = */ CreateInput(hDlg, cid, x1, y, hide, param); + CreateInput(hParent, cid, x1, y, hide, param); sparam = (bx_param_string_c*)param; if (sparam->get_options() & sparam->IS_FILENAME) { - /* HWND browse = */ CreateBrowseButton(hDlg, cid, x2, y, hide); + CreateBrowseButton(hParent, cid, x2, y, hide); if (size.cx < (int)(x2 + 60)) { size.cx = x2 + 60; } @@ -690,13 +754,21 @@ SIZE CreateParamList(HWND hDlg, UINT lid, UINT xpos, UINT ypos, BOOL hide, bx_li EnableParam(hDlg, cid, param, FALSE); } y += 20; - size.cy += 20; + if ((scrollwin == NULL) || (i < 16)) { + size.cy += 20; + } + if (scrollwin != NULL) { + vrect.bottom += 20; + } } } cid++; } if (options & list->USE_TAB_WINDOW) { CreateTabControl(hDlg, lid, xpos, ypos, size, hide, list); + } else if (scrollwin != NULL) { + MapDialogRect(hDlg, &vrect); + SendMessage(scrollwin, WM_USER, 0x1234, vrect.bottom); } else { CreateGroupbox(hDlg, lid, xpos, ypos, size, hide, list); } @@ -717,6 +789,9 @@ void SetParamList(HWND hDlg, bx_list_c *list) lid = findDlgListBaseID(list); items = list->get_size(); + if (list->get_options() & list->USE_SCROLL_WINDOW) { + hDlg = FindWindowEx(hDlg, NULL, "ScrollWin", NULL); + } for (i = 0; i < items; i++) { cid = lid + i; param = list->get(i); @@ -975,6 +1050,7 @@ int win32ParamDialog(HWND parent, const char *menu) INT_PTR ret; InitDlgFont(); + RegisterScrollWindow(NULL); ret = DialogBoxParam(NULL, MAKEINTRESOURCE(PARAM_DLG), parent, (DLGPROC)ParamDlgProc, (LPARAM)menu); DeleteObject(DlgFont); return ret;