Direct2D窗口最大化后绘图尺寸变形(正方形变长方形)求助
解决Direct2D窗口最大化后图形拉伸的问题
嘿,这个问题我刚学Direct2D的时候也踩过坑!本质就是窗口客户区的宽高比变化后,你的绘图逻辑没适配新尺寸——Direct2D默认会把绘制的图形直接映射到当前像素空间,原来的小窗口宽高比和最大化后的宽屏(比如16:9)不一样,固定尺寸的正方形自然就被拉成长方形了。
给你两个实用的解决方案,按需选择:
方案一:动态适配窗口尺寸,始终绘制正方形
这个方法会根据当前窗口的实际大小,自动调整正方形的尺寸和位置,保证它永远是正方形,还能居中显示。
先监听窗口大小变化:在你的窗口过程函数里处理
WM_SIZE消息,把当前客户区的宽高存下来,然后触发重绘:// 可以用全局变量或者类成员来存客户区尺寸 float m_clientWidth; float m_clientHeight; LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_SIZE: // 获取当前客户区的宽和高 m_clientWidth = LOWORD(lParam); m_clientHeight = HIWORD(lParam); // 告诉窗口需要重绘 InvalidateRect(hwnd, NULL, FALSE); break; // 其他消息处理(比如WM_PAINT、WM_DESTROY)... } return DefWindowProc(hwnd, uMsg, wParam, lParam); }在绘制逻辑里动态计算:每次绘制时,根据存下来的宽高,算出正方形的边长(取宽高中的较小值,保证是正方形),再居中绘制:
HRESULT Render() { HRESULT hr = S_OK; pRenderTarget->BeginDraw(); // 先清空背景为黑色 pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::Black)); // 计算正方形边长:留20%的边距,避免贴边 float squareSize = min(m_clientWidth, m_clientHeight) * 0.8f; // 计算居中的坐标 float posX = (m_clientWidth - squareSize) / 2.0f; float posY = (m_clientHeight - squareSize) / 2.0f; // 绘制白色正方形 pRenderTarget->FillRectangle( D2D1::RectF(posX, posY, posX + squareSize, posY + squareSize), pWhiteBrush ); hr = pRenderTarget->EndDraw(); return hr; }
方案二:用变换矩阵保持图形原始宽高比
如果你希望图形保持最初的大小比例,哪怕窗口拉伸也不变形(就像视频的“保持比例”模式,多余区域显示背景),可以用Direct2D的变换矩阵来实现。
在WM_SIZE里计算变换矩阵:
case WM_SIZE: m_clientWidth = LOWORD(lParam); m_clientHeight = HIWORD(lParam); // 这里替换成你初始窗口的宽高(比如你原来的小窗口是800x600) float originalWidth = 800.0f; float originalHeight = 600.0f; float originalRatio = originalWidth / originalHeight; float currentRatio = m_clientWidth / m_clientHeight; D2D1::Matrix3x2F transformMatrix; if (currentRatio > originalRatio) { // 当前窗口更宽,按高度缩放,水平方向居中 float scale = m_clientHeight / originalHeight; float offsetX = (m_clientWidth - originalWidth * scale) / 2.0f; transformMatrix = D2D1::Matrix3x2F::Translation(offsetX, 0) * D2D1::Matrix3x2F::Scale(scale, scale); } else { // 当前窗口更高,按宽度缩放,垂直方向居中 float scale = m_clientWidth / originalWidth; float offsetY = (m_clientHeight - originalHeight * scale) / 2.0f; transformMatrix = D2D1::Matrix3x2F::Translation(0, offsetY) * D2D1::Matrix3x2F::Scale(scale, scale); } // 把变换矩阵应用到RenderTarget上 pRenderTarget->SetTransform(transformMatrix); InvalidateRect(hwnd, NULL, FALSE); break;绘制时用原始尺寸:这样不管窗口怎么变,你的正方形都会保持最初的比例,不会被拉伸:
// 用你最初小窗口里绘制的正方形尺寸就行 pRenderTarget->FillRectangle( D2D1::RectF(100.0f, 100.0f, 500.0f, 500.0f), pWhiteBrush );
小提醒
如果你的RenderTarget是ID2D1HwndRenderTarget,窗口大小变化时别忘了调用Resize更新它的尺寸:
pRenderTarget->Resize(D2D1::SizeU((UINT32)m_clientWidth, (UINT32)m_clientHeight));
内容的提问来源于stack exchange,提问作者tamer
相关产品推荐
相关产品推荐

