Win32GUI: Use a back buffer for all status rendering
This eliminates all flickering when status is updated.
This commit is contained in:
committed by
Pasi Kallinen
parent
7c24b420a9
commit
1ec7bed529
+97
-24
@@ -12,6 +12,52 @@
|
|||||||
|
|
||||||
extern COLORREF nhcolor_to_RGB(int c); /* from mhmap */
|
extern COLORREF nhcolor_to_RGB(int c); /* from mhmap */
|
||||||
|
|
||||||
|
typedef struct back_buffer {
|
||||||
|
HWND hWnd;
|
||||||
|
HDC hdc;
|
||||||
|
HBITMAP bm;
|
||||||
|
HBITMAP orig_bm;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
} back_buffer_t;
|
||||||
|
|
||||||
|
void back_buffer_free(back_buffer_t * back_buffer)
|
||||||
|
{
|
||||||
|
if (back_buffer->bm != NULL) {
|
||||||
|
SelectObject(back_buffer->hdc, back_buffer->orig_bm);
|
||||||
|
DeleteObject(back_buffer->bm);
|
||||||
|
back_buffer->bm = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void back_buffer_allocate(back_buffer_t * back_buffer, int width, int height)
|
||||||
|
{
|
||||||
|
HDC hdc = GetDC(back_buffer->hWnd);
|
||||||
|
back_buffer->bm = CreateCompatibleBitmap(hdc, width, height);
|
||||||
|
back_buffer->orig_bm = SelectObject(back_buffer->hdc, back_buffer->bm);
|
||||||
|
back_buffer->width = width;
|
||||||
|
back_buffer->height = height;
|
||||||
|
ReleaseDC(back_buffer->hWnd, hdc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void back_buffer_size(back_buffer_t * back_buffer, int width, int height)
|
||||||
|
{
|
||||||
|
if (back_buffer->bm == NULL || back_buffer->width != width
|
||||||
|
|| back_buffer->height != height) {
|
||||||
|
back_buffer_free(back_buffer);
|
||||||
|
back_buffer_allocate(back_buffer, width, height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void back_buffer_init(back_buffer_t * back_buffer, HWND hWnd, int width, int height)
|
||||||
|
{
|
||||||
|
back_buffer->hWnd = hWnd;
|
||||||
|
back_buffer->hdc = CreateCompatibleDC(NULL);
|
||||||
|
back_buffer->bm = NULL;
|
||||||
|
|
||||||
|
back_buffer_size(back_buffer, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct mswin_nethack_status_window {
|
typedef struct mswin_nethack_status_window {
|
||||||
int index;
|
int index;
|
||||||
char window_text[NHSW_LINES][MAXWINDOWTEXT + 1];
|
char window_text[NHSW_LINES][MAXWINDOWTEXT + 1];
|
||||||
@@ -20,6 +66,7 @@ typedef struct mswin_nethack_status_window {
|
|||||||
boolean *activefields;
|
boolean *activefields;
|
||||||
int *percents;
|
int *percents;
|
||||||
int *colors;
|
int *colors;
|
||||||
|
back_buffer_t back_buffer;
|
||||||
} NHStatusWindow, *PNHStatusWindow;
|
} NHStatusWindow, *PNHStatusWindow;
|
||||||
|
|
||||||
static int fieldorder1[] = { BL_TITLE, BL_STR, BL_DX, BL_CO, BL_IN,
|
static int fieldorder1[] = { BL_TITLE, BL_STR, BL_DX, BL_CO, BL_IN,
|
||||||
@@ -45,6 +92,7 @@ mswin_init_status_window()
|
|||||||
HWND ret;
|
HWND ret;
|
||||||
NHStatusWindow *data;
|
NHStatusWindow *data;
|
||||||
RECT rt;
|
RECT rt;
|
||||||
|
int width, height;
|
||||||
|
|
||||||
if (!run_once) {
|
if (!run_once) {
|
||||||
register_status_window_class();
|
register_status_window_class();
|
||||||
@@ -59,12 +107,14 @@ mswin_init_status_window()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* create status window object */
|
/* create status window object */
|
||||||
|
width = rt.right - rt.left;
|
||||||
|
height = rt.bottom - rt.top;
|
||||||
ret = CreateWindow(szStatusWindowClass, NULL,
|
ret = CreateWindow(szStatusWindowClass, NULL,
|
||||||
WS_CHILD | WS_CLIPSIBLINGS | WS_SIZEBOX,
|
WS_CHILD | WS_CLIPSIBLINGS | WS_SIZEBOX,
|
||||||
rt.left, /* horizontal position of window */
|
rt.left, /* horizontal position of window */
|
||||||
rt.top, /* vertical position of window */
|
rt.top, /* vertical position of window */
|
||||||
rt.right - rt.left, /* window width */
|
width, /* window width */
|
||||||
rt.bottom - rt.top, /* window height */
|
height, /* window height */
|
||||||
GetNHApp()->hMainWnd, NULL, GetNHApp()->hApp, NULL);
|
GetNHApp()->hMainWnd, NULL, GetNHApp()->hApp, NULL);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
panic("Cannot create status window");
|
panic("Cannot create status window");
|
||||||
@@ -80,8 +130,20 @@ mswin_init_status_window()
|
|||||||
ZeroMemory(data, sizeof(NHStatusWindow));
|
ZeroMemory(data, sizeof(NHStatusWindow));
|
||||||
SetWindowLongPtr(ret, GWLP_USERDATA, (LONG_PTR) data);
|
SetWindowLongPtr(ret, GWLP_USERDATA, (LONG_PTR) data);
|
||||||
|
|
||||||
|
back_buffer_init(&data->back_buffer, ret, width, height);
|
||||||
|
|
||||||
mswin_apply_window_style(ret);
|
mswin_apply_window_style(ret);
|
||||||
|
|
||||||
|
if (status_bg_brush == NULL) {
|
||||||
|
status_bg_color = (COLORREF)GetSysColor(DEFAULT_COLOR_BG_STATUS);
|
||||||
|
status_bg_brush = CreateSolidBrush(status_bg_color);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status_fg_brush == NULL) {
|
||||||
|
status_fg_color = (COLORREF)GetSysColor(DEFAULT_COLOR_FG_STATUS);
|
||||||
|
status_fg_brush = CreateSolidBrush(status_fg_color);
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,9 +160,7 @@ register_status_window_class()
|
|||||||
wcex.hInstance = GetNHApp()->hApp;
|
wcex.hInstance = GetNHApp()->hApp;
|
||||||
wcex.hIcon = NULL;
|
wcex.hIcon = NULL;
|
||||||
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
|
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||||
wcex.hbrBackground = status_bg_brush
|
wcex.hbrBackground = NULL;
|
||||||
? status_bg_brush
|
|
||||||
: SYSCLR_TO_BRUSH(DEFAULT_COLOR_BG_STATUS);
|
|
||||||
wcex.lpszMenuName = NULL;
|
wcex.lpszMenuName = NULL;
|
||||||
wcex.lpszClassName = szStatusWindowClass;
|
wcex.lpszClassName = szStatusWindowClass;
|
||||||
|
|
||||||
@@ -216,30 +276,35 @@ onWMPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
|
|||||||
int *f;
|
int *f;
|
||||||
int **fop;
|
int **fop;
|
||||||
SIZE sz;
|
SIZE sz;
|
||||||
HGDIOBJ oldFont, normalFont, boldFont;
|
HGDIOBJ normalFont, boldFont;
|
||||||
TCHAR wbuf[BUFSZ];
|
TCHAR wbuf[BUFSZ];
|
||||||
COLORREF OldBg, OldFg, Bg, Fg;
|
|
||||||
RECT rt;
|
RECT rt;
|
||||||
PAINTSTRUCT ps;
|
PAINTSTRUCT ps;
|
||||||
HDC hdc;
|
HDC hdc;
|
||||||
PNHStatusWindow data;
|
PNHStatusWindow data;
|
||||||
|
int width, height;
|
||||||
|
RECT clear_rect;
|
||||||
|
HDC front_buffer_hdc;
|
||||||
|
|
||||||
data = (PNHStatusWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA);
|
data = (PNHStatusWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA);
|
||||||
|
|
||||||
hdc = BeginPaint(hWnd, &ps);
|
front_buffer_hdc = BeginPaint(hWnd, &ps);
|
||||||
GetClientRect(hWnd, &rt);
|
GetClientRect(hWnd, &rt);
|
||||||
|
|
||||||
|
width = rt.right - rt.left;
|
||||||
|
height = rt.bottom - rt.top;
|
||||||
|
|
||||||
|
back_buffer_size(&data->back_buffer, width, height);
|
||||||
|
|
||||||
|
hdc = data->back_buffer.hdc;
|
||||||
|
|
||||||
normalFont = mswin_get_font(NHW_STATUS, ATR_NONE, hdc, FALSE);
|
normalFont = mswin_get_font(NHW_STATUS, ATR_NONE, hdc, FALSE);
|
||||||
boldFont = mswin_get_font(NHW_STATUS, ATR_BOLD, hdc, FALSE);
|
boldFont = mswin_get_font(NHW_STATUS, ATR_BOLD, hdc, FALSE);
|
||||||
oldFont = SelectObject(hdc, normalFont);
|
|
||||||
|
|
||||||
Bg = status_bg_brush ? status_bg_color
|
SelectObject(hdc, normalFont);
|
||||||
: (COLORREF) GetSysColor(DEFAULT_COLOR_BG_STATUS);
|
|
||||||
OldBg = SetBkColor(hdc, Bg);
|
|
||||||
|
|
||||||
Fg = status_fg_brush ? status_fg_color
|
SetBkColor(hdc, status_bg_color);
|
||||||
: (COLORREF) GetSysColor(DEFAULT_COLOR_FG_STATUS);
|
SetTextColor(hdc, status_fg_color);
|
||||||
OldFg = SetTextColor(hdc, Fg);
|
|
||||||
|
|
||||||
if (iflags.wc2_hitpointbar && BL_HP < data->n_fields
|
if (iflags.wc2_hitpointbar && BL_HP < data->n_fields
|
||||||
&& data->activefields[BL_HP]) {
|
&& data->activefields[BL_HP]) {
|
||||||
@@ -247,6 +312,13 @@ onWMPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
|
|||||||
hpbar_color = data->colors[BL_HP] & 0x00ff;
|
hpbar_color = data->colors[BL_HP] & 0x00ff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clear_rect.left = 0;
|
||||||
|
clear_rect.top = 0;
|
||||||
|
clear_rect.right = width;
|
||||||
|
clear_rect.bottom = height;
|
||||||
|
|
||||||
|
FillRect(hdc, &clear_rect, status_bg_brush);
|
||||||
|
|
||||||
for (fop = fieldorders; *fop; fop++) {
|
for (fop = fieldorders; *fop; fop++) {
|
||||||
LONG left = rt.left;
|
LONG left = rt.left;
|
||||||
LONG cy = 0;
|
LONG cy = 0;
|
||||||
@@ -275,9 +347,10 @@ onWMPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
|
|||||||
else if (atr & HL_DIM)
|
else if (atr & HL_DIM)
|
||||||
fntatr = ATR_DIM;
|
fntatr = ATR_DIM;
|
||||||
fnt = mswin_get_font(NHW_STATUS, fntatr, hdc, FALSE);
|
fnt = mswin_get_font(NHW_STATUS, fntatr, hdc, FALSE);
|
||||||
nFg = (clr == NO_COLOR ? Fg :
|
nFg = (clr == NO_COLOR ? status_fg_color
|
||||||
((clr >= 0 && clr < CLR_MAX) ? nhcolor_to_RGB(clr) : Fg));
|
: ((clr >= 0 && clr < CLR_MAX) ? nhcolor_to_RGB(clr)
|
||||||
nBg = Bg;
|
: status_fg_color));
|
||||||
|
nBg = status_bg_color;
|
||||||
|
|
||||||
GetTextExtentPoint32(hdc, wbuf, vlen, &sz);
|
GetTextExtentPoint32(hdc, wbuf, vlen, &sz);
|
||||||
if (*f == BL_TITLE && iflags.wc2_hitpointbar) {
|
if (*f == BL_TITLE && iflags.wc2_hitpointbar) {
|
||||||
@@ -287,7 +360,7 @@ onWMPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
|
|||||||
/* first draw title normally */
|
/* first draw title normally */
|
||||||
SelectObject(hdc, fnt);
|
SelectObject(hdc, fnt);
|
||||||
SetBkMode(hdc, OPAQUE);
|
SetBkMode(hdc, OPAQUE);
|
||||||
SetBkColor(hdc, Bg);
|
SetBkColor(hdc, status_bg_color);
|
||||||
SetTextColor(hdc, nhcolor_to_RGB(hpbar_color));
|
SetTextColor(hdc, nhcolor_to_RGB(hpbar_color));
|
||||||
DrawText(hdc, wbuf, vlen, &rt, DT_LEFT);
|
DrawText(hdc, wbuf, vlen, &rt, DT_LEFT);
|
||||||
|
|
||||||
@@ -323,13 +396,13 @@ onWMPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
|
|||||||
rt.left += sz.cx;
|
rt.left += sz.cx;
|
||||||
cy = max(cy, sz.cy);
|
cy = max(cy, sz.cy);
|
||||||
}
|
}
|
||||||
|
|
||||||
rt.left = left;
|
rt.left = left;
|
||||||
rt.top += cy;
|
rt.top += cy;
|
||||||
}
|
}
|
||||||
|
|
||||||
SelectObject(hdc, oldFont);
|
BitBlt(front_buffer_hdc, 0, 0, width, height, hdc, 0, 0, SRCCOPY);
|
||||||
SetTextColor(hdc, OldFg);
|
|
||||||
SetBkColor(hdc, OldBg);
|
|
||||||
EndPaint(hWnd, &ps);
|
EndPaint(hWnd, &ps);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user