Почему этот код, почти идентичный коду из MSDN, не будет работать?

Я оставил некоторые // Комментарии, чтобы помочь вам сориентироваться в проблеме

У меня есть Main.cpp

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nShowCmd)
{
Game game;

game.Initialize(hInst);
game.MainMenu();

while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return 0;
}

Game.h

#pragma once

#define WIN32_LEAN_AND_MEAN

/*Various includes*/

template<class Interface>
inline void SafeRelease(Interface** ppInterfaceToRelease)
{
if (*ppInterfaceToRelease != NULL)
{
(*ppInterfaceToRelease)->Release();

(*ppInterfaceToRelease) = NULL;
}
}class Game{
public:
Game();
~Game();

HRESULT Initialize(HINSTANCE);

void MainMenu();

void OnResize(UINT width, UINT height);

void OnRender();

private:
static LRESULT CALLBACK WinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

private:
HWND m_hWnd;
ID2D1Factory* pD2DFactory;
ID2D1HwndRenderTarget* pRT;

};

И Game.cpp

#include "Game.h"#include <comdef.h>

Game::Game() :
pD2DFactory(NULL),
pRT(NULL)
{
}

Game::~Game()
{
SafeRelease(&pD2DFactory);
SafeRelease(&pRT);
}

HRESULT Game::Initialize(HINSTANCE hInst)
{
HRESULT hr;

// Create factory
hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pD2DFactory);

// Create a window class
WNDCLASSEX wClass;
ZeroMemory(&wClass,sizeof(WNDCLASSEX));
wClass.cbClsExtra=NULL;
wClass.cbSize=sizeof(WNDCLASSEX);
wClass.cbWndExtra=NULL;
wClass.hbrBackground=(HBRUSH)COLOR_WINDOW;
wClass.hCursor=LoadCursor(NULL,IDC_ARROW);
wClass.hIcon=NULL;
wClass.hIconSm=NULL;
wClass.hInstance=hInst;
wClass.lpfnWndProc=Game::WinProc;
wClass.lpszClassName="Window Class";
wClass.lpszMenuName=NULL;
wClass.style=CS_HREDRAW|CS_VREDRAW;

m_hWnd=CreateWindowEx(NULL,
"Window Class",
"Game", // Replace with gameName
WS_OVERLAPPEDWINDOW|WS_MAXIMIZE,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInst,
NULL);

RECT rc;
GetClientRect(m_hWnd,&rc);

// Creates render target
if(SUCCEEDED(hr))
{
pD2DFactory->CreateHwndRenderTarget(
D2D1::RenderTargetProperties(),
D2D1::HwndRenderTargetProperties(
m_hWnd,
D2D1::SizeU(
rc.right - rc.left,
rc.bottom - rc.top)),
&pRT);
}

ShowWindow(m_hWnd,SW_MAXIMIZE); //When my program gets there, WinProc gets called with the WM_PAINT message. The problem then happens.
UpdateWindow(m_hWnd);

return hr;
}

void Game::OnRender()
{
// The following code will eventually be deleted. It is left for test purpose only.
HRESULT hr;

RECT rc;
GetClientRect(m_hWnd,&rc); // The error happens when my program gets to this line of code.

ID2D1SolidColorBrush* pBlackBrush = NULL;
pRT->CreateSolidColorBrush(
D2D1::ColorF(D2D1::ColorF::White),
&pBlackBrush);

pRT->BeginDraw();

pRT->DrawRectangle(
D2D1::RectF(
rc.left + 100.0f,
rc.top + 100.0f,
rc.right - 100.0f,
rc.bottom - 100.0f),
pBlackBrush);

hr = pRT->EndDraw();
}

LRESULT Game::WinProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if(msg==WM_CREATE)
{
LPCREATESTRUCT pcs = (LPCREATESTRUCT)lParam;
Game* pGame = (Game*)pcs->lpCreateParams;

::SetWindowLongPtrW(
hWnd,
GWLP_USERDATA,
PtrToUlong(pGame)
);
}
else
{
Game* pGame = reinterpret_cast<Game*>(static_cast<LONG_PTR>(
::GetWindowLongPtrW(
hWnd,
GWLP_USERDATA
)));

switch(msg)
{

case WM_PAINT:
{
pGame->OnRender();
ValidateRect(hWnd, NULL);
}
break;

case WM_SIZE:
{
UINT width = LOWORD(lParam);
UINT height = HIWORD(lParam);
pGame->OnResize(width, height); //OnResize is called here
}
break;

case WM_DISPLAYCHANGE:
{
InvalidateRect(hWnd, NULL, FALSE);
}
break;

case WM_DESTROY:
{
//SafeRelease(p2D2Factory);
PostQuitMessage(0);
return 0;
}
break;
}
}

return DefWindowProc(hWnd,msg,wParam,lParam);
}

Это исключение, которое я получаю:

Необработанное исключение в 0x001f1666 в Arena Clash client.exe: 0xC0000005: расположение чтения нарушения доступа 0x00000000.

Я удалил некоторый код, чтобы его было легче читать. Что происходит, я получаю необработанное исключение. По причинам, которые я не понимаю, m_hWnd, кажется, не имеет значения.

Я пытался найти решение в течение нескольких часов. Почти на весь день на самом деле. Мне действительно нужна помощь

На самом деле, я хочу перерисовать мое изображение после изменения размера и подобных изменений.

-1

Решение

Вы передаете NULL для lpParam параметр (то есть последний) CreateWindowEx,

Затем в WinProc, ты говоришь

Game* pGame = (Game*)pcs->lpCreateParams;
::SetWindowLongPtrW(
hWnd,
GWLP_USERDATA,
PtrToUlong(pGame)
);

Таким образом, вы также установите указатель пользовательских данных в NULL.

Вы должны пройти thisв CreateWindowEx вместо.

4

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]