Я оставил некоторые // Комментарии, чтобы помочь вам сориентироваться в проблеме
У меня есть 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, кажется, не имеет значения.
Я пытался найти решение в течение нескольких часов. Почти на весь день на самом деле. Мне действительно нужна помощь
На самом деле, я хочу перерисовать мое изображение после изменения размера и подобных изменений.
Вы передаете NULL для lpParam
параметр (то есть последний) CreateWindowEx
,
Затем в WinProc
, ты говоришь
Game* pGame = (Game*)pcs->lpCreateParams;
::SetWindowLongPtrW(
hWnd,
GWLP_USERDATA,
PtrToUlong(pGame)
);
Таким образом, вы также установите указатель пользовательских данных в NULL.
Вы должны пройти this
в CreateWindowEx
вместо.
Других решений пока нет …