支持界面随窗口尺寸等比缩放

This commit is contained in:
2026-04-24 11:08:38 +08:00
parent c8f90621b6
commit e8bbf609fd
3 changed files with 112 additions and 70 deletions
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

+3
View File
@@ -200,6 +200,9 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
InvalidateRect(hWnd, nullptr, FALSE);
}
break;
case WM_SIZE:
InvalidateRect(hWnd, nullptr, FALSE);
break;
case WM_KEYDOWN:
if (wParam == 'R')
{
+109 -70
View File
@@ -16,20 +16,59 @@ void TDrawScreen(HDC hdc, HWND hWnd)
RECT clientRect;
GetClientRect(hWnd, &clientRect);
int clientWidth = clientRect.right - clientRect.left;
int clientHeight = clientRect.bottom - clientRect.top;
int scaleX = MulDiv(clientWidth, 1000, WINDOW_CLIENT_WIDTH);
int scaleY = MulDiv(clientHeight, 1000, WINDOW_CLIENT_HEIGHT);
int scale = (scaleX < scaleY) ? scaleX : scaleY;
if (scale < 500)
{
scale = 500;
}
int layoutWidth = MulDiv(WINDOW_CLIENT_WIDTH, scale, 1000);
int layoutHeight = MulDiv(WINDOW_CLIENT_HEIGHT, scale, 1000);
int offsetX = (clientWidth - layoutWidth) / 2;
int offsetY = (clientHeight - layoutHeight) / 2;
auto SX = [offsetX, scale](int value) -> int
{
return offsetX + MulDiv(value, scale, 1000);
};
auto SY = [offsetY, scale](int value) -> int
{
return offsetY + MulDiv(value, scale, 1000);
};
auto SS = [scale](int value) -> int
{
int result = MulDiv(value, scale, 1000);
return result < 1 ? 1 : result;
};
int grid = SS(GRID);
int padding = SS(WINDOW_PADDING);
int panelGap = SS(SIDE_PANEL_GAP);
int panelWidth = SS(SIDE_PANEL_WIDTH);
int boardWidth = grid * nGameWidth;
int boardHeight = grid * nGameHeight;
const RECT gameRect =
{
WINDOW_PADDING,
WINDOW_PADDING,
WINDOW_PADDING + nGameWidth * GRID,
WINDOW_PADDING + nGameHeight * GRID
SX(WINDOW_PADDING),
SY(WINDOW_PADDING),
SX(WINDOW_PADDING) + boardWidth,
SY(WINDOW_PADDING) + boardHeight
};
const RECT panelRect =
{
gameRect.right + SIDE_PANEL_GAP,
WINDOW_PADDING,
gameRect.right + SIDE_PANEL_GAP + SIDE_PANEL_WIDTH,
WINDOW_PADDING + nGameHeight * GRID
gameRect.right + panelGap,
SY(WINDOW_PADDING),
gameRect.right + panelGap + panelWidth,
SY(WINDOW_PADDING) + boardHeight
};
const COLORREF pageColor = RGB(255, 244, 248);
@@ -64,22 +103,22 @@ void TDrawScreen(HDC hdc, HWND hWnd)
// 创建中文清晰字体
HFONT titleFont = CreateFont(
-34, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE,
-SS(34), 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE,
DEFAULT_CHARSET, OUT_OUTLINE_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_NATURAL_QUALITY,
VARIABLE_PITCH, _T("Microsoft YaHei UI"));
HFONT sectionFont = CreateFont(
-24, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE,
-SS(24), 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE,
DEFAULT_CHARSET, OUT_OUTLINE_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_NATURAL_QUALITY,
VARIABLE_PITCH, _T("Microsoft YaHei UI"));
HFONT bodyFont = CreateFont(
-20, 0, 0, 0, FW_SEMIBOLD, FALSE, FALSE, FALSE,
-SS(20), 0, 0, 0, FW_SEMIBOLD, FALSE, FALSE, FALSE,
DEFAULT_CHARSET, OUT_OUTLINE_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_NATURAL_QUALITY,
VARIABLE_PITCH, _T("Microsoft YaHei UI"));
HFONT smallFont = CreateFont(
-17, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
-SS(17), 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
DEFAULT_CHARSET, OUT_OUTLINE_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_NATURAL_QUALITY,
VARIABLE_PITCH, _T("Microsoft YaHei UI"));
@@ -92,9 +131,9 @@ void TDrawScreen(HDC hdc, HWND hWnd)
HBRUSH panelBrush = CreateSolidBrush(cardColor);
oldPen = (HPEN)SelectObject(hdc, framePen);
oldBrush = (HBRUSH)SelectObject(hdc, gameCardBrush);
RoundRect(hdc, gameRect.left - 10, gameRect.top - 10, gameRect.right + 10, gameRect.bottom + 10, 28, 28);
RoundRect(hdc, gameRect.left - SS(10), gameRect.top - SS(10), gameRect.right + SS(10), gameRect.bottom + SS(10), SS(28), SS(28));
SelectObject(hdc, panelBrush);
RoundRect(hdc, panelRect.left, panelRect.top, panelRect.right, panelRect.bottom, 30, 30);
RoundRect(hdc, panelRect.left, panelRect.top, panelRect.right, panelRect.bottom, SS(30), SS(30));
SelectObject(hdc, oldBrush);
SelectObject(hdc, oldPen);
DeleteObject(gameCardBrush);
@@ -108,10 +147,10 @@ void TDrawScreen(HDC hdc, HWND hWnd)
RECT innerRect =
{
gameRect.left + 6,
gameRect.top + 6,
gameRect.right - 6,
gameRect.bottom - 6
gameRect.left + SS(6),
gameRect.top + SS(6),
gameRect.right - SS(6),
gameRect.bottom - SS(6)
};
HBRUSH innerBrush = CreateSolidBrush(boardInnerColor);
@@ -119,10 +158,10 @@ void TDrawScreen(HDC hdc, HWND hWnd)
DeleteObject(innerBrush);
// 绘制游戏区边框
HPEN borderPen = CreatePen(PS_SOLID, 2, RGB(132, 108, 146));
HPEN borderPen = CreatePen(PS_SOLID, SS(2), RGB(132, 108, 146));
oldPen = (HPEN)SelectObject(hdc, borderPen);
oldBrush = (HBRUSH)SelectObject(hdc, GetStockObject(NULL_BRUSH));
RoundRect(hdc, gameRect.left, gameRect.top, gameRect.right, gameRect.bottom, 18, 18);
RoundRect(hdc, gameRect.left, gameRect.top, gameRect.right, gameRect.bottom, SS(18), SS(18));
SelectObject(hdc, oldBrush);
SelectObject(hdc, oldPen);
DeleteObject(borderPen);
@@ -133,14 +172,14 @@ void TDrawScreen(HDC hdc, HWND hWnd)
for (int i = 1; i < nGameWidth; i++)
{
int x = gameRect.left + i * GRID;
int x = gameRect.left + i * grid;
MoveToEx(hdc, x, gameRect.top, nullptr);
LineTo(hdc, x, gameRect.bottom);
}
for (int i = 1; i < nGameHeight; i++)
{
int y = gameRect.top + i * GRID;
int y = gameRect.top + i * grid;
MoveToEx(hdc, gameRect.left, y, nullptr);
LineTo(hdc, gameRect.right, y);
}
@@ -158,17 +197,17 @@ void TDrawScreen(HDC hdc, HWND hWnd)
int colorIndex = workRegion[i][j] - 1;
RECT brickRect =
{
gameRect.left + j * GRID + 2,
gameRect.top + i * GRID + 2,
gameRect.left + (j + 1) * GRID - 2,
gameRect.top + (i + 1) * GRID - 2
gameRect.left + j * grid + SS(2),
gameRect.top + i * grid + SS(2),
gameRect.left + (j + 1) * grid - SS(2),
gameRect.top + (i + 1) * grid - SS(2)
};
HBRUSH brickBrush = CreateSolidBrush(BrickColor[colorIndex]);
HPEN brickPen = CreatePen(PS_SOLID, 1, RGB(255, 248, 250));
oldPen = (HPEN)SelectObject(hdc, brickPen);
oldBrush = (HBRUSH)SelectObject(hdc, brickBrush);
RoundRect(hdc, brickRect.left, brickRect.top, brickRect.right, brickRect.bottom, 10, 10);
RoundRect(hdc, brickRect.left, brickRect.top, brickRect.right, brickRect.bottom, SS(10), SS(10));
SelectObject(hdc, oldBrush);
SelectObject(hdc, oldPen);
DeleteObject(brickBrush);
@@ -180,7 +219,7 @@ void TDrawScreen(HDC hdc, HWND hWnd)
// 绘制预测落点
if (targetFlag)
{
HPEN targetPen = CreatePen(PS_DOT, 2, RGB(255, 240, 245));
HPEN targetPen = CreatePen(PS_DOT, SS(2), RGB(255, 240, 245));
oldPen = (HPEN)SelectObject(hdc, targetPen);
oldBrush = (HBRUSH)SelectObject(hdc, GetStockObject(NULL_BRUSH));
@@ -197,11 +236,11 @@ void TDrawScreen(HDC hdc, HWND hWnd)
{
RoundRect(
hdc,
gameRect.left + drawX * GRID + 5,
gameRect.top + drawY * GRID + 5,
gameRect.left + (drawX + 1) * GRID - 5,
gameRect.top + (drawY + 1) * GRID - 5,
8, 8);
gameRect.left + drawX * grid + SS(5),
gameRect.top + drawY * grid + SS(5),
gameRect.left + (drawX + 1) * grid - SS(5),
gameRect.top + (drawY + 1) * grid - SS(5),
SS(8), SS(8));
}
}
}
@@ -226,17 +265,17 @@ void TDrawScreen(HDC hdc, HWND hWnd)
{
RECT brickRect =
{
gameRect.left + drawX * GRID + 2,
gameRect.top + drawY * GRID + 2,
gameRect.left + (drawX + 1) * GRID - 2,
gameRect.top + (drawY + 1) * GRID - 2
gameRect.left + drawX * grid + SS(2),
gameRect.top + drawY * grid + SS(2),
gameRect.left + (drawX + 1) * grid - SS(2),
gameRect.top + (drawY + 1) * grid - SS(2)
};
HBRUSH brickBrush = CreateSolidBrush(BrickColor[type]);
HPEN brickPen = CreatePen(PS_SOLID, 1, RGB(255, 250, 252));
oldPen = (HPEN)SelectObject(hdc, brickPen);
oldBrush = (HBRUSH)SelectObject(hdc, brickBrush);
RoundRect(hdc, brickRect.left, brickRect.top, brickRect.right, brickRect.bottom, 12, 12);
RoundRect(hdc, brickRect.left, brickRect.top, brickRect.right, brickRect.bottom, SS(12), SS(12));
SelectObject(hdc, oldBrush);
SelectObject(hdc, oldPen);
DeleteObject(brickBrush);
@@ -249,12 +288,12 @@ void TDrawScreen(HDC hdc, HWND hWnd)
// 绘制右侧信息面板
HFONT oldFont = (HFONT)SelectObject(hdc, titleFont);
SetTextColor(hdc, titleColor);
TextOut(hdc, panelRect.left + 24, panelRect.top + 22, _T("俄罗斯方块"), lstrlen(_T("俄罗斯方块")));
TextOut(hdc, panelRect.left + SS(24), panelRect.top + SS(22), _T("俄罗斯方块"), lstrlen(_T("俄罗斯方块")));
HPEN accentPen = CreatePen(PS_SOLID, 3, accentColor);
HPEN accentPen = CreatePen(PS_SOLID, SS(3), accentColor);
oldPen = (HPEN)SelectObject(hdc, accentPen);
MoveToEx(hdc, panelRect.left + 24, panelRect.top + 68, nullptr);
LineTo(hdc, panelRect.left + 160, panelRect.top + 68);
MoveToEx(hdc, panelRect.left + SS(24), panelRect.top + SS(68), nullptr);
LineTo(hdc, panelRect.left + SS(160), panelRect.top + SS(68));
SelectObject(hdc, oldPen);
DeleteObject(accentPen);
@@ -263,23 +302,23 @@ void TDrawScreen(HDC hdc, HWND hWnd)
TCHAR scoreText[64];
_stprintf_s(scoreText, _T("当前得分 %d"), tScore);
TextOut(hdc, panelRect.left + 24, panelRect.top + 104, scoreText, lstrlen(scoreText));
TextOut(hdc, panelRect.left + SS(24), panelRect.top + SS(104), scoreText, lstrlen(scoreText));
TextOut(hdc, panelRect.left + 24, panelRect.top + 172, _T("下一个方块"), lstrlen(_T("下一个方块")));
TextOut(hdc, panelRect.left + SS(24), panelRect.top + SS(172), _T("下一个方块"), lstrlen(_T("下一个方块")));
RECT nextCard =
{
panelRect.left + 24,
panelRect.top + 210,
panelRect.left + 24 + GRID * 4 + 32,
panelRect.top + 210 + GRID * 4 + 32
panelRect.left + SS(24),
panelRect.top + SS(210),
panelRect.left + SS(24) + grid * 4 + SS(32),
panelRect.top + SS(210) + grid * 4 + SS(32)
};
HBRUSH nextCardBrush = CreateSolidBrush(RGB(255, 238, 244));
HPEN nextCardPen = CreatePen(PS_SOLID, 1, RGB(233, 191, 208));
oldPen = (HPEN)SelectObject(hdc, nextCardPen);
oldBrush = (HBRUSH)SelectObject(hdc, nextCardBrush);
RoundRect(hdc, nextCard.left, nextCard.top, nextCard.right, nextCard.bottom, 22, 22);
RoundRect(hdc, nextCard.left, nextCard.top, nextCard.right, nextCard.bottom, SS(22), SS(22));
SelectObject(hdc, oldBrush);
SelectObject(hdc, oldPen);
DeleteObject(nextCardBrush);
@@ -294,17 +333,17 @@ void TDrawScreen(HDC hdc, HWND hWnd)
{
RECT brickRect =
{
nextCard.left + 16 + j * GRID,
nextCard.top + 16 + i * GRID,
nextCard.left + 16 + (j + 1) * GRID - 2,
nextCard.top + 16 + (i + 1) * GRID - 2
nextCard.left + SS(16) + j * grid,
nextCard.top + SS(16) + i * grid,
nextCard.left + SS(16) + (j + 1) * grid - SS(2),
nextCard.top + SS(16) + (i + 1) * grid - SS(2)
};
HBRUSH brickBrush = CreateSolidBrush(BrickColor[nType]);
HPEN brickPen = CreatePen(PS_SOLID, 1, RGB(255, 248, 250));
oldPen = (HPEN)SelectObject(hdc, brickPen);
oldBrush = (HBRUSH)SelectObject(hdc, brickBrush);
RoundRect(hdc, brickRect.left, brickRect.top, brickRect.right, brickRect.bottom, 10, 10);
RoundRect(hdc, brickRect.left, brickRect.top, brickRect.right, brickRect.bottom, SS(10), SS(10));
SelectObject(hdc, oldBrush);
SelectObject(hdc, oldPen);
DeleteObject(brickBrush);
@@ -314,29 +353,29 @@ void TDrawScreen(HDC hdc, HWND hWnd)
}
SelectObject(hdc, sectionFont);
TextOut(hdc, panelRect.left + 24, panelRect.top + 390, _T("操作提示"), lstrlen(_T("操作提示")));
TextOut(hdc, panelRect.left + SS(24), panelRect.top + SS(390), _T("操作提示"), lstrlen(_T("操作提示")));
SelectObject(hdc, bodyFont);
TextOut(hdc, panelRect.left + 24, panelRect.top + 432, _T("方向键 / WASD:移动 / 旋转"), lstrlen(_T("方向键 / WASD:移动 / 旋转")));
TextOut(hdc, panelRect.left + 24, panelRect.top + 468, _T("空格:快速下落"), lstrlen(_T("空格:快速下落")));
TextOut(hdc, panelRect.left + 24, panelRect.top + 504, _T("P:暂停 R:重新开始"), lstrlen(_T("P:暂停 R:重新开始")));
TextOut(hdc, panelRect.left + 24, panelRect.top + 540, _T("G:显示 / 隐藏落点"), lstrlen(_T("G:显示 / 隐藏落点")));
TextOut(hdc, panelRect.left + SS(24), panelRect.top + SS(432), _T("方向键 / WASD:移动 / 旋转"), lstrlen(_T("方向键 / WASD:移动 / 旋转")));
TextOut(hdc, panelRect.left + SS(24), panelRect.top + SS(468), _T("空格:快速下落"), lstrlen(_T("空格:快速下落")));
TextOut(hdc, panelRect.left + SS(24), panelRect.top + SS(504), _T("P:暂停 R:重新开始"), lstrlen(_T("P:暂停 R:重新开始")));
TextOut(hdc, panelRect.left + SS(24), panelRect.top + SS(540), _T("G:显示 / 隐藏落点"), lstrlen(_T("G:显示 / 隐藏落点")));
if (suspendFlag || gameOverFlag)
{
RECT overlayRect =
{
gameRect.left + GRID,
gameRect.top + GRID * 6,
gameRect.right - GRID,
gameRect.top + GRID * 13
gameRect.left + grid,
gameRect.top + grid * 6,
gameRect.right - grid,
gameRect.top + grid * 13
};
HBRUSH overlayBrush = CreateSolidBrush(RGB(255, 241, 246));
HPEN overlayPen = CreatePen(PS_SOLID, 2, RGB(232, 170, 194));
oldPen = (HPEN)SelectObject(hdc, overlayPen);
oldBrush = (HBRUSH)SelectObject(hdc, overlayBrush);
RoundRect(hdc, overlayRect.left, overlayRect.top, overlayRect.right, overlayRect.bottom, 26, 26);
RoundRect(hdc, overlayRect.left, overlayRect.top, overlayRect.right, overlayRect.bottom, SS(26), SS(26));
SelectObject(hdc, oldBrush);
SelectObject(hdc, oldPen);
DeleteObject(overlayBrush);
@@ -345,17 +384,17 @@ void TDrawScreen(HDC hdc, HWND hWnd)
RECT titleRect =
{
overlayRect.left,
overlayRect.top + GRID,
overlayRect.top + grid,
overlayRect.right,
overlayRect.top + GRID * 3
overlayRect.top + grid * 3
};
RECT tipRect =
{
overlayRect.left + 20,
overlayRect.top + GRID * 3,
overlayRect.right - 20,
overlayRect.bottom - GRID
overlayRect.left + SS(20),
overlayRect.top + grid * 3,
overlayRect.right - SS(20),
overlayRect.bottom - grid
};
SetTextColor(hdc, RGB(121, 76, 99));