为什么这个代码几乎与MSDN中的代码完全不相同?

时间:2013-03-11 13:20:23

标签: c++ oop msdn graphic direct2d

我留下了一些//评论来帮助您解决问题

我有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);
}

这是我收到的例外情况:

Arena Clash client.exe中0x001f1666处的未处理异常:0xC0000005:访问冲突读取位置0x00000000。

我删除了一些代码以便于阅读。会发生什么是我得到一个未处理的异常。由于我不明白的原因,m_hWnd似乎没有价值。

我试图找到解决方案几个小时。实际上几乎是整整一天。我真的需要帮助。

实际上,我想要的是在调整大小和类似更改时重绘我的图像。

1 个答案:

答案 0 :(得分:4)

您将lpParam参数(即最后一个)的NULL传递给CreateWindowEx

然后,在WinProc中,您说

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

因此,您也将用户数据指针设置为NULL。

您应该将this传递给CreateWindowEx