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

来源:互联网 发布:电子书离线软件 编辑:程序博客网 时间:2024/06/05 06:50


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 positionAdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);    // adjust the size// create the window and use the result as the handlehWnd = 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 prototypeLRESULT CALLBACK WindowProc(HWND hWnd,                         UINT message,                         WPARAM wParam,                         LPARAM lParam);// the entry point for any Windows programint 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 programLRESULT 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!


0 0