【DirecX 教程】Lesson 4: 窗口大小和客户区大小



Lesson 4: 窗口大小和客户区大小


课程预览

在处理图形的时候,知道你要绘制的区域的准确尺寸很重要。上节课我们创建了一个窗口并把它的尺寸设为500X400.但是Direct3D的绘制区域并不是窗口的500x400。

本节我们将要探索绘制区域的实际尺寸并学习一个准确设置它的函数。

Window Size vs. Client Size

当我们调用CreateWindowEx()时,我们用500和400设置窗口大小。但是客户区大小是不同的,客户区是窗口不包含边框的部分。

正如你看到的,我们只会在窗口的客户区绘图,它的确切大小为什么相当重要?当用Direct3D绘画时你被询问以指定产生图形的大小。如果窗口客户区大小不同于图形大小,它会拉伸或收缩以适应客户区。

正如你看到的,右边的截图有明显的失真。这是图形收缩适应客户区造成的。

The AdjustWindowRect() Function

其思想是预先决定客户区大小然后计算相应的窗口大小,而不是设置窗口尺寸再决定客户区大小。要达到此目的需要在创建窗口之前使用AdjustWindowRect() 函数。

这真的是个卖萌函数。它做的就是采用要求的客户区的尺寸和位置并计算必要的窗口位置和尺寸来创建客户区大小。

函数原型:

BOOL AdjustWindowRect(LPRECT lpRect,
                      DWORD dwStyle,
                      BOOL bMenu);

第一个参数是指向RECT结构的指针。RECT包含了所要求客户区的坐标。当函数被调用后RECT被修改以代替包含窗口区域的坐标。

第二个参数是窗口风格。函数用这个信息决定窗口边框的大小。

第三个参数是个BOOL值,告诉函数我们是否使用菜单。菜单不在客户区。

下面是我们修改过的CreateWindowEx()调用:

RECT wr = {0, 0, 500, 400};    // set the size, but not the position
AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);    // adjust the size

// create the window and use the result as the handle
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};

这是个简单语句,我们创建一个矩形(窗口矩形命名为‘wr’),初始化为所要求的客户区大小。我们不在‘left’和‘top’值里放入位置是因为我们所做的不需要如此。

AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);

RECT初始化之后我们调用AdjustWindowRect()函数。我们给他填上RECT的地址,窗口风格并指定没有菜单。

wr.right - wr.left, 
wr.bottom - wr.top,

调用AdjustWindowRect()之后,左右之间的宽和顶底之间的高将会是不同的。

使用这两个窗口的宽高表达式将给我们正确的窗口尺寸。

添加新代码

这儿是我们的新代码包括 AdjustWindowRect()函数。我们已经改变的部分现在是粗体。

// include the basic windows header file
#include <windows.h>
#include <windowsx.h>

// the WindowProc function prototype
LRESULT CALLBACK WindowProc(HWND hWnd,
                         UINT message,
                         WPARAM wParam,
                         LPARAM lParam);

// the entry point for any Windows program
int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine,
                   int nCmdShow)
{
    // the handle for the window, filled by a function
    HWND hWnd;
    // this struct holds information for the window class
    WNDCLASSEX wc;

    // clear out the window class for use
    ZeroMemory(&wc, sizeof(WNDCLASSEX));

    // fill in the struct with the needed information
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
    wc.lpszClassName = L"WindowClass1";

    // register the window class
    RegisterClassEx(&wc);

    // calculate the size of the client area
    RECT wr = {0, 0, 500, 400};    // set the size, but not the position
    AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);    // adjust the size

    // create the window and use the result as the handle
    hWnd = CreateWindowEx(NULL,
                          L"WindowClass1",    // name of the window class
                          L"Our First Windowed Program",   // title of the window
                          WS_OVERLAPPEDWINDOW,    // window style
                          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,    // we have no parent window, NULL
                          NULL,    // we aren't using menus, NULL
                          hInstance,    // application handle
                          NULL);    // used with multiple windows, NULL

    // display the window on the screen
    ShowWindow(hWnd, nCmdShow);

    // enter the main loop:

    // this struct holds Windows event messages
    MSG msg;

    // wait for the next message in the queue, store the result in 'msg'
    while(GetMessage(&msg, NULL, 0, 0))
    {
        // translate keystroke messages into the right format
        TranslateMessage(&msg);

        // send the message to the WindowProc function
        DispatchMessage(&msg);
    }

    // return this part of the WM_QUIT message to Windows
    return msg.wParam;
}

// this is the main message handler for the program
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    // sort through and find what code to run for the message given
    switch(message)
    {
        // this message is read when the window is closed
        case WM_DESTROY:
            {
                // close the application entirely
                PostQuitMessage(0);
                return 0;
            } break;
    }

    // Handle any messages the switch statement didn't
    return DefWindowProc (hWnd, message, wParam, lParam);
}

当你运行这个程序的时候你会发现外观上真的没有区别。事实上你在游戏编程中使用AdjustWindowRect()之前你都不会看到差别。

好的,再来一节就接触Direct3D!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值