-3

私のWinMainは次のように始まります:

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nShowCmd)
{
    if(SUCCEEDED(CoInitialize(NULL)))
    {
        {
            HRESULT hr = S_OK;

            Game game;

            D2DResources d2DResources;

            game.SetPointer(d2DResources);
            hr = d2DResources.Initialize(hInst);

私のコンパイラは、上記の行を最後に実行してから、アンアンドリングされた例外を解除します。hr = d2DResources.Initialize(hInst)の直前にMessageBoxコマンドを追加し、直後に別のコマンドを追加したので、それ以上先に進まないことはわかっていますが、最初のコマンドだけが表示されました。

したがって、D2DResources :: Initialisize(HINSTANCE)は次のようになります。

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

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

    // Create WIC factory
    if(SUCCEEDED(hr))
    {
        hr = CoCreateInstance(
            CLSID_WICImagingFactory,
            NULL,
            CLSCTX_INPROC_SERVER,
            IID_PPV_ARGS(&pIWICIF)
            );
    }

    // 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=WinProc;
    wClass.lpszClassName="Window Class";
    wClass.lpszMenuName=NULL;
    wClass.style=CS_HREDRAW|CS_VREDRAW;

    if(!RegisterClassEx(&wClass))
    {
        int nResult=GetLastError();

        MessageBox(NULL,"Failed to register window class","Window Class Failed",MB_ICONERROR);
    }

    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,
            this);

    if(!m_hWnd)
    {
        int nResult=GetLastError();

        MessageBox(NULL,"Window class creation failed","Window Class Failed",MB_ICONERROR);
    }

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

    D2D1_SIZE_F pRTSize = pRT->GetSize();
    RECT rect = {50, (long)pRTSize.height-(LogLineSize*5), (long)pRTSize.width, (long)pRTSize.height};
    logArea = rect;

    if(SUCCEEDED(hr))
    {
        pRT->CreateSolidColorBrush(
            D2D1::ColorF(D2D1::ColorF::White),
            &pWhiteBrush
            );
    }

    if(SUCCEEDED(hr))
    {
        hr = DWriteCreateFactory(
            DWRITE_FACTORY_TYPE_SHARED,
            __uuidof(pWF),
            reinterpret_cast<IUnknown**>(&pWF)
            );
    }

    if(SUCCEEDED(hr))
    {
        hr = pWF->CreateTextFormat(
            L"Verdana",
            NULL,
            DWRITE_FONT_WEIGHT_NORMAL,
            DWRITE_FONT_STYLE_NORMAL,
            DWRITE_FONT_STRETCH_NORMAL,
            14.0f,
            L"",
            &pTextFormat
            );
    }

    return hr;
}

そして、オーバーロードされているGame :: SetPointerは、D2DResourcesオブジェクトで呼び出されると次のようになります。

void Game::SetPointer(D2DResources& p)
{
    pD2DResources=&p;
}

pD2DResourcesはD2DResources*です。

この問題は、D2DResources :: Initialization(HINSTANCE)中に、WM_SIZEメッセージがWinProcに送信されたときに発生します。だから、私のWinProcのいくつかがあります:

LRESULT CALLBACK 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_SIZE:
            {
                UINT width = LOWORD(lParam);
                UINT height = HIWORD(lParam);
                pGame->pD2DResources->OnResize(width, height);
            }
            break;

OnResizeが呼び出されると、問題が発生します。

void D2DResources::OnResize(UINT width, UINT height)
{
    if(pRT)
    {
        HRESULT hr = pRT->Resize(D2D1::SizeU(width, height));
        if(hr!=0) MessageBox(NULL,"Render target could not be resized","ID2D1HwndRenterTarget Error",MB_ICONERROR);
    }
}

コンパイラーが壊れ、if(pRT)(pRTはレンダーターゲットへのポインター)行を指す黄色の矢印があります。

興味深いことに、デバッグ中に自動車を見ると、これがわかります。

  • this 0x00000000 {log = 0x00000000 nLogLines = ??? logArea = {...} ...} D2DResources * const
  • log 0x00000000 wchar_t [511] nLogLines CXX0030:エラー:式を評価できません
  • logArea {top = ??? 底=??? 左=??? right = ???} tagRECT m_hWnd CXX0017:エラー:symbol "" not found pD2DFactory CXX0017:Error:symbol "" not found pIWICIF CXX0017:Error:symbol "" not found pWF CXX0017:Error:symbol "" not found pRT CXX0030:エラー:式を評価できません
    pCurrentScreen CXX0017:エラー:シンボル ""が見つかりませんpWhiteBrushCXX0017:エラー:シンボル ""が見つかりませんpTextFormatCXX0017:エラー:シンボル""が見つかりません

それで、問題は何ですか、そして解決策は何ですか?

4

2 に答える 2

3

WinProcが呼び出されるまでに、WinMainで宣言したD2DResourcesオブジェクトはスコープ外になっていますが、それへのポインターを保持しています。ポインターを介してメソッドを呼び出すと、D2DResourcesオブジェクトを指していないスタック内のスポットに対して実行されます(注意-MessageBoxは誤解を招きます-実際にはスコープ外になっています)。

これを修正する最も簡単な方法は、変更することです

D2DResources d2DResources;

WinMainで

D2DResources& d2DResources = *(new D2DResources());

同じオブジェクトをヒープに配置します。

私はそれがあなたのコードの唯一の問題であることを誓うつもりはありませんが...

于 2013-03-15T21:33:48.933 に答える
2

ウィンドウに間違ったポインタを渡しています。ウィンドウを作成し、としてD2DResources::Initialize渡しますが、ウィンドウプロシージャでは、ウィンドウをにキャストします。thislpParamGame*

于 2013-03-15T21:38:52.543 に答える