2010-05-12 141 views
1
#include "stdafx.h" 

// Mario Headers 
#include "GameMain.h" 

#define MAX_LOADSTRING 100 

// Global Variables: 
HINSTANCE hInst;        // current instance 
TCHAR szTitle[MAX_LOADSTRING];     // The title bar text 
TCHAR szWindowClass[MAX_LOADSTRING];   // the main window class name 

// Mario global variables ================= 
CGameMain* gGameMain; 
HWND hWnd; 
PAINTSTRUCT ps; 
// ======================================== 



// Forward declarations of functions included in this code module: 
ATOM    MyRegisterClass(HINSTANCE hInstance); 
BOOL    InitInstance(HINSTANCE, int); 
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); 

// My unprocess function ===================================== 
void OnCreate(HWND hWnd) 
{ 
} 
void OnKeyUp(WPARAM wParam) 
{ 
    switch (wParam) { 
       case VK_LEFT: 
        gGameMain->KeyReleased(LEFT); 
        break; 
       case VK_UP: 
        gGameMain->KeyReleased(UP); 
        break; 
       case VK_RIGHT: 
        gGameMain->KeyReleased(RIGHT); 
        break; 
       case VK_DOWN: 
        gGameMain->KeyReleased(DOWN); 
        break; 
    } 
} 
void OnKeyDown(HWND hWnd,WPARAM wParam) 
{ 
    switch (wParam) { 
       case VK_LEFT: 
        gGameMain->KeyPressed(LEFT); 
        break; 
       case VK_UP: 
        gGameMain->KeyPressed(UP); 
        break; 
       case VK_RIGHT: 
        gGameMain->KeyPressed(RIGHT); 
        break; 
       case VK_DOWN: 
        gGameMain->KeyPressed(DOWN); 
        break; 
      } 
} 
void OnPaint(HWND hWnd) 
{ 
    HDC hdc = BeginPaint(hWnd,&ps); 

    RECT rect; 
    GetClientRect(hWnd,&rect); 

    HDC hdcDouble  = CreateCompatibleDC(hdc); 
    HBITMAP hdcBitmap = CreateCompatibleBitmap(hdc,rect.right,rect.bottom); 
    HBITMAP bmOld  = (HBITMAP)SelectObject(hdcDouble, hdcBitmap); 

    gGameMain->SetHDC(&hdcDouble); 
    gGameMain->SendMessage(MESSAGE_PAINT); 

    BitBlt(hdc,0,0,rect.right,rect.bottom,hdcDouble,0,0,SRCCOPY); 
    SelectObject(hdcDouble,bmOld); 
    DeleteDC(hdcDouble); 
    DeleteObject(hdcBitmap); 
    DeleteDC(hdc); 
} 

void OnDestroy() 
{ 
    gGameMain->isPlaying = false; 
    EndPaint(hWnd,&ps); 
} 
// My unprocess function ===================================== 

ATOM MyRegisterClass(HINSTANCE hInstance) 
{ 
    WNDCLASSEX wcex; 

    wcex.cbSize = sizeof(WNDCLASSEX); 

    wcex.style   = CS_HREDRAW | CS_VREDRAW; 
    wcex.lpfnWndProc = WndProc; 
    wcex.cbClsExtra  = 0; 
    wcex.cbWndExtra  = 0; 
    wcex.hInstance  = hInstance; 
    wcex.hIcon   = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_GDIMARIO)); 
    wcex.hCursor  = LoadCursor(NULL, IDC_ARROW); 
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); 
    wcex.lpszMenuName = MAKEINTRESOURCE(IDC_GDIMARIO); 
    wcex.lpszClassName = szWindowClass; 
    wcex.hIconSm  = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); 

    return RegisterClassEx(&wcex); 
} 

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) 
{ 

    hInst = hInstance; // Store instance handle in our global variable 

    hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, 
     CW_USEDEFAULT, CW_USEDEFAULT, WIDTH, HEIGHT, 0, NULL, hInstance, NULL); 
    if (!hWnd) 
    { 
     return FALSE; 
    } 

    // ---------------- Start gdiplus ------------------ 
    GdiplusStartup(&gdiToken,&gdiStartInput,NULL); 
    // ------------------------------------------------- 

    // Init GameMain 
    gGameMain = new CGameMain(); 

    ShowWindow(hWnd, nCmdShow); 
    UpdateWindow(hWnd); 

    return TRUE; 
} 

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
    int wmId, wmEvent; 
    switch (message) 
    { 
    case WM_COMMAND: 
     wmId = LOWORD(wParam); 
     wmEvent = HIWORD(wParam); 
     // Parse the menu selections: 
     switch (wmId) 
     { 
     case IDM_ABOUT: 
      DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); 
      break; 

     case IDM_EXIT: 
      DestroyWindow(hWnd); 
      break; 

     default: 
      return DefWindowProc(hWnd, message, wParam, lParam); 
     } 
     break; 
    case WM_KEYDOWN: 
     OnKeyDown(hWnd,wParam); 
     break; 
    case WM_KEYUP: 
     OnKeyUp(wParam);  
     break; 
    case WM_CREATE: 
     OnCreate(hWnd); 
     break; 
    case WM_PAINT:   
     OnPaint(hWnd); 
     break; 
    case WM_DESTROY: 
     OnDestroy(); 
     PostQuitMessage(0); 
     break; 
    default: 
     return DefWindowProc(hWnd, message, wParam, lParam); 
    } 
    return 0; 
} 

