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
This commit is contained in:
Volker Ruppert 2013-03-18 19:08:26 +00:00
parent 0dfd73dd15
commit a4a275848f
4 changed files with 257 additions and 13 deletions

View File

@ -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*)

141
bochs/gui/scrollwin.cc Normal file
View File

@ -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 <windows.h>
#include <commctrl.h>
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);
}

27
bochs/gui/scrollwin.h Normal file
View File

@ -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

View File

@ -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;