/* Copyright (c) Alex Kompel, 2002 */
/* NetHack may be freely redistributed. See license for details. */
+#include "win10.h"
#include "winMS.h"
#include <assert.h>
#include "resource.h"
#define DEFAULT_COLOR_BG_MENU COLOR_WINDOW
#define DEFAULT_COLOR_FG_MENU COLOR_WINDOWTEXT
+#define CHECK_WIDTH 16
+#define CHECK_HEIGHT 16
+
typedef struct mswin_menu_item {
int glyph;
ANY_P identifier;
HBITMAP bmpChecked;
HBITMAP bmpCheckedCount;
HBITMAP bmpNotChecked;
+ HDC bmpDC;
BOOL is_active;
} NHMenuWindow, *PNHMenuWindow;
/* If we just used the permanent inventory window to pick something,
* set the menu back to its display inventory state.
*/
- if (flags.perm_invent && mswin_winid_from_handle(hWnd) == WIN_INVEN
+ if (iflags.perm_invent && mswin_winid_from_handle(hWnd) == WIN_INVEN
&& how != PICK_NONE) {
data->menu.prompt[0] = '\0';
SetMenuListType(hWnd, PICK_NONE);
INT_PTR CALLBACK
MenuWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
- PNHMenuWindow data;
- HWND control;
- HDC hdc;
+ PNHMenuWindow data = (PNHMenuWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA);
+ HWND control = GetDlgItem(hWnd, IDC_MENU_TEXT);
TCHAR title[MAX_LOADSTRING];
- data = (PNHMenuWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA);
switch (message) {
- case WM_INITDIALOG:
+ case WM_INITDIALOG: {
+
+ HDC hdc = GetDC(control);
data = (PNHMenuWindow) malloc(sizeof(NHMenuWindow));
ZeroMemory(data, sizeof(NHMenuWindow));
data->type = MENU_TYPE_TEXT;
LoadBitmap(GetNHApp()->hApp, MAKEINTRESOURCE(IDB_MENU_SEL_COUNT));
data->bmpNotChecked =
LoadBitmap(GetNHApp()->hApp, MAKEINTRESOURCE(IDB_MENU_UNSEL));
+ data->bmpDC = CreateCompatibleDC(hdc);
data->is_active = FALSE;
SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) data);
/* set font for the text cotrol */
- control = GetDlgItem(hWnd, IDC_MENU_TEXT);
- hdc = GetDC(control);
+ cached_font * font = mswin_get_font(NHW_MENU, ATR_NONE, hdc, FALSE);
SendMessage(control, WM_SETFONT,
- (WPARAM) mswin_get_font(NHW_MENU, ATR_NONE, hdc, FALSE),
+ (WPARAM) font->hFont,
(LPARAM) 0);
ReleaseDC(control, hdc);
/* set focus to text control for now */
SetFocus(control);
+ }
return FALSE;
case WM_MSNH_COMMAND:
GetWindowRect(hWnd, &rt);
ScreenToClient(GetNHApp()->hMainWnd, (LPPOINT) &rt);
ScreenToClient(GetNHApp()->hMainWnd, ((LPPOINT) &rt) + 1);
- if (flags.perm_invent && mswin_winid_from_handle(hWnd) == WIN_INVEN)
+ if (iflags.perm_invent && mswin_winid_from_handle(hWnd) == WIN_INVEN)
mswin_update_window_placement(NHW_INVEN, &rt);
else
mswin_update_window_placement(NHW_MENU, &rt);
GetWindowRect(hWnd, &rt);
ScreenToClient(GetNHApp()->hMainWnd, (LPPOINT) &rt);
ScreenToClient(GetNHApp()->hMainWnd, ((LPPOINT) &rt) + 1);
- if (flags.perm_invent && mswin_winid_from_handle(hWnd) == WIN_INVEN)
+ if (iflags.perm_invent && mswin_winid_from_handle(hWnd) == WIN_INVEN)
mswin_update_window_placement(NHW_INVEN, &rt);
else
mswin_update_window_placement(NHW_MENU, &rt);
case WM_DESTROY:
if (data) {
+ DeleteDC(data->bmpDC);
DeleteObject(data->bmpChecked);
DeleteObject(data->bmpCheckedCount);
DeleteObject(data->bmpNotChecked);
/* calculate dimensions of the added line of text */
hdc = GetDC(text_view);
- saveFont =
- SelectObject(hdc, mswin_get_font(NHW_MENU, ATR_NONE, hdc, FALSE));
+ cached_font * font = mswin_get_font(NHW_MENU, ATR_NONE, hdc, FALSE);
+ saveFont = SelectObject(hdc, font->hFont);
SetRect(&text_rt, 0, 0, 0, 0);
- DrawText(hdc, msg_data->text, strlen(msg_data->text), &text_rt,
+ DrawTextA(hdc, msg_data->text, strlen(msg_data->text), &text_rt,
DT_CALCRECT | DT_TOP | DT_LEFT | DT_NOPREFIX
| DT_SINGLELINE);
data->text.text_box_size.cx =
/* calculate tabstop size */
hDC = GetDC(hWnd);
- saveFont = SelectObject(
- hDC, mswin_get_font(NHW_MENU, msg_data->attr, hDC, FALSE));
+ cached_font * font = mswin_get_font(NHW_MENU, msg_data->attr, hDC, FALSE);
+ saveFont = SelectObject(hDC, font->hFont);
GetTextMetrics(hDC, &tm);
p1 = data->menu.items[new_item].str;
p = strchr(data->menu.items[new_item].str, '\t');
ZeroMemory(data->menu.prompt, sizeof(data->menu.prompt));
}
} break;
+
+ case MSNH_MSG_RANDOM_INPUT: {
+ PostMessage(GetMenuControl(hWnd),
+ WM_MSNH_COMMAND, MSNH_MSG_RANDOM_INPUT, 0);
+ } break;
+
}
}
/*-----------------------------------------------------------------------------*/
SendMessage(control, WM_SETFONT, (WPARAM) fnt, (LPARAM) 0);
/* add column to the list view */
+ MonitorInfo monitorInfo;
+ win10_monitor_info(hWnd, &monitorInfo);
ZeroMemory(&lvcol, sizeof(lvcol));
lvcol.mask = LVCF_WIDTH | LVCF_TEXT;
- lvcol.cx = GetSystemMetrics(SM_CXFULLSCREEN);
+ lvcol.cx = monitorInfo.width;
lvcol.pszText = NH_A2W(data->menu.prompt, wbuf, BUFSZ);
ListView_InsertColumn(control, 0, &lvcol);
GetClientRect(GetMenuControl(hWnd), &list_rect);
hdc = GetDC(GetMenuControl(hWnd));
- saveFont =
- SelectObject(hdc, mswin_get_font(NHW_MENU, ATR_INVERSE, hdc, FALSE));
+ cached_font * font = mswin_get_font(NHW_MENU, ATR_INVERSE, hdc, FALSE);
+ saveFont = SelectObject(hdc, font->hFont);
GetTextMetrics(hdc, &tm);
/* Set the height of the list box items to max height of the individual
int color = NO_COLOR, attr;
boolean menucolr = FALSE;
+ double monitorScale = win10_monitor_scale(hWnd);
+ int tileXScaled = (int) (TILE_X * monitorScale);
+ int tileYScaled = (int) (TILE_Y * monitorScale);
UNREFERENCED_PARAMETER(wParam);
item = &data->menu.items[lpdis->itemID];
tileDC = CreateCompatibleDC(lpdis->hDC);
- saveFont = SelectObject(
- lpdis->hDC, mswin_get_font(NHW_MENU, item->attr, lpdis->hDC, FALSE));
+ cached_font * font = mswin_get_font(NHW_MENU, item->attr, lpdis->hDC, FALSE);
+ saveFont = SelectObject(lpdis->hDC, font->hFont);
NewBg = menu_bg_brush ? menu_bg_color
: (COLORREF) GetSysColor(DEFAULT_COLOR_BG_MENU);
OldBg = SetBkColor(lpdis->hDC, NewBg);
if (NHMENU_IS_SELECTABLE(*item)) {
char buf[2];
if (data->how != PICK_NONE) {
- HGDIOBJ saveBrush;
- HBRUSH hbrCheckMark;
+ HBITMAP bmpCheck;
+ HBITMAP bmpSaved;
switch (item->count) {
case -1:
- hbrCheckMark = CreatePatternBrush(data->bmpChecked);
+ bmpCheck = data->bmpChecked;
break;
case 0:
- hbrCheckMark = CreatePatternBrush(data->bmpNotChecked);
+ bmpCheck = data->bmpNotChecked;
break;
default:
- hbrCheckMark = CreatePatternBrush(data->bmpCheckedCount);
+ bmpCheck = data->bmpCheckedCount;
break;
}
- y = (lpdis->rcItem.bottom + lpdis->rcItem.top - TILE_Y) / 2;
- SetBrushOrgEx(lpdis->hDC, x, y, NULL);
- saveBrush = SelectObject(lpdis->hDC, hbrCheckMark);
- PatBlt(lpdis->hDC, x, y, TILE_X, TILE_Y, PATCOPY);
- SelectObject(lpdis->hDC, saveBrush);
- DeleteObject(hbrCheckMark);
+ y = (lpdis->rcItem.bottom + lpdis->rcItem.top - tileYScaled) / 2;
+ bmpSaved = SelectBitmap(data->bmpDC, bmpCheck);
+ StretchBlt(lpdis->hDC, x, y, tileXScaled, tileYScaled,
+ data->bmpDC, 0, 0, CHECK_WIDTH, CHECK_HEIGHT, SRCCOPY);
+ SelectObject(data->bmpDC, bmpSaved);
}
- x += TILE_X + spacing;
+ x += tileXScaled + spacing;
if (item->accelerator != 0) {
buf[0] = item->accelerator;
if (iflags.use_menu_color
&& (menucolr = get_menu_coloring(item->str, &color, &attr))) {
- SelectObject(lpdis->hDC,
- mswin_get_font(NHW_MENU, attr, lpdis->hDC, FALSE));
+ cached_font * menu_font = mswin_get_font(NHW_MENU, attr, lpdis->hDC, FALSE);
+ SelectObject(lpdis->hDC, menu_font->hFont);
if (color != NO_COLOR)
SetTextColor(lpdis->hDC, nhcolor_to_RGB(color));
}
}
x += tm.tmAveCharWidth + tm.tmOverhang + spacing;
} else {
- x += TILE_X + tm.tmAveCharWidth + tm.tmOverhang + 2 * spacing;
+ x += tileXScaled + tm.tmAveCharWidth + tm.tmOverhang + 2 * spacing;
}
/* print glyph if present */
if (NHMENU_HAS_GLYPH(*item)) {
if (!IS_MAP_ASCII(iflags.wc_map_mode)) {
HGDIOBJ saveBmp;
+ double monitorScale = win10_monitor_scale(hWnd);
saveBmp = SelectObject(tileDC, GetNHApp()->bmpMapTiles);
ntile = glyph2tile[item->glyph];
t_y =
(ntile / GetNHApp()->mapTilesPerLine) * GetNHApp()->mapTile_Y;
- y = (lpdis->rcItem.bottom + lpdis->rcItem.top
- - GetNHApp()->mapTile_Y) / 2;
+ y = (lpdis->rcItem.bottom + lpdis->rcItem.top - tileYScaled) / 2;
if (GetNHApp()->bmpMapTiles == GetNHApp()->bmpTiles) {
/* using original nethack tiles - apply image transparently */
- (*GetNHApp()->lpfnTransparentBlt)(lpdis->hDC, x, y, TILE_X, TILE_Y,
+ (*GetNHApp()->lpfnTransparentBlt)(lpdis->hDC, x, y,
+ tileXScaled, tileYScaled,
tileDC, t_x, t_y, TILE_X, TILE_Y,
TILE_BK_COLOR);
} else {
/* using custom tiles - simple blt */
- BitBlt(lpdis->hDC, x, y, GetNHApp()->mapTile_X,
- GetNHApp()->mapTile_Y, tileDC, t_x, t_y, SRCCOPY);
+ StretchBlt(lpdis->hDC, x, y, tileXScaled, tileYScaled,
+ tileDC, t_x, t_y, GetNHApp()->mapTile_X, GetNHApp()->mapTile_Y, SRCCOPY);
}
SelectObject(tileDC, saveBmp);
- x += GetNHApp()->mapTile_X;
+ x += tileXScaled;
} else {
const char *sel_ind;
switch (item->count) {
}
} else {
/* no glyph - need to adjust so help window won't look to cramped */
- x += TILE_X;
+ x += tileXScaled;
}
x += spacing;
data->menu.items[lpdis->itemID].count);
}
- SelectObject(lpdis->hDC, mswin_get_font(NHW_MENU, ATR_BLINK,
- lpdis->hDC, FALSE));
+ /* TOOD: add blinking for blink text */
+
+ cached_font * blink_font = mswin_get_font(NHW_MENU, ATR_BLINK, lpdis->hDC, FALSE);
+ SelectObject(lpdis->hDC, blink_font->hFont);
/* calculate text rectangle */
SetRect(&drawRect, client_rt.left, lpdis->rcItem.top,
data = (PNHMenuWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA);
+ is_accelerator = FALSE;
+ for (i = 0; i < data->menu.size; i++) {
+ if (data->menu.items[i].accelerator == ch) {
+ is_accelerator = TRUE;
+ break;
+ }
+ }
+
+ /* Don't use switch if input matched an accelerator. Sometimes
+ * accelerators can conflict with menu actions. For example, when
+ * engraving the extra choice of using fingers matches MENU_UNSELECT_ALL.
+ */
+ if (is_accelerator)
+ goto accelerator;
+
switch (ch) {
case MENU_FIRST_PAGE:
i = 0;
}
} break;
+ accelerator:
default:
if (strchr(data->menu.gacc, ch)
&& !(ch == '0' && data->menu.counting)) {
return -2;
}
- is_accelerator = FALSE;
- for (i = 0; i < data->menu.size; i++) {
- if (data->menu.items[i].accelerator == ch) {
- is_accelerator = TRUE;
- break;
- }
- }
-
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')
|| is_accelerator) {
if (data->how == PICK_ANY || data->how == PICK_ONE) {
LRESULT CALLBACK
NHMenuListWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
+ HWND hWndParent = GetParent(hWnd);
BOOL bUpdateFocusItem;
/* we will redraw focused item whenever horizontal scrolling occurs
SetFocus(GetNHApp()->hMainWnd);
}
return FALSE;
+
+ case WM_MSNH_COMMAND:
+ if (wParam == MSNH_MSG_RANDOM_INPUT) {
+ char c = randomkey();
+ if (c == '\n')
+ PostMessage(hWndParent, WM_COMMAND, MAKELONG(IDOK, 0), 0);
+ else if (c == '\033')
+ PostMessage(hWndParent, WM_COMMAND, MAKELONG(IDCANCEL, 0), 0);
+ else
+ PostMessage(hWnd, WM_CHAR, c, 0);
+ return 0;
+ }
+ break;
+
}
/* update focused item */
LRESULT CALLBACK
NHMenuTextWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
+ HWND hWndParent = GetParent(hWnd);
HDC hDC;
RECT rc;
&& (si.nPos + (int) si.nPage) <= (si.nMax - si.nMin))
SendMessage(hWnd, EM_SCROLL, SB_PAGEDOWN, 0);
else
- PostMessage(GetParent(hWnd), WM_COMMAND, MAKELONG(IDOK, 0),
- 0);
+ PostMessage(hWndParent, WM_COMMAND, MAKELONG(IDOK, 0), 0);
return 0;
}
case VK_NEXT:
case WM_SETFOCUS:
HideCaret(hWnd);
return 0;
+
+ case WM_MSNH_COMMAND:
+ if (wParam == MSNH_MSG_RANDOM_INPUT) {
+ char c = randomkey();
+ if (c == '\n')
+ PostMessage(hWndParent, WM_COMMAND, MAKELONG(IDOK, 0), 0);
+ else if (c == '\033')
+ PostMessage(hWndParent, WM_COMMAND, MAKELONG(IDCANCEL, 0), 0);
+ else
+ PostMessage(hWnd, WM_CHAR, c, 0);
+ return 0;
+ }
+ break;
+
}
if (editControlWndProc)