拖动窗口左/上边缘调整大小时RECT值不变的原因咨询
拖动窗口右/下边缘调整大小时,打印的相关数值会发生变化,但拖动左/上边缘调整窗口大小时,数值却没有改变。以下是对应的WindowProc函数:
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; switch (uMsg) { case WM_SIZE: { break; } case WM_PAINT: { int height = 50; TCHAR buff[256] = { 0 }; HDC hdc = BeginPaint(hwnd, &ps); SetMapMode(hdc, MM_TEXT); RECT windowSize; RECT logicExtent; GetWindowRect(hwnd, &windowSize); logicExtent = windowSize; DPtoLP(hdc, (LPPOINT)(&logicExtent), 2); memset(buff, 0, 256); _stprintf_s(buff, TEXT("TEXT MODE:Physical Extent=[%d, %d], Logical Extent=[%d,%d]"), windowSize.right, windowSize.bottom, logicExtent.right, logicExtent.bottom); TextOut(hdc,0, height * 0,buff, _tcslen(buff)); EndPaint(hwnd, &ps); break; } case WM_DESTROY: { PostQuitMessage(0); break; } } return DefWindowProc(hwnd, uMsg, wParam, lParam); }
原因解析
错误使用
GetWindowRect的返回值GetWindowRect获取的是窗口在屏幕坐标系中的位置和范围,windowSize.right是窗口右边缘的屏幕X坐标,windowSize.bottom是窗口下边缘的屏幕Y坐标。当拖动左/上边缘时,窗口的左上角位置(windowSize.left/windowSize.top)会改变,但右/下边缘的屏幕坐标(right/bottom)不会变化——比如向左拖动左边缘,窗口宽度增加,但right值保持不变,所以你打印的这两个数值自然不会有变化;而拖动右/下边缘时,right或bottom会直接增大,数值也就随之改变。DPtoLP的转换逻辑错误DPtoLP的作用是将设备上下文(DC)的设备坐标转换为逻辑坐标,但你传入的windowSize是屏幕坐标,并非DC对应的设备坐标(DC的设备坐标通常以窗口客户区左上角为原点)。在MM_TEXT模式下,设备坐标和逻辑坐标本身是一致的,所以这次转换完全没有意义,反而因为输入的坐标错误,导致logicExtent的结果也不符合预期。混淆了"坐标值"和"尺寸值"
你现在打印的是窗口边缘的绝对坐标,而非窗口的实际宽高。真正的窗口宽度应该是windowSize.right - windowSize.left,高度是windowSize.bottom - windowSize.top,无论拖动哪个边缘,这两个计算值都会正确反映窗口尺寸的变化。
内容的提问来源于stack exchange,提问作者SZYoo

