2013-03-15 49 views
-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); 

我的編譯器將執行之前打破了一個unandled例外高於去年出的線。我知道它不會進一步,因爲我已經在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; 
} 

和遊戲:: SetPointer,這是超載,看起來像這樣當與D2DResources稱爲對象:

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

pD2DResources是D2DResources *。

當WM_SIZE消息發送到我的WinProc時,問題發生在D2DResources :: Initialization(HINSTANCE)期間。所以,我的一些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是指向渲染目標的指針)行的黃色箭頭。

有趣的是,在調試期間查看汽車顯示了這一點。

  • 此00000000 {登錄= 00000000 nLogLines = ??? logArea = {...} ...} D2DResources * const的
  • 日誌00000000 wchar_t的[511] nLogLines CXX0030:錯誤:表達無法評估
  • logArea {頂= ???底= ???左= ???右= ???} tagRECT m_hWnd CXX0017:錯誤:符號 「」 未找到 pD2DFactory CXX0017:錯誤:符號 「」 未找到 pIWICIF CXX0017:錯誤:符號 「」 未找到 PWF CXX0017:錯誤:符號 「」 不發現 PRT CXX0030:錯誤:表達無法評估
    pCurrentScreen CXX0017:錯誤:符號 「」 未找到 pWhiteBrush CXX0017:錯誤:符號 「」 未找到 pTextFormat CXX0017:錯誤:符號 「」 未找到

那麼,什麼是問題,什麼是解決方案?

+5

'有些東西是錯誤的,也許是用指針'可能是這裏最糟糕的題目,這是我見過的... – VoidKing 2013-03-15 21:23:14

+0

粗略推測...'pGame-> pD2DResources'爲null ? – 2013-03-15 21:23:36

+3

這個問題給了我癌症。 – shoosh 2013-03-15 21:24:19

回答

2

你傳遞了​​錯誤的指針到你的窗口。您正在創建D2DResources::Initialize中的窗口並將this作爲lpParam創建,但在窗口過程中,您將其投射到Game*

+0

好的,我會嘗試,但還有一個問題。 D2DResources對象需要HWND才能運行,我如何使用它的函數與Game的WHND一起工作?是通過使用指針嗎? – 2013-03-15 21:42:42

+1

要麼重構你的代碼以從你的'Game'類的函數中創建窗口,要麼(更簡單地)指向'D2DResources :: Initialize'函數的'Game'結構,並將其用於窗口的'lpParam'值。 – 2013-03-15 21:45:35

+0

太好了,謝謝! – 2013-03-15 21:47:51

3

在WinProc被調用的時候,你在WinMain中聲明的D2DResources對象已經超出了範圍,但是你仍然持有一個指向它的指針。當您通過指針調用方法時,它將針對堆棧中不再指向D2DResources對象的地點執行(請注意,您的MessageBox誤導了您 - 它確實超出了範圍。)

最簡單的方法解決這個問題是在你的WinMain改變

D2DResources d2DResources; 

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

將放在同一個對象在堆上。

雖然我不會發誓這是你的代碼的唯一的問題...

+0

謝謝!我正在嘗試。 – 2013-03-15 21:36:23

+2

在接受它之前,最好先試着回答問題,因爲我認爲在這種情況下你會發現這不是你問題的原因。 – 2013-03-15 21:36:44

+2

我只是因爲最後一行而投票贊成。 – 2013-03-15 21:36:48