Разве материал 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;
}
И это должно сделать это.