在尝试使用C ++创建窗口并绘制窗口大小与我设置的大小不匹配的矩形时,我注意到一些非常烦人的事情。
例如,如果我设置480x240窗口并尝试通过获取GetWindowRect(hwnd,& rect)从上到下,从左到右绘制矩形并计算宽度和高度:
rectangle_width = (rect.right - rect.left) / amountRectangleX;
rectangle_height = (rect.bottom - rect.top) / amountRectangleY;
如果amountRectangleX = 2且Y = 2则绘制4个矩形,但宽度和高度为“off”,因此它不会填满整个屏幕或者渲染它。这种情况发生的唯一方法(我已经用很多其他语言完成了所以我知道它有效)是如果我设置Window Size = 480x240我希望它是“DRAW”的区域。因为如果窗口大小中包含边框 - 在具有不同窗口样式的另一台计算机上会有所不同。我不能只为我的电脑手动“改变”这个。
如果我设置窗口大小= 480x240并截取屏幕截图,我看到Window Space = 452x232令人困惑。如果我设置窗口大小= 480x240就可以了,但是当我GetWindowRect()时,我得到452x232而不是480x240然后无效,因为我有更少的空间来绘制。这可以解释为什么我的矩形渲染超出窗口空间而我不希望这样。但我仍然希望能够设置我的尺寸= 480x240或其他任何东西,但仍然有边框。
为什么它以这种方式工作,是否有解决此问题的方法? 我不能是唯一一个想要设置窗口分辨率的人,无论你使用什么计算机,你设置的那个尺寸都是你可以利用的绘图区域。
答案 0 :(得分:2)
我使用这种方法现在可行:
if ( IsWindow( hwnd ) )
{
DWORD dwStyle = GetWindowLongPtr( hwnd, GWL_STYLE ) ;
DWORD dwExStyle = GetWindowLongPtr( hwnd, GWL_EXSTYLE ) ;
HMENU menu = GetMenu( hwnd ) ;
RECT rc = { 0, 0, width, height } ;
AdjustWindowRectEx( &rc, dwStyle, menu ? TRUE : FALSE, dwExStyle );
SetWindowPos( hwnd, NULL, 0, 0, rc.right - rc.left, rc.bottom - rc.top, SWP_NOZORDER | SWP_NOMOVE ) ;
}
答案 1 :(得分:2)
就像@Deukalion一样,我无意中将所需的客户区大小放入::CreateWindow()
调用中,在绘制网格时,我发现自己没有像素。我采用相同的方法来调查我的应用程序的屏幕截图的像素大小。我可以理解窗口的边框和标题栏会从客户区域中占用一些空间 - 但令人沮丧的是,在Windows 10下,甚至整个应用程序窗口都没有请求的大小!
我怀疑::CreateWindow()
通过减去宽度和高度中硬编码的像素数来计算较小的客户区,然后在其周围构建窗口边框和标题栏。对于Windows 10的超薄鲜明的窗口主题,这个硬编码的数字已不再正确。这太荒谬了 - 屏幕尺寸上确实没有没有 ::CreateWindow()
!
我按照@PeterRuderman的建议使用::AdjustWindowRect()
电话:
RECT rect;
rect.left = rect.top = 0;
rect.right = clientWidth;
rect.bottom = clientHeight;
::AdjustWindowRect(&rect, wflags, false);
HWND hWindow = ::CreateWindow(wcName, title, wflags, 0, 0,
rect.right - rect.left, rect.bottom - rect.top, 0, 0, hInstance, 0);
right
和bottom
字段视为外预期的矩形。::AdjustWindowRect()
保留给定的原点坐标(0,0),那将会很好,这样right
和bottom
就可以直接填入{{1}调用。但令我惊讶的是,::CreateWindow()
和left
字段变为否定。答案 2 :(得分:1)
我仍然认为你没有提供足够的信息来解决你的问题,但这是一个完整的程序(基本上)你想要的。您可以将它与您自己的相比较,以查看您出错的地方。
#include <Windows.h>
LRESULT CALLBACK WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch( uMsg ) {
case WM_CLOSE:
PostQuitMessage( 0 );
break;
case WM_PAINT:
{
RECT clientArea;
GetClientRect( hwnd, &clientArea );
PAINTSTRUCT ps;
BeginPaint( hwnd, &ps );
HBRUSH brush = (HBRUSH)GetStockObject( BLACK_BRUSH );
RECT topLeft = clientArea;
topLeft.right /= 2;
topLeft.bottom /= 2;
RECT bottomRight = clientArea;
bottomRight.left = bottomRight.right / 2;
bottomRight.top = bottomRight.bottom / 2;
FillRect( ps.hdc, &topLeft, brush );
FillRect( ps.hdc, &bottomRight, brush );
EndPaint( hwnd, &ps );
}
return 0;
}
return DefWindowProc( hwnd, uMsg, wParam, lParam );
}
int CALLBACK WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
// Error checking omitted for brevity.
WNDCLASSEX wc = { 0 };
wc.cbSize = sizeof( wc );
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszClassName = L"testclass";
ATOM classAtom = RegisterClassEx( &wc );
HWND window = CreateWindow( L"testclass", L"Test", WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 480, 240, NULL, NULL, hInstance, NULL );
MSG msg;
while( GetMessage( &msg, NULL, 0, 0 ) ) {
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
修改强>
重新阅读您的问题后,我认为您只是在寻找AdjustWindowRect API。在这种情况下,您的问题与此问题重复:WinAPI: Create a window with a specified client area size。为了将来参考,“您可以绘制的区域”称为客户区。