// Message handler for about box. 
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) 

{ 
    UNREFERENCED_PARAMETER(lParam); 
    switch (message) 
    { 
    case WM_INITDIALOG: 
     return (INT_PTR)TRUE; 

    case WM_COMMAND: 
     if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 
     { 
      EndDialog(hDlg, LOWORD(wParam)); 
      return (INT_PTR)TRUE; 
     } 
     break; 
    } 
    return (INT_PTR)FALSE; 
} 
int APIENTRY _tWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine,int nCmdShow) 
{ 
    UNREFERENCED_PARAMETER(hPrevInstance); 
    UNREFERENCED_PARAMETER(lpCmdLine); 

    // TODO: Place code here. 
    MSG msg; 
    HACCEL hAccelTable; 

    // Initialize global strings 
    LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); 
    LoadString(hInstance, IDC_GDIMARIO, szWindowClass, MAX_LOADSTRING); 
    MyRegisterClass(hInstance); 

    // Perform application initialization: 
    if (!InitInstance (hInstance, nCmdShow)) 
    { 
     return FALSE; 
    } 

    hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_GDIMARIO)); 

    // Main message loop: 
    // GameLoop 

    PeekMessage(&msg,NULL,0,0,PM_NOREMOVE); 

    while (gGameMain->isPlaying) 
    { 
     while (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { 
      if (msg.message == WM_QUIT) 
       break; 

      TranslateMessage(&msg); 
      DispatchMessage(&msg); 
     } 
     if (gGameMain->enterNextState) { 
      gGameMain->SendMessage(MESSAGE_ENTER); 
      gGameMain->enterNextState = false; 
     } 

     gGameMain->SendMessage(MESSAGE_UPDATE); 
     InvalidateRect(hWnd,NULL,FALSE); 
     /*if (gGameMain->exitCurrentState) { 
      gGameMain->SendMessage(MESSAGE_EXIT); 
      gGameMain->enterNextState = true; 
      gGameMain->exitCurrentState = false; 
     }*/ 
     ::Sleep(gGameMain->timer); 
      // Do your game stuff here 
    } 

    GdiplusShutdown(gdiToken); // Shut down gdiplus token 

    return (int) msg.wParam; 
} 

我使用InvalidateRect(hWnd,NULL,FALSE);重新繪製窗口,但我遇到的問題是當我重繪沒有任何更改Game結構。 (只調用InvalidateRect(hWnd,NULL,FALSE);沒有gGameMain-> SendMessage(MESSAGE_ENTER);這是初始化一些繪製變量。 感謝您閱讀此:)重繪窗口問題

回答

3

您在每個wm_paint消息中調用BeginPaint(),但在wm_paint消息處理函數中沒有對應的EndPaint()調用。每個BeginPaint()必須與相應的EndPaint()匹配。 OnDestroy中的EndPaint()調用沒有用處。

另外,不要刪除BeginPaint()返回的DC。它是借來的,不是擁有的。

其他注意事項:儘量避免在每個wm_paint消息上分配一個新的位圖。當窗口更改大小時分配位圖,並保留它以供多個wm_paint傳遞重用。

另請注意,您並未優化繪圖以僅繪製在剪輯矩形中已失效的內容。您正在繪製所有內容,將所有內容都拍攝下來,並依靠GDI來僅佔用實際位於剪輯中的小部分位圖。隨着窗口/位圖大小的增加以及在屏幕上運行的對象/精靈數量的增加,這將成爲性能問題。您只應繪製可見並在剪輯內的東西。

+0

我該如何使用一個位圖。我謹HDC =調用BeginPaint(HWND,&ps);中的OnPaint。 每次節目EXCUTE HDC =調用BeginPaint(HWND,&ps);,HDC地址改變,我必須重新進行添加hdcDouble,hdcBitmap。我是新來這個,謝謝:) – nXqd 2010-05-13 00:35:48

+0

你可以也可以提前創建你的hdcDouble--它不必由BeginPaint返回的hdc構造,GetDC(0)將爲屏幕設備返回一個與CreateCompatibleDC相同的dc值,你需要放棄如果用戶改變屏幕設置,所以你需要聽取相應的消息通知你。 是的,你需要在每個OnPaint調用中使用hdc = BeginPaint(...),但是hdcDouble會不必從該hdc構建.BitBlt將位圖hdc中的像素複製到屏幕hdc。 – dthorpe 2010-05-13 05:37:18