当使用图形时,知道绘制区域的确切尺寸十分重要。在上一节中,我们创建了一个窗口,并将其尺寸设置为(500,400,但是该窗口在D3D中绘制的尺寸并不是(500,400)。在本节中,我们将介绍绘图区域的实际尺寸,并学习一个更加精确设置窗口尺寸的函数AdjustWindowRect()。
窗口尺寸 vs 客户端尺寸
当我们调用CreateWindowEx()函数时,我们分别使用500和400来设置窗口的尺寸。但是窗口尺寸与客户端的尺寸不同,客户端区域是指窗口中不包含边界的那部分。
如上图所示,窗口的尺寸是从边框的外部开始计算,而客户端的尺寸是从边框的内部开始计算。当渲染时,我们只会在窗口的客户端区域上进行绘制,因此,了解客户端区域的尺寸十分重要。当我们使用D3D进行绘制时,需要指定要生成的图像的尺寸,如果客户端区域的尺寸与图像的尺寸不符,那么图像会被拉伸或压缩以适应客户端区域的尺寸。
下面两幅图是在后面课程中的示例程序的两个屏幕截图,左边的图像是正常情况下截取的,右边的图像是在不使用AdjustWindowRect()的情形下截取的:如图所示,右侧的图像明显有些变形,这是因为图像被缩小以适应客户端区域的尺寸。
AdjustWindowRect()函数
与其先设置窗口尺寸然后确定客户端尺寸,还不如先确定客户端尺寸再确定合适的窗口尺寸。为此,我们需要在创建窗口之前使用AdjustWindowRect()函数。这个函数的功能十分简单,它所做的就是获取客户端区域的尺寸和位置,然后计算必要的窗口的尺寸和位置。下面是该函数的原型:
BOOL AdjustWindowRect(LPRECT lpRect,
DWORD dwStyle,
BOOL bMenu);
第一个参数是一个指向RECT结构体的指针,RECT包含所需的客户端区域的坐标,调用该函数之后,RECT的坐标被修改为包含窗口区域的坐标。第二个参数表示窗口样式,函数通过这个参数来确定窗口边框的大小。第三个参数是一个BOOL值,它告诉函数我们是否正在使用菜单,因为菜单不属于客户端区域,因此必须予以考虑。
下面是我们对CreateWindowEx()进行改进之后的代码:
RECT wr = {0, 0, 500, 400}; // 设置尺寸,而不是位置
AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE); // 调整尺寸
// 创建窗口并将结果作为句柄
hWnd = CreateWindowEx(NULL,
L"WindowClass1",
L"Our First Windowed Program",
WS_OVERLAPPEDWINDOW,
300, // x-position of the window
300, // y-position of the window
wr.right - wr.left, // width of the window
wr.bottom - wr.top, // height of the window
NULL,
NULL,
hInstance,
NULL);
下面我们将介绍新出现的几行代码:
代码 | 作用 |
---|---|
RECT wr = {0, 0, 500, 400}; | 创建了一个rect,并使用客户端区域的尺寸进行初始化 |
AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE); | 调用AdjustWindowRect() 函数进行调整,并获得调整之后的窗口尺寸,WS_OVERLAPPEDWINDOW 表示窗口样式,FALSE 表示没有菜单 |
wr.right - wr.left, wr.bottom - wr.top, | 通过AdjustWindowRect() 函数调整之后,窗口宽度为wr的左右之差,高度为顶部和底部之差,这便是调整之后正确的窗口尺寸 |
添加新代码
当你把AdjustWindowRect()
的代码添加之后,你会发现运行的结果几乎没有区别。实际上,除非在游戏编程中使用AdjustWindowRect(),否则很难看到区别。