#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);这是init用于绘制的一些变量。 感谢您阅读:)
答案 0 :(得分:3)
您在每个wm_paint消息中调用BeginPaint(),但是在wm_paint消息处理程序中没有对EndPaint()的相应调用。每个BeginPaint()必须与相应的EndPaint()匹配。在OnDestroy中调用EndPaint()是没用的。
另外,不要删除BeginPaint()返回的DC。它是借来的,不是拥有的。
其他注意事项:尽量避免在每个wm_paint消息上分配新的位图。当窗口改变大小时分配位图,并保持位置以便被多个wm_paint传递重用。
另请注意,您并未优化绘图以仅绘制剪辑矩形中已失效的内容。你正在绘制所有内容,blitting所有内容,并依赖GDI来仅占用实际位于剪辑矩形中的位图的一小部分。随着窗口/位图大小的增加以及屏幕上运行的对象/精灵数量的增加,这将成为性能问题。您应该只绘制可见的内容并在剪辑内。