2015-12-29 34 views
-1

我正在寫什麼應該是俄羅斯方塊遊戲的代碼。它很早就開始了,現在它只顯示一個單一的片斷(這個片斷在那個時候會「下降」),這是它應該做的。向上箭頭允許您通過隨機生成的部分序列(使用「bag」方法)向前循環(特別是僅循環)。並且,使用左右箭頭,您可以旋轉這些部分。無論如何,它是在一個win32平臺上編碼的,我發現在一定數量的幀(運行WM_PAINT)後,主HDC變爲空,一切都停止。按住右箭頭鍵或左箭頭鍵的幀數大約是按住向上箭頭鍵的兩倍。奇怪的是,在大約1000幀後,我正在主動繪製的控制檯區域(600x600像素幀)將變黑(hdc尚未被取消),並且只有當向上箭頭被按下時, hdc無效。我懷疑是問題的是當按下向上箭頭鍵時調用的方法將hdc作爲參數傳遞給類內方法(告訴我這是不好的練習還是應該做的事情)。我認爲HDC可能是腐敗或某事(說實話,我不知道)。左右箭頭鍵不直接調用HDC作爲參數的方法。由於箱子標籤以及win32模板的設計,我必須存儲一個HDC,它的範圍不屬於任何案例標籤,所以我可以訪問窗口的油漆案例外的手柄(我覺得這是一種很差的做法,但我想了解爲什麼在我走出去尋找新的方式之前)。我將發佈代碼,存儲的HDC稱爲mainHDC,它在主要語句之前定義。爲了讓你瞭解代碼結構,我將給出代碼結構的概述:C++ Win32:HDC的和調試

包含基本win32程序的主.cpp文件在WM_PAINT中調用Tetris類的構造函數並將其存儲爲像mainHDC一樣,當提示時,「下一個」方法(帶來下一個片段),「turnPiece」方法(基於參數順時針或逆時針旋轉片)和更新屏幕的「繪畫」方法,重新繪製目前的一塊。在俄羅斯方塊類(它在它自己的頭文件中)中,有一個叫做「pieces」的子類,它包含關於它的對象的信息,這些信息是由另一個級別的子類定義的,這些子類用單個字符命名形狀。片段的形狀,顏色和大小存儲在一個二維指針數組中(使用COLORREF)。 「Pieces」包含自己的「DrawObject」方法,該方法繪製調用它的對象(與所有繪圖/繪畫方法都有HDC作爲參數一樣)。還有一種方法可以旋轉稱爲「turnTet」的形狀(「turnPiece」方法將調用從主.cpp文件中繼到「碎片」)。唯一的其他適用的方法是在「俄羅斯方塊」類中找到的那些「繪畫」和「下一個」(它們最終繪製對象)。 WM_KEY情況(不包括VK_UP情況)不使用保存的hdc,而是使用InvalidateRect()。

這裏的.cpp文件

int tempt = 2; 
int tempvar = 0; 
tetris *mainOBJ; 
HDC mainHDC; 
HDC testHDC; 

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
    switch (message) 
    { 
    case WM_KEYDOWN: 
     switch (wParam) { 
     case VK_LEFT: 
      mainOBJ->turnPiece(false); 
      InvalidateRect(hWnd, 0, FALSE); 
      break; 
     case VK_RIGHT: 
      mainOBJ->turnPiece(true); 
      InvalidateRect(hWnd, 0, FALSE); 
      break; 
     case VK_UP: 
      mainOBJ->next(mainHDC); 
      InvalidateRect(hWnd, 0, FALSE); 
      break; 
     } 
     break; 
    case WM_COMMAND: 
     //Non-applicable & has not been changed 
    case WM_PAINT: 
     { 
      PAINTSTRUCT ps; 
      HDC hdc = BeginPaint(hWnd, &ps); 

      mainHDC = hdc; 

      HPEN oldP; 
      HPEN newP; 
      COLORREF qLC; 
      qLC = RGB(0, 0, 0); 
      newP = CreatePen(PS_SOLID, 1, qLC); 
      oldP = (HPEN) SelectObject(hdc, newP); 


      tempt++; 
     //USED FOR COUNTING FRAMES WITH DEBUGGER 
      if (tempt % 1 == 0) { 

       if (tempvar == 0) { 
      //CONSTRUCTOR CALL 
        mainOBJ = new tetris(hdc); 
        tempvar++; 
       } 
      //PAINT METHOD CALL 
       mainOBJ->paint(hdc); 
      } 



      if (hdc == NULL) { 

       int x = 3; 
       int y = x + 3; //SET DEBUG_BREAK POINT HERE 
      } 

      testHDC = hdc; 
      SelectObject(hdc, oldP); 
      DeleteObject(newP); 
      EndPaint(hWnd, &ps); 

     } 
     break; 
    } 
} 

頭文件的適用部分,它包含了俄羅斯方塊和片類

class tetris { 
public: 
    class pieces { 
    private: 
     COLORREF **test; 
     int size; 
    public: 
    //Abbreviated for space 
     class O {}; 
     class I {}; 
     class S {}; 
     class Z {}; 
     class T {}; 
     class L {}; 
     class J {}; 
     void setSize(int a) { 
     //Initializing the piece-array 
      test = new COLORREF*[a]; 
      size = a; 
      int i = 0; 
      while (i < a) { 
       test[i] = new COLORREF[a]; 
       i++; 
      } 

     } 
     void setShape(COLORREF **shape) { 
      test = shape; 
     } 
     void setColor(HDC hdc, COLORREF rgb) { 
      HPEN Penn = CreatePen(PS_SOLID, 1, rgb); 
      HPEN Peno = (HPEN)SelectObject(hdc, Penn); 
     } 
     static pieces getObject(char type) { 

      pieces Gen; 
      switch (type) { 

      case 'O': 
      { 
       //Identical (almost) to the other cases 
       O pcs = O(); 
       Gen = *pcs.getObject(); 
       return Gen; 
      } 
      break; 
      case 'I': 
      case 'S': 
      case 'Z': 
      case 'T': 
      case 'L': 
      case 'J': 

      return pieces(); 
     } 

     void turnTet(bool clockwise) { 
      int i = 0; 
      int s; 
      COLORREF **shape; 
      int ter = size - 1; 
      shape = new COLORREF*[2]; 

      while (i < size) { 
       shape[i] = new COLORREF[2]; 

       s = 0; 
       while (s < size) { 
        shape[i][s] = def; 
        s++; 
       } 
       i++; 
      } 
      i = 0; 

      while (i < size) { 

       s = 0; 
       while (s < size) { 
        if (clockwise) { 
         shape[s][ter - i] = test[i][s]; 
        } 
        else { 
         shape[ter - s][i] = test[i][s]; 
        } 
        s++; 
       } 
       i++; 
      } 
      test = shape; 
     } 
     void drawObject(HDC hWnd) { 
      int i = 0; 
      int s; 
      while (i < size) { 
       s = 0; 
       while (s < size) { 
        setColor(hWnd, test[i][s]); 
        int scaleOfBox = 90; 
        DrawBox((s + 1) * scaleOfBox, (i + 1) * scaleOfBox, scaleOfBox - 1, scaleOfBox - 1, hWnd); 
        s++; 
       } 
       i++; 
      } 
     } 
     void DrawBox(int x, int y, int w, int h, HDC hdc) { 
      if (h < 0) { 
       h *= -1; 
      } 
      if (w < 0) { 
       w *= -1; 
      } 

      int i = 0; 
      while (i < h) { 
       MoveToEx(hdc, x, y + i, NULL); 
       LineTo(hdc, x + w, y + i); 

       i++; 
      } 

     } 

    }; 

    tetris(HDC hdc) { 
     refresh(); 
     bagp[cur].drawObject(hdc); 
    } 
    void next(HDC hdc) { 
     bagp[cur].DrawBox(0, 0, 600, 600, hdc); 
     bagp[cur].drawObject(hdc); 
     cur++; 

     if (cur > 6) { 
      refresh(); 
     } 
    } 
    void turnPiece(bool clockwise) { 
     bagp[cur].turnTet(clockwise); 
    } 
    void refresh() { 
     srand(time(NULL)); 
     bag[0] = rand() % 7; 

     int i = 1; 
     while (i < 7) { 
      bool open = false; 
      cur = i; 

      while (!open) { 
       bag[i] = rand() % 7; 
       int s = 1; 
       open = true; 
       while (s <= i) { 
        if (bag[i] == bag[i - s]) { 
         open = false; 
        } 
        s++; 
       } 
      } 
      i++; 
     } 

     cur = 0; 
     while (cur < 7) { 
      switch (bag[cur]) { 
      case 0: 
       bagp[cur] = pieces::getObject('O'); 
       break; 
      case 2: 
       bagp[cur] = pieces::getObject('T'); 
       break; 
      case 1: 
       bagp[cur] = pieces::getObject('I'); 
       break; 
      case 3: 
       bagp[cur] = pieces::getObject('S'); 
       break; 
      case 4: 
       bagp[cur] = pieces::getObject('Z'); 
       break; 
      case 5: 
       bagp[cur] = pieces::getObject('L'); 
       break; 
      case 6: 
       bagp[cur] = pieces::getObject('J'); 
       break; 
      } 

      cur++; 
     } 
     cur = 0; 
    } 
    void paint(HDC hdc) { 
     COLORREF temp = def; 
     bagp[cur].setColor(hdc, temp); 
     bagp[cur].DrawBox(0, 0, 600, 600, hdc); 
     bagp[cur].drawObject(hdc); 
    } 
private: 
    int bag[7]; 
    int cur; 
    pieces bagp[7]; 
}; 

我不明白爲什麼HDC勾銷像它。我再次懷疑它與如何將hdc作爲參數傳遞或者我如何保存hdc有關。請幫助...(謝謝)。

+1

太多無關的文字。您的問題與* Tetris *無關。請以最簡潔的方式說明您的問題。 – IInspectable

回答

0

哦,老同學windows編程...

這可能不是問題的全部,但在你的setColor功能你與CreatePen但從來沒有要求它DeleteObject創建一支筆。這會泄漏資源並最終導致Windows耗盡對象的資源句柄時出現問題。另外,由BeginPaint返回的設備上下文(通常)只有在調用EndPaint之前(除非在CreateWindow調用中另行指定,如果我沒有記錯的話)纔有效。這可能是手柄泄漏的另一個來源。

在任務管理器的進程選項卡中,您可以添加「GDI對象」列,如果您泄漏手柄,程序將運行的列數將增加。我曾經看到過一次,當時我寫回了一些東西。

+1

任務管理器中的列稱爲* GDI對象*。 * Handles *列是指內核對象,而不是GDI對象。 – IInspectable

+0

感謝(至今)似乎工作,並沒有那麼古老。這不像是fortran。 Tsk Tsk,傲慢的程序員。強大的1201ProgramAlarm會提示什麼? –

+0

@IInspectable固定;我正在離開(越來越不值得信任)的記憶。 – 1201ProgramAlarm