Разве материал DirextX9 больше не является подходящим материалом для изучения программирования на Win32 API?

Я расширяю свою библиотеку (физическая библиотека этих странных вещей, называемых "книгами"... я знаю... я знаю), и я читаю Beginning DirectX 9.0 от Wendy Jones. Поскольку в прошлом я просматривал некоторые "устаревшие" книги, логика, лежащая в их основе, на самом деле та же самая, если не более важная в более ранних версиях (по моему опыту) таких вещей, как книги на С ++, которые я читал. Проблема, с которой я сталкиваюсь в этой книге о DirectX 9, состоит в том, что 10/10 тренировочные коды не работают, никогда. Даже решения, найденные здесь, и MSDN не работали для меня. (Одинаковая проблема).

Поэтому я надеялся, что вы могли бы сказать мне, прежде чем я пойду и куплю книгу по DX11, может ли это быть связано с моим компилятором /vs или с фактом, что vs обновлен в 2015 году, и этот DX9 устарел / стандарты DX11 были представил.

//Include the Windows header file that's needed for all Windows applications 
#include <Windows.h>


HINSTANCE hInst; // global handle to hold the application instance
HWND wndHandle; // global variable to hold the window handle

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow);

//forward declerations
bool initWindow(HINSTANCE hInstance);
LRESULT CALLBACK WndProc(HWND, UINT WPARAM, LPARAM);

//This is winmain, the main etry point for Windows applications
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
    //Initialize the window
    if (!initWindow(hInstance))
        return false;
    //main message loop: (See page 13, "Adding the Windows Code" - Chapter 2
    MSG msg;
    ZeroMemory(&msg, sizeof(msg));
    while (msg.message != WM_QUIT);
    {
        //Check the message queue
            while (GetMessage(&msg, wndHandle, 0, 0))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
    }
    return(int)msg.wParam;
}


/****************************************************************************** 
* bool initWindow( HINSTANCE hInstance ) 
* initWindow registers the window class for the application, creates the window 
******************************************************************************/

bool initWindow(HINSTANCE hInstance)
{
    WNDCLASSEX wcex;

    //Fill in the WNDCLASSEX structure. THis describes how the window will look to the system
    wcex.cbSize = sizeof(WNDCLASSEX);                    // the size of the structure
    wcex.style = CS_HREDRAW | CS_VREDRAW;                // the class style
    wcex.lpfnWndProc = (WNDPROC)WndProc;                 // the window procedure callback
    wcex.cbClsExtra = 0;                                 // extra bytes to allocate for this calss
    wcex.cbWndExtra = 0;                                 // extra bytes to allocate for this instance
    wcex.hInstance = hInstance;                          // handle to the application
    wcex.hIcon = 0;                                      // icon to associate with the application
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);          // the default cursor
    wcex.lpszMenuName = NULL;                            // the resource name for the menu
    wcex.lpszClassName = NULL;                           // the class name being created
    wcex.hIconSm = 0;
    RegisterClassEx(&wcex);

    //Create the window
    wndHandle = CreateWindow(
        (LPCWSTR)"DirectXExample",              // the window class to use
        (LPCWSTR)"DirectXExample",              // the title bar text
        WS_OVERLAPPEDWINDOW,                    // the window style
        CW_USEDEFAULT,                          // the starting x coordinate
        CW_USEDEFAULT,                          // the starting y coordinate
        640,                                    //the pixel width of the window
        480,                                    //the pixel height of the window
        NULL,                                   // the parent window; NULL for desktop
        NULL,                                   // the menu for the application; NULL for none
        hInstance,                              // the handle to the apllication instance
        NULL);                                  // no values passed to the window

    //make sure that the window handle that is created is valid
    if (!wndHandle)
        return false;

    //Display the window on the screen
    ShowWindow(wndHandle, SW_SHOW);
    UpdateWindow(wndHandle);
    return true;
}

1 ответ

Вполне нормально продолжать использовать DirectX 9. Но ваша реализация для получения минимального окна хоста на экране имеет несколько простых ошибок. Он также делает плохие преобразования между ANSI и широкими строками. Давайте исправим:

Удалите предварительную декларацию WinMain. Эта строка, просто удали ее.

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow);

В фактическом теле функции для WinMain измените тип на lpCmdLine из параметра LPT STR будет просто LPSTR.

//This is winmain, the main etry point for Windows applications
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    //Initialize the window
    if (!initWindow(hInstance))

Ваше объявление WndProc также неверно. WndProc должен быть объявлен следующим образом:

LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wparam, LPARAM lparam);

Как только вы исправите описанное выше объявление WndProc, вы можете убрать эту неудачную операцию приведения в инициализации WNDCLASS. Изменить это:

wcex.lpfnWndProc = (WNDPROC)WndProc;  // the window procedure callback

К этому:

wcex.lpfnWndProc = WndProc;  // the window procedure callback

Вам не хватает определения WndProc. Вы должны реализовать эту функцию самостоятельно. Вот минимальная реализация:

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_CLOSE:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;

}

Вышеприведенный код заставит ваш код скомпилироваться, но он все равно будет иметь некоторые ошибки и не будет работать так, как должен. Давайте исправим это.

Во-первых, у вашего сообщения есть дополнительный ; это препятствует тому, чтобы это фактически выполнялось и держало Ваш код в бесконечном цикле. Эта строка:

while (msg.message != WM_QUIT);

Должно быть (без точки с запятой):

while (msg.message != WM_QUIT)

И пока я здесь, ваша реализация насоса сообщений выглядит довольно странно. GetMessage возвращает FALSE только когда msg.message==WM_QUIT Так что внешний цикл не нужен. Изменить это:

while (msg.message != WM_QUIT)
{
    //Check the message queue
        while (GetMessage(&msg, wndHandle, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
}

быть этим:

//Check the message queue until WM_QUIT is received
while (GetMessage(&msg, wndHandle, 0, 0))
{
     TranslateMessage(&msg);
     DispatchMessage(&msg);
}

Когда вы на самом деле реализуете свой графический цикл для приложения DX, вы можете изменить GetMessage позвонить PeekMessage а затем явно проверьте WM_QUIT.

Ваше initWindow не работает по многим причинам.

Вы оставляете некоторые значения мусора в переменной WNDCLASSEX. Измените эту строку:

 WNDCLASSEX wcex;

Быть этим:

WNDCLASSEX wcex = {};

Вы забыли установить wcex.lpszClassName. Сделай это так:

 wcex.lpszClassName = L"DirectXExample";

И тогда ваше приведение строк ANSI к (LPCWSTR) неверно. Чтобы сделать это проще, вот исправленная версия вашей функции initWindow.

bool initWindow(HINSTANCE hInstance)
{
    WNDCLASSEX wcex = {};

    //Fill in the WNDCLASSEX structure. THis describes how the window will look to the system
    wcex.cbSize = sizeof(WNDCLASSEX);                    // the size of the structure
    wcex.style = CS_HREDRAW | CS_VREDRAW;                // the class style
    wcex.lpfnWndProc = (WNDPROC)WndProc;                 // the window procedure callback
    wcex.cbClsExtra = 0;                                 // extra bytes to allocate for this calss
    wcex.cbWndExtra = 0;                                 // extra bytes to allocate for this instance
    wcex.hInstance = hInstance;                          // handle to the application
    wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);                                      // icon to associate with the application
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);          // the default cursor
    wcex.lpszMenuName = NULL;                            // the resource name for the menu
    wcex.lpszClassName = L"DirectXExample";                           // the class name being created
    wcex.hIconSm = 0;
    RegisterClassEx(&wcex);

    //Create the window
    wndHandle = CreateWindow(
        L"DirectXExample",              // the window class to use
        L"DirectXExample",              // the title bar text
        WS_OVERLAPPEDWINDOW,                    // the window style
        CW_USEDEFAULT,                          // the starting x coordinate
        CW_USEDEFAULT,                          // the starting y coordinate
        640,                                    //the pixel width of the window
        480,                                    //the pixel height of the window
        NULL,                                   // the parent window; NULL for desktop
        NULL,                                   // the menu for the application; NULL for none
        hInstance,                              // the handle to the apllication instance
        NULL);                                  // no values passed to the window

                                                //make sure that the window handle that is created is valid
    if (!wndHandle)
        return false;

    //Display the window on the screen
    ShowWindow(wndHandle, SW_SHOW);
    UpdateWindow(wndHandle);
    return true;
}

И это должно сделать это.

Другие вопросы по тегам