ok im creating a game but it uses too much cpu but it doesn't uses too much memory. the cpu does increase and decrease. i have too many timers in my game, i kill the timer when i don't use it any more so that should cause a problem but what i think that causes the problem is there is too many messages in my message qeue. i have new laptop it is 5 months old and it has a high cpu. it uses about 40% of my cpu. is there way to reduce it because when it gets to 40% the game slows down.
here is my code
// Xstrike.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "Xstrike.h"
#include <vector>
#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
RECT *rect;
const UINT_PTR EVERYTHING_ID=0x1;
const UINT_PTR LBUTTONDOWN_ID=0x3;
const UINT_PTR TDENEMIE1_ID=0x4;
const UINT_PTR TAENEMIE1_ID=0x5;
const UINT_PTR PROTECTED_ID=0x6;
int conno=2;
int health=0;
int life=3;
int score=0;
int level=1;
int protect=0;
int cursor=0;
HCURSOR hCursor[3];
// 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);
struct Enemies
{
int cEnemie1;
int dEnemie1;
int aEnemie1;
int sEnemie1;
int pEnemie1;
bool e1;
time_t now;
time_t tEnemie1;
vector <POINT> vS1Enemie1;
vector <POINT> vS2Enemie1;
};
vector <POINT> vRegularShots;
Enemies Enemie1;
VOID installising()
{
Enemie1.cEnemie1=0;
Enemie1.dEnemie1=1;
Enemie1.aEnemie1=0;
Enemie1.sEnemie1=1;
Enemie1.pEnemie1=550;
Enemie1.e1=true;
POINT pt;
pt.x=0;
pt.y=0;
vRegularShots.push_back(pt);
}
VOID Paint(HDC hdc, HWND hWnd)
{
int lifePos=200;
hdc=GetDC(hWnd);
HDC memDC=CreateCompatibleDC(hdc);
HBITMAP hMemMap=CreateCompatibleBitmap(hdc, 225, 350);
HBITMAP hOldMap=(HBITMAP)SelectObject(memDC, hMemMap);
Graphics draw(memDC);
// Drawing
Image bg(L"bg.jpg");
draw.DrawImage(&bg, 0, 0);
// if regular cursor
if(cursor==0)
{
// Regular shots
Image shot(L"RegularShots.png");
long s=vRegularShots.size();
// Draw shots
for(long index=0; index < (long)vRegularShots.size(); ++index)
{
draw.DrawImage(&shot, vRegularShots[index].x, vRegularShots[index].y);
}
// Update the shots
for(long index=0; index < (long)vRegularShots.size(); ++index)
{
vRegularShots[index].y--;
}
// Delete Shots
for(long index=0; index < (long)vRegularShots.size(); index++)
{
if(vRegularShots[index].y<-16)
{
vRegularShots.erase(vRegularShots.begin()+index);
}
}
// Create Enemies
if(Enemie1.dEnemie1==0)
{
if(Enemie1.cEnemie1<2)
{
if(Enemie1.aEnemie1==0)
{
SetTimer(hWnd, TAENEMIE1_ID, 550, NULL);
}
Enemie1.aEnemie1=1;
Enemie1.cEnemie1++;
}
else
{
KillTimer(hWnd, TDENEMIE1_ID);
}
Enemie1.dEnemie1=1;
}
// Draw enemies
for(long index=0; index < (long)Enemie1.vS1Enemie1.size(); ++index)
{
Image iEnemie1(L"Enemie1.png");
draw.DrawImage(&iEnemie1, Enemie1.vS1Enemie1[index].x, Enemie1.vS1Enemie1[index].y);
}
for(long index=0; index < (long)Enemie1.vS2Enemie1.size(); ++index)
{
Image iEnemie1(L"Enemie1.png");
draw.DrawImage(&iEnemie1, Enemie1.vS2Enemie1[index].x, Enemie1.vS2Enemie1[index].y);
}
// Update enemies
for(long index=0; index < (long)Enemie1.vS1Enemie1.size(); index++)
{
Enemie1.vS1Enemie1[index].x++;
Enemie1.vS1Enemie1[index].y++;
}
for(long index=0; index < (long)Enemie1.vS2Enemie1.size(); index++)
{
Enemie1.vS2Enemie1[index].x--;
Enemie1.vS2Enemie1[index].y++;
}
// Delete enemies
for(long index=0; index < (long)Enemie1.vS1Enemie1.size(); index++)
{
if(Enemie1.vS1Enemie1[index].x>225)
{
Enemie1.vS1Enemie1.erase(Enemie1.vS1Enemie1.begin()+index);
}
// Stop enemie1 timer
if(Enemie1.vS1Enemie1.size()==0&&Enemie1.vS2Enemie1.size()==0)
{
KillTimer(hWnd, TAENEMIE1_ID);
}
}
for(long index=0; index < (long)Enemie1.vS2Enemie1.size(); index++)
{
if(Enemie1.vS2Enemie1[index].x<-21)
{
Enemie1.vS2Enemie1.erase(Enemie1.vS2Enemie1.begin()+index);
}
// Stop enemie1 timer
if(Enemie1.vS1Enemie1.size()==0&&Enemie1.vS2Enemie1.size()==0)
{
KillTimer(hWnd, TAENEMIE1_ID);
}
}
// player hits
if(Enemie1.pEnemie1==550)
{
POINT pt;
GetCursorPos(&pt);
ScreenToClient(hWnd, &pt);
for(long index=0; index < (long)Enemie1.vS1Enemie1.size(); index++)
{
if(((pt.x+5)>=Enemie1.vS1Enemie1[index].x&&(pt.x+5)<=(Enemie1.vS1Enemie1[index].x+17)&&pt.y>=Enemie1.vS1Enemie1[index].y&&pt.y<=(Enemie1.vS1Enemie1[index].y+17))||((pt.x+15)>=Enemie1.vS1Enemie1[index].x&&pt.y>=Enemie1.vS1Enemie1[index].y&&pt.y<=(Enemie1.vS1Enemie1[index].y+17)&&(pt.x+14)<=(Enemie1.vS1Enemie1[index].x+17))||((pt.x+21)>=Enemie1.vS1Enemie1[index].x&&(pt.y+14)>=Enemie1.vS1Enemie1[index].y&&(pt.y+14)<=(Enemie1.vS1Enemie1[index].y+17)&&(pt.x+21)<=(Enemie1.vS1Enemie1[index].x+17))||((pt.x+23)>=Enemie1.vS1Enemie1[index].x&&(pt.y+22)>=Enemie1.vS1Enemie1[index].y&&(pt.y+22)<=(Enemie1.vS1Enemie1[index].y+17)&&(pt.x+23)<=(Enemie1.vS1Enemie1[index].x+17))||((pt.x+13)>=Enemie1.vS1Enemie1[index].x&&(pt.y+31)>=Enemie1.vS1Enemie1[index].y&&(pt.y+31)<=(Enemie1.vS1Enemie1[index].y+17)&&(pt.x+13)<=(Enemie1.vS1Enemie1[index].x+17))||(pt.x>=Enemie1.vS1Enemie1[index].x&&(pt.y+22)>=Enemie1.vS1Enemie1[index].y&&(pt.y+22)<=(Enemie1.vS1Enemie1[index].y+17)&&pt.x<=(Enemie1.vS1Enemie1[index].x+21))||((pt.x+3)>=Enemie1.vS1Enemie1[index].x&&(pt.y+14)>=Enemie1.vS1Enemie1[index].y&&(pt.y+14)<=(Enemie1.vS1Enemie1[index].y+21)&&(pt.x+3)<=(Enemie1.vS1Enemie1[index].x+21)))
{
health+=30;
Enemie1.pEnemie1=0;
InvalidateRect(hWnd, rect, false);
}
}
for(long index=0; index < (long)Enemie1.vS2Enemie1.size(); index++)
{
if(((pt.x+5)>=Enemie1.vS2Enemie1[index].x&&(pt.x+5)<=(Enemie1.vS2Enemie1[index].x+17)&&pt.y>=Enemie1.vS2Enemie1[index].y&&pt.y<=(Enemie1.vS2Enemie1[index].y+17))||((pt.x+15)>=Enemie1.vS2Enemie1[index].x&&pt.y>=Enemie1.vS2Enemie1[index].y&&pt.y<=(Enemie1.vS2Enemie1[index].y+17)&&(pt.x+14)<=(Enemie1.vS2Enemie1[index].x+17))||((pt.x+21)>=Enemie1.vS2Enemie1[index].x&&(pt.y+14)>=Enemie1.vS2Enemie1[index].y&&(pt.y+14)<=(Enemie1.vS2Enemie1[index].y+17)&&(pt.x+21)<=(Enemie1.vS2Enemie1[index].x+17))||((pt.x+23)>=Enemie1.vS2Enemie1[index].x&&(pt.y+22)>=Enemie1.vS2Enemie1[index].y&&(pt.y+22)<=(Enemie1.vS2Enemie1[index].y+17)&&(pt.x+23)<=(Enemie1.vS2Enemie1[index].x+17))||((pt.x+13)>=Enemie1.vS2Enemie1[index].x&&(pt.y+31)>=Enemie1.vS2Enemie1[index].y&&(pt.y+31)<=(Enemie1.vS2Enemie1[index].y+17)&&(pt.x+13)<=(Enemie1.vS2Enemie1[index].x+17))||(pt.x>=Enemie1.vS2Enemie1[index].x&&(pt.y+22)>=Enemie1.vS2Enemie1[index].y&&(pt.y+22)<=(Enemie1.vS2Enemie1[index].y+17)&&pt.x<=(Enemie1.vS2Enemie1[index].x+21))||((pt.x+3)>=Enemie1.vS2Enemie1[index].x&&(pt.y+14)>=Enemie1.vS2Enemie1[index].y&&(pt.y+14)<=(Enemie1.vS2Enemie1[index].y+21)&&(pt.x+3)<=(Enemie1.vS2Enemie1[index].x+21)))
{
health+=30;
Enemie1.pEnemie1=0;
InvalidateRect(hWnd, rect, false);
}
}
}
if(health>225)
{
cursor=1;
SetTimer(hWnd, PROTECTED_ID, 1000, NULL);
life--;
health=0;
InvalidateRect(hWnd, rect, false);
}
// Hits
for(long index=0; index < (long)vRegularShots.size(); index++)
{
for(long indexs=0; indexs < (long)Enemie1.vS1Enemie1.size(); indexs++)
{
if((vRegularShots[index].x>=Enemie1.vS1Enemie1[indexs].x && vRegularShots[index].y>=Enemie1.vS1Enemie1[indexs].y && vRegularShots[index].y<=(Enemie1.vS1Enemie1[indexs].y+17) && vRegularShots[index].x<=(Enemie1.vS1Enemie1[indexs].x+17))||(Enemie1.vS1Enemie1[indexs].x>=vRegularShots[index].x && Enemie1.vS1Enemie1[indexs].y>=vRegularShots[index].y && Enemie1.vS1Enemie1[indexs].y<=(vRegularShots[index].y+16) && Enemie1.vS1Enemie1[indexs].x<=(vRegularShots[index].x+5)))
{
Enemie1.vS1Enemie1.erase(Enemie1.vS1Enemie1.begin()+indexs);
vRegularShots[index].y=-17;
score+=100;
// Stop enemie1 timer
if(Enemie1.vS1Enemie1.size()==0&&Enemie1.vS2Enemie1.size()==0)
{
KillTimer(hWnd, TAENEMIE1_ID);
}
}
}
for(long indexs=0; indexs < (long)Enemie1.vS2Enemie1.size(); indexs++)
{
if((vRegularShots[index].x>=Enemie1.vS2Enemie1[indexs].x && vRegularShots[index].y>=Enemie1.vS2Enemie1[indexs].y && vRegularShots[index].y<=(Enemie1.vS2Enemie1[indexs].y+17) && vRegularShots[index].x<=(Enemie1.vS2Enemie1[indexs].x+17))||(Enemie1.vS2Enemie1[indexs].x>=vRegularShots[index].x && Enemie1.vS2Enemie1[indexs].y>=vRegularShots[index].y && Enemie1.vS2Enemie1[indexs].y<=(vRegularShots[index].y+16) && Enemie1.vS2Enemie1[indexs].x<=(vRegularShots[index].x+5)))
{
Enemie1.vS2Enemie1.erase(Enemie1.vS2Enemie1.begin()+indexs);
vRegularShots[index].y=-17;
score+=100;
// Stop enemie1 timer
if(Enemie1.vS1Enemie1.size()==0&&Enemie1.vS2Enemie1.size()==0)
{
KillTimer(hWnd, TAENEMIE1_ID);
}
}
}
}
}
// If protected
if(cursor==1)
{
if(protect!=4)
{
// Regular shots
Image shot(L"RegularShots.png");
// Draw shots
for(long index=0; index < (long)vRegularShots.size(); ++index)
{
draw.DrawImage(&shot, vRegularShots[index].x, vRegularShots[index].y);
}
// Update the shots
for(long index=0; index < (long)vRegularShots.size(); ++index)
{
vRegularShots[index].y--;
}
// Delete Shots
for(long index=0; index < (long)vRegularShots.size(); index++)
{
if(vRegularShots[index].y<-16)
{
vRegularShots.erase(vRegularShots.begin()+index);
}
}
// Delete Shots
for(long index=0; index < (long)vRegularShots.size(); index++)
{
if(vRegularShots[index].y<-16)
{
vRegularShots.erase(vRegularShots.begin()+index);
}
}
// Create Enemies
if(Enemie1.dEnemie1==0)
{
if(Enemie1.cEnemie1<2)
{
if(Enemie1.aEnemie1==0)
{
SetTimer(hWnd, TAENEMIE1_ID, 550, NULL);
}
Enemie1.aEnemie1=1;
Enemie1.cEnemie1++;
}
else
{
KillTimer(hWnd, TDENEMIE1_ID);
}
Enemie1.dEnemie1=1;
}
// Draw enemies
for(long index=0; index < (long)Enemie1.vS1Enemie1.size(); ++index)
{
Image iEnemie1(L"Enemie1.png");
draw.DrawImage(&iEnemie1, Enemie1.vS1Enemie1[index].x, Enemie1.vS1Enemie1[index].y);
}
for(long index=0; index < (long)Enemie1.vS2Enemie1.size(); ++index)
{
Image iEnemie1(L"Enemie1.png");
draw.DrawImage(&iEnemie1, Enemie1.vS2Enemie1[index].x, Enemie1.vS2Enemie1[index].y);
}
// Update enemies
for(long index=0; index < (long)Enemie1.vS1Enemie1.size(); index++)
{
Enemie1.vS1Enemie1[index].x++;
Enemie1.vS1Enemie1[index].y++;
}
for(long index=0; index < (long)Enemie1.vS2Enemie1.size(); index++)
{
Enemie1.vS2Enemie1[index].x--;
Enemie1.vS2Enemie1[index].y++;
}
// Delete enemies
for(long index=0; index < (long)Enemie1.vS1Enemie1.size(); index++)
{
if(Enemie1.vS1Enemie1[index].x>225)
{
Enemie1.vS1Enemie1.erase(Enemie1.vS1Enemie1.begin()+index);
}
// Stop enemie1 timer
if(Enemie1.vS1Enemie1.size()==0&&Enemie1.vS2Enemie1.size()==0)
{
KillTimer(hWnd, TAENEMIE1_ID);
}
}
}
else
{
KillTimer(hWnd, PROTECTED_ID);
cursor=0;
protect=0;
}
}
// Draw Lifes
for(long index=0; index != life; index++)
{
Image lifes(L"lifes.png");
draw.DrawImage(&lifes, lifePos, 275);
lifePos-=30;
}
SolidBrush textColor(Color(255, 255, 54, 0));
LinearGradientBrush linGrBrush(
Point(1000, 20),
Point(health, 20),
Color(255, 255, 0, 0), // opaque black
Color(0, 0, 0, 0)); // opaque red
SolidBrush databrush(Color(0, 225, 0));
draw.FillRectangle(&databrush, 0, 0, 225, 30);
draw.FillRectangle(&linGrBrush, 0, 0, 225, 30);
FontFamily courieNew(L"Courier New");
Font font(&courieNew, 12, 0, UnitPixel);
PointF pLevel(5.0f, 6.0f);
PointF pScore(100.0f, 6.0f);
WCHAR wLevel[11];
WCHAR wScore[60];
_swprintf(wLevel, L"Level : %d", level);
_swprintf(wScore, L"Score : %d", score);
draw.DrawString(wLevel, -1, &font, pLevel, &textColor);
draw.DrawString(wScore, -1, &font, pScore, &textColor);
BitBlt(hdc, 0, 0, 225, 350, memDC, 0, 0, SRCCOPY);
ReleaseDC(hWnd, hdc);
SelectObject(memDC, hOldMap);
DeleteObject(hMemMap);
DeleteDC(memDC);
}
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
// TODO: Place code here.
MSG msg;
HACCEL hAccelTable;
// Cursors
hCursor[0]=LoadCursor(hInstance, MAKEINTRESOURCE(IDC_CURSOR));
hCursor[1]=LoadCursor(hInstance, MAKEINTRESOURCE(IDC_PROTECTED));
// Initialize GDI+.
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_XSTRIKE, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_XSTRIKE));
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
GdiplusShutdown(gdiplusToken);
return (int) msg.wParam;
}
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
// COMMENTS:
//
// This function and its usage are only necessary if you want this code
// to be compatible with Win32 systems prior to the 'RegisterClassEx'
// function that was added to Windows 95. It is important to call this function
// so that the application will get 'well formed' small icons associated
// with it.
//
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_XSTRIKE));
wcex.hCursor = LoadCursor(hInstance, MAKEINTRESOURCE(IDC_CURSOR));
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_XSTRIKE);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassEx(&wcex);
}
//
// FUNCTION: InitInstance(HINSTANCE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindow(szWindowClass, szTitle, (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX),
CW_USEDEFAULT, 0, 225, 350, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
POINT pt;
switch (message)
{
case WM_CREATE:
installising();
SetTimer(hWnd, EVERYTHING_ID, 1, NULL);
break;
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_PAINT:
hdc = BeginPaint(hWnd, &ps);
Paint(hdc, hWnd);
EndPaint(hWnd, &ps);
break;
case WM_LBUTTONDOWN:
GetCursorPos(&pt);
ScreenToClient(hWnd, &pt);
if(conno==1)
{
conno++;
}
else
{
pt.x+=18;
conno--;
}
vRegularShots.push_back(pt);
SetTimer(hWnd, LBUTTONDOWN_ID, 350, NULL);
InvalidateRect(hWnd, rect, false);
break;
case WM_LBUTTONUP:
KillTimer(hWnd, LBUTTONDOWN_ID);
break;
case WM_TIMER:
switch(wParam)
{
case EVERYTHING_ID:
if(Enemie1.e1==true)
{
Enemie1.now=time(NULL);
Enemie1.tEnemie1=Enemie1.now+1;
Enemie1.e1=false;
}
Enemie1.now=time(NULL);
if(Enemie1.now==Enemie1.tEnemie1)
{
SetTimer(hWnd, TDENEMIE1_ID, 550, NULL);
}
InvalidateRect(hWnd, rect, false);
break;
case LBUTTONDOWN_ID:
GetCursorPos(&pt);
ScreenToClient(hWnd, &pt);
if(conno==1)
{
if(cursor==0)
{
conno++;
}
else if(cursor==1)
{
pt.x+=2;
conno++;
}
}
else
{
if(cursor==0)
{
pt.x+=18;
}
else if(cursor==1)
{
pt.x+=15;
}
conno--;
}
vRegularShots.push_back(pt);
break;
case TDENEMIE1_ID:
pt.y=5;
pt.x=-21;
Enemie1.vS1Enemie1.push_back(pt);
pt.y=5;
pt.x=219;
Enemie1.vS2Enemie1.push_back(pt);
Enemie1.dEnemie1=0;
InvalidateRect(hWnd, rect, false);
break;
case TAENEMIE1_ID:
if(Enemie1.pEnemie1!=550)
{
Enemie1.pEnemie1+=550;
}
InvalidateRect(hWnd, rect, false);
break;
case PROTECTED_ID:
protect++;
break;
}
break;
case WM_SETCURSOR:
SetCursor(hCursor[cursor]);
return 0;
break;
case WM_DESTROY:
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;
}
any idea?
My guess would be that you are constantly re-allocating and re-drawing everything instead simply moving the images around. I can see the application frequently having to re-allocate and re-draw from scratch having a bottleneck on the system.
You can optimize a little the paint function.
For example the creation of the four bitmaps could be done in an initialization phase since it is always the same files you are loading.
Also, in all the for loops, you can make one call to the size function of your vector, store it in a temporary variable and use that variable in the for loop for the condition ( as long as the size of the vectors doesn't change in the for loops).
It's very hard to say without knowing more about usage patterns of the thing. A good profiler will do wonders - I've had good luck on Windows with AQTime, although it's not free which may not suit you.
A few observations which may or may not be relevant:
You are drawing using GDI+. It is not fast and may well not scale to what you need. If I wanted rendering of complex scenes, I'd find something else.
I am suspicious about you calling InvalidateRect in your Paint function. Seems odd to me (doesn't painting validate the image?). Also, you are still repainting everything regardless, so what's the point?
You are using erase() on a vector to erase multiple (possibly many) random entries. This has quadratic performance and should be avoided for large vectors.
In one spot there's a pair of nested loops (loop over all 'shots' followed by loop over all 'enemies'); those look like they'll scale badly to large numbers of both.
But you really need to find a profiler; I'm just guessing here.
Please try with the profiler that comes with VS 2010 details of which are here
That may be your best bet on this.
Related
CreateWindow.h
#pragma once
#include <Windows.h>
#include <iostream>
#include <stdint.h>
#include <cmath>
#include <vector>
#include <sstream>
using namespace std;
struct returncursorposdemcical
{
float x, y;
};
struct CustomImage
{
vector<vector<unsigned>> CImage;
int long height, width;
};
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
class window
{
public:
window();
window(const window&) = delete;
window& operator = (const window&) = delete;
~window();
bool windowpro();
void stretchbit();
void backgroundcolor(int R, int G, int B);
private:
};
CreateWindow.cpp
#include "../Header/CreateWindow.h"
WNDCLASS WindowClass = {};
HWND CreateMyWindow;
HDC mydc;
int BitmapWidth;
int BitmapHeight;
RECT ClientRect;
int ClientWidth;
int ClientHeight;
long int buffer_sizes;
void* buffer_memory;
BITMAPINFO buffer_bitmap;
HINSTANCE myhinstance;
window::window()
{
WindowClass.lpszClassName = "Game_Engine";
WindowClass.lpfnWndProc = WindowProc;
WindowClass.hInstance = myhinstance;
WindowClass.hCursor = LoadCursor(0, IDC_CROSS);
RegisterClass(&WindowClass);
CreateMyWindow = CreateWindowEx(0, "Game_Engine", "Program",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
0, 0, GetModuleHandle(nullptr), 0);
mydc = GetDC(CreateMyWindow);
ShowWindow(CreateMyWindow, SW_SHOWMAXIMIZED);
}
window::~window()
{
std::cout << "destroy";
ReleaseDC(CreateMyWindow, mydc);
UnregisterClass("Game_Engine", myhinstance);
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
case WM_MOUSEMOVE:
{
}
case WM_MOUSELEAVE:
{
}
case WM_SIZE:
{
GetClientRect(CreateMyWindow, &ClientRect);
ClientWidth = ClientRect.right - ClientRect.left;
ClientHeight = ClientRect.bottom - ClientRect.top;
BitmapWidth = ClientWidth;
BitmapHeight = ClientHeight;
buffer_sizes = BitmapWidth * BitmapHeight * sizeof(unsigned int);
if (buffer_memory) {
VirtualFree(buffer_memory, 0, MEM_RELEASE);
}
buffer_memory = VirtualAlloc(0, buffer_sizes, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
buffer_bitmap.bmiHeader.biSize = sizeof(buffer_bitmap.bmiHeader);
buffer_bitmap.bmiHeader.biWidth = BitmapWidth;
buffer_bitmap.bmiHeader.biHeight = -BitmapHeight;
buffer_bitmap.bmiHeader.biPlanes = 1;
buffer_bitmap.bmiHeader.biBitCount = 24;
buffer_bitmap.bmiHeader.biCompression = BI_RGB;
}
return 0;
case WM_PAINT:
{
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
bool window::windowpro()
{
MSG msg = { };
while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT) {
return false;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return true;
}
void window::backgroundcolor(int R, int G, int B)
{
unsigned int* pixel = (unsigned int*)buffer_memory;
for (int y = 0; y < BitmapHeight; y++) {
for (int x = 0; x < BitmapWidth; x++)
{
*pixel++ = (R << 16) + (G << 8) + B;
}
}
}
void window::stretchbit()
{
StretchDIBits(mydc, 0, 0, BitmapWidth, BitmapHeight, 0, 0, ClientWidth, ClientHeight, buffer_memory,&buffer_bitmap,DIB_RGB_COLORS,SRCCOPY);
}
Source.cpp
#include "../WindowStartup/Header/CreateWindow.h"
int main()
{
window mywindow;
bool running = true;
while (running == true)
{
mywindow.backgroundcolor(225, 225, 225);
mywindow.stretchbit();
if (!mywindow.windowpro())
{
running = false;
}
}
return 0;
}
I tried to double buffer it, but it didn't work, I tried using bitblit, but it's the same result. Also, when the window resizing, it's not fully painted. And when the window it's not at the full size, it does not look strippy, so my speculation is that either my program is writing the data to bitmap to slow for the refresh rate, or the bitmap it's copying to screen to slow. Sorry for my bad English, English it's not my first language, and I am new to program.
I fixed, all you have to do is change biBitcounts to 32, I don't know why that works, might be some to do with ARGB, although I am only using RGB which is 24bits or 3 bytes, if someone could explain this why I need to change biBitcounts to 32, that would be nice. Also thanks for all the people in the comment that are trying to help me.
I'm trying to write a light Win32 program (OS is Windows XP SP 1) which should draw a 2D plot from a data set stored in a .csv file. I'm using Code::Blocks IDE with a MS Visual C++ Express 2008 compiler. Therefore, I'm also using SDK as a source of Windows headers and libraries.
Here's the code:
main.cpp
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>
#include "daneWykres.h"
static TCHAR szWindowClass[] = _T("win32app");
static TCHAR szTitle[] = _T("Win32 Guided Tour Application");
POINT logicalUnitSize;
RECT ClientRect;
HINSTANCE hInst;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
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, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, IDI_APPLICATION);
if (!RegisterClassEx(&wcex))
{
MessageBox(NULL,
_T("Call to RegisterClassEx failed!"),
_T("Win32 Guided Tour"),
0);
return 1;
}
hInst = hInstance;
logicalUnitSize.x = 560;
logicalUnitSize.y = 560;
HWND hWnd = CreateWindow(
szWindowClass,
szTitle,
WS_OVERLAPPEDWINDOW,
100, 100,
logicalUnitSize.x, logicalUnitSize.y,
NULL,
NULL,
hInstance,
NULL
);
if (!hWnd)
{
MessageBox(NULL,
_T("Call to CreateWindow failed!"),
_T("Win32 Guided Tour"),
0);
return 1;
}
GetClientRect(hWnd,&ClientRect);
ShowWindow(hWnd,
nCmdShow);
UpdateWindow(hWnd);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
daneWykres* rysik = new daneWykres;
rysik->sczytaj(); // method putting data from CSV into a static array dane[][]
int iloscPunktow = rysik->getRozmiar(); // a getter for the array's size (number of points)
double minX = rysik->najmniejsza(0); // the lowest X coordinate
double minY = rysik->najmniejsza(1); // the lowest Y coordinate
double maxX = rysik->najwieksza(0); // the highest X coordinate
double maxY = rysik->najwieksza(1); // the highest Y coordinate
int lgXokna = 30; // top left corner X coordinate of the border rectangle
int lgYokna = 30; // top left corner Y coordinate of the border rectangle
int pdXokna = ClientRect.right - lgXokna; // bottom right corner X coordinate of the border rectangle
int pdYokna = ClientRect.bottom - lgYokna; // bottom right corner Y coordinate of the border rectangle
POINT punkt;
punkt.x = 0;
punkt.y = 0;
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
HPEN hPenOld;
HPEN hSolidPen;
HPEN hBluePen;
COLORREF qLineColor;
qLineColor = RGB(0,0,0);
hSolidPen = CreatePen(PS_SOLID, 1, qLineColor);
qLineColor = RGB(0,0,255);
hBluePen = CreatePen(PS_SOLID, 2, qLineColor);
hPenOld = (HPEN)SelectObject(hdc, hSolidPen);
// the border rectangle
Rectangle(ps.hdc, lgXokna, lgYokna, pdXokna, pdYokna);
hPenOld = (HPEN)SelectObject(hdc, hBluePen);
// draws text every time a daneWykres constructor is called
if (rysik->getFlaga() == true) DrawText(ps.hdc, TEXT("Rysik istnieje"), -1, &ClientRect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
// 'the drawing loop'
for (int i = 0; i < iloscPunktow; i++)
{
punkt.x = lgXokna + ((pdXokna - lgXokna)*(rysik->getSingleData(i,0) - minX)/(maxX - minX));
punkt.y = pdYokna - ((pdYokna - lgYokna)*(rysik->getSingleData(i,1) - minY)/(maxY - minY));
if (i > 0) LineTo(ps.hdc,punkt.x,punkt.y);
MoveToEx(ps.hdc,punkt.x,punkt.y,NULL);
}
SelectObject(hdc,hPenOld);
DeleteObject(hSolidPen);
DeleteObject(hBluePen);
delete rysik;
EndPaint(hWnd, &ps);
break;
case WM_SIZE:
GetClientRect(hWnd,&ClientRect); // update the client area dimensions (and the plot shape with it)
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
}
return 0;
}
daneWykres.h
#ifndef DANEWYKRES_H_INCLUDED
#define DANEWYKRES_H_INCLUDED
#include <fstream>
#include <string>
#include <cstdlib>
using namespace std;
class daneWykres {
static const int rozmiar = 3490; // number of data points
private:
bool flaga; // set to 'true' when constructor is called
ifstream file;
string value;
double wartosc;
double data[rozmiar][2];
public:
daneWykres();
~daneWykres();
double strToDouble(string);
void sczytaj(); // reading method adjusted to the contents of 'file.csv'
double najmniejsza(int indeksKolumny); // returns minimum value in a dataset
double najwieksza(int indeksKolumny); // returns maximum value in a dataset
int getRozmiar();
// returns an X or Y coordinate of a data point by row and column index, respectively
double getSingleData(int indeksWiersza, int indeksKolumny);
bool getFlaga();
};
#endif // DANEWYKRES_H_INCLUDED
daneWykres.cpp
#include "daneWykres.h"
daneWykres::daneWykres()
{
file.open("file.csv");
flaga = true;
}
daneWykres::~daneWykres()
{
file.close();
flaga = false;
}
double daneWykres::strToDouble(string zapis)
{
const char* c = zapis.c_str();
return atof(c);
}
void daneWykres::sczytaj()
{
int i = 0;
while (i < rozmiar)
{
getline(file,value,',');
wartosc = strToDouble(value);
data[i][0] = wartosc;
getline(file,value,',');
wartosc = strToDouble(value);
data[i][1] = wartosc;
getline(file,value,'\n');
i++;
}
}
double daneWykres::najmniejsza(int indeksKolumny)
{
double najmniejsza = data[0][indeksKolumny];
for (int i = 0; i < rozmiar; i++) najmniejsza = ((data[i][indeksKolumny] < najmniejsza) ? data[i][indeksKolumny] : najmniejsza);
return najmniejsza;
}
double daneWykres::najwieksza(int indeksKolumny)
{
double najwieksza = data[0][indeksKolumny];
for (int i = 0; i < rozmiar; i++) najwieksza = ((data[i][indeksKolumny] > najwieksza) ? data[i][indeksKolumny] : najwieksza);
return najwieksza;
}
int daneWykres::getRozmiar()
{
return rozmiar;
}
double daneWykres::getSingleData(int indeksWiersza, int indeksKolumny)
{
return data[indeksWiersza][indeksKolumny];
}
bool daneWykres::getFlaga()
{
return flaga;
}
Also, here's the link to a zip containing 'file.csv', just in case:
https://drive.google.com/file/d/1QHore2OJpQqaAzgxJEiVJIs0BFiSShFo/view?usp=sharing
Whenever I'm running the build via Code::Blocks (don't mind the title) on a machine with Win XP SP1, I see this:
https://imgur.com/SjOMu0G
And after resizing or minimizing a few times I see this:
https://imgur.com/mwzOf3w
I initially thought it was a matter of the object from daneWykres class being prematurely destroyed but the 'Rysik istnieje' string displays properly.
I've got hold of "Programming Windows" by C. Petzold recently but I'm still struggling to understand the basic concepts underlaying WinAPI and it shows.
So, the main question is: why are the black line rectangle and 'Rysik istnieje' string being drawn, yet the blue plot lines cease to be drawn at some point?
EDIT:
I've moved the delete rysik back to the end of the WM_PAINT message. I've separated the declarations and assignments and moved it all into the WM_PAINT message (along with allocation to and deallocation from rysik). This has seemingly helped limit the memory/resource leak.
I've moved the code for opening and reading the file into global functions. The resulting application seems to run smoother but I don't see any significant changes in the Task Manager compared to the earlier edit.
Here's what I have thus far:
main.cpp
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>
#include <fstream>
#include <string>
#include <vector>
#include "daneWykres.h"
static TCHAR szWindowClass[] = _T("win32app");
static TCHAR szTitle[] = _T("My Application");
double data[3490][2];
POINT logicalUnitSize;
RECT ClientRect;
HINSTANCE hInst;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
double strToDouble(string zapis)
{
const char* c = zapis.c_str();
return atof(c);
}
void sczytaj(ifstream& file, double (&data)[3490][2])
{
double wartosc;
string line;
unsigned int i = 0;
unsigned int pos, pos2;
while (getline(file,line))
{
pos = 0;
pos2 = line.find(',',pos);
wartosc = strToDouble(line.substr(pos,(pos2-pos)));
data[i][0] = wartosc;
pos = pos2 + 1;
pos2 = line.find(',',pos);
wartosc = strToDouble(line.substr(pos,(pos2-pos)));
data[i][1] = wartosc;
i++;
}
}
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
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, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, IDI_APPLICATION);
if (!RegisterClassEx(&wcex))
{
MessageBox(NULL,
_T("Call to RegisterClassEx failed!"),
_T("Win32 Guided Tour"),
0);
return 1;
}
hInst = hInstance;
ifstream file;
file.open("file.csv");
sczytaj(file,data);
file.close();
logicalUnitSize.x = 560;
logicalUnitSize.y = 560;
HWND hWnd = CreateWindow(
szWindowClass,
szTitle,
WS_OVERLAPPEDWINDOW,
100, 100,
logicalUnitSize.x, logicalUnitSize.y,
NULL,
NULL,
hInstance,
NULL
);
if (!hWnd)
{
MessageBox(NULL,
_T("Call to CreateWindow failed!"),
_T("Win32 Guided Tour"),
0);
return 1;
}
GetClientRect(hWnd,&ClientRect);
ShowWindow(hWnd,
nCmdShow);
UpdateWindow(hWnd);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
daneWykres* rysik;
rysik = new daneWykres;
int iloscPunktow;
iloscPunktow = rysik->getRozmiar();
double minX, minY, maxX, maxY;
minX = rysik->najmniejsza(data, 0);
minY = rysik->najmniejsza(data, 1);
maxX = rysik->najwieksza(data, 0);
maxY = rysik->najwieksza(data, 1);
int lgXokna, lgYokna, pdXokna, pdYokna;
lgXokna = 30;
lgYokna = 30;
pdXokna = ClientRect.right - lgXokna;
pdYokna = ClientRect.bottom - lgYokna;
POINT punkt;
punkt.x = 0;
punkt.y = 0;
HPEN hPen;
HPEN hSolidPen;
HPEN hBluePen;
hSolidPen = CreatePen(PS_SOLID, 1, RGB(0,0,0));
hBluePen = CreatePen(PS_SOLID, 2, RGB(0,0,255));
hPen = (HPEN)SelectObject(hdc, hSolidPen);
Rectangle(ps.hdc, lgXokna, lgYokna, pdXokna, pdYokna);
SelectObject(hdc,hPen);
DeleteObject(hSolidPen);
hPen = (HPEN)SelectObject(hdc, hBluePen);
if (rysik) DrawText(ps.hdc, TEXT("Rysik istnieje"), -1, &ClientRect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
for (int i = 0; i < iloscPunktow; i++)
{
punkt.x = lgXokna + ((pdXokna - lgXokna)*(data[i][0] - minX)/(maxX - minX));
punkt.y = pdYokna - ((pdYokna - lgYokna)*(data[i][1] - minY)/(maxY - minY));
if (i > 0) LineTo(ps.hdc,punkt.x,punkt.y);
MoveToEx(ps.hdc,punkt.x,punkt.y,NULL);
}
SelectObject(hdc,hPen);
DeleteObject(hBluePen);
delete rysik;
EndPaint(hWnd, &ps);
break;
case WM_SIZE:
GetClientRect(hWnd,&ClientRect);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
}
return 0;
}
daneWykres.h
#ifndef DANEWYKRES_H_INCLUDED
#define DANEWYKRES_H_INCLUDED
#include <fstream>
#include <string>
#include <cstdlib>
#include <vector>
using namespace std;
class daneWykres {
static const int rozmiar = 3490;
private:
public:
daneWykres();
~daneWykres();
double najmniejsza( double (&data)[3490][2], int indeksKolumny);
double najwieksza( double (&data)[3490][2], int indeksKolumny);
int getRozmiar();
};
#endif // DANEWYKRES_H_INCLUDED
daneWykres.cpp
#include "daneWykres.h"
daneWykres::daneWykres()
{
}
daneWykres::~daneWykres()
{
}
double daneWykres::najmniejsza( double (&data)[3490][2], int indeksKolumny)
{
double najmniejsza = data[0][indeksKolumny];
for (int i = 0; i < rozmiar; i++) najmniejsza = ((data[i][indeksKolumny] < najmniejsza) ? data[i][indeksKolumny] : najmniejsza);
return najmniejsza;
}
double daneWykres::najwieksza( double (&data)[3490][2], int indeksKolumny)
{
double najwieksza = data[0][indeksKolumny];
for (int i = 0; i < rozmiar; i++) najwieksza = ((data[i][indeksKolumny] > najwieksza) ? data[i][indeksKolumny] : najwieksza);
return najwieksza;
}
int daneWykres::getRozmiar()
{
return rozmiar;
}
I'm trying to figure out how I can find where to either download the file set or get rid of this error. This elusive 'basewin.h' is nowhere to be found. So I don't know if I'm missing a library or what. I've also tried switching around the 'windows.h' and 'basewin.h' statements. I've tried disabling precompiled headers. Apparently this file holds the information for the "basewindow" class.
I'm using visual studio 2013 and I'm using a win32 project.I'm trying to run the example from the microsoft tutorial website http://msdn.microsoft.com/en-us/library/windows/desktop/ff684181(v=vs.85).aspx. Any help would be very much appreciated. Here is the code:
#include <windows.h>
#include <d2d1.h>
#pragma comment(lib, "d2d1")
#include "basewin.h"
template <class T> void SafeRelease(T **ppT)
{
if (*ppT)
{
(*ppT)->Release();
*ppT = NULL;
}
}
class MainWindow : public BaseWindow<MainWindow>
{
ID2D1Factory *pFactory;
ID2D1HwndRenderTarget *pRenderTarget;
ID2D1SolidColorBrush *pBrush;
D2D1_ELLIPSE ellipse;
void CalculateLayout();
HRESULT CreateGraphicsResources();
void DiscardGraphicsResources();
void OnPaint();
void Resize();
public:
MainWindow() : pFactory(NULL), pRenderTarget(NULL), pBrush(NULL)
{
}
PCWSTR ClassName() const { return L"Circle Window Class"; }
LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
};
// Recalculate drawing layout when the size of the window changes.
void MainWindow::CalculateLayout()
{
if (pRenderTarget != NULL)
{
D2D1_SIZE_F size = pRenderTarget->GetSize();
const float x = size.width / 2;
const float y = size.height / 2;
const float radius = min(x, y);
ellipse = D2D1::Ellipse(D2D1::Point2F(x, y), radius, radius);
}
}
HRESULT MainWindow::CreateGraphicsResources()
{
HRESULT hr = S_OK;
if (pRenderTarget == NULL)
{
RECT rc;
GetClientRect(m_hwnd, &rc);
D2D1_SIZE_U size = D2D1::SizeU(rc.right, rc.bottom);
hr = pFactory->CreateHwndRenderTarget(
D2D1::RenderTargetProperties(),
D2D1::HwndRenderTargetProperties(m_hwnd, size),
&pRenderTarget);
if (SUCCEEDED(hr))
{
const D2D1_COLOR_F color = D2D1::ColorF(1.0f, 1.0f, 0);
hr = pRenderTarget->CreateSolidColorBrush(color, &pBrush);
if (SUCCEEDED(hr))
{
CalculateLayout();
}
}
}
return hr;
}
void MainWindow::DiscardGraphicsResources()
{
SafeRelease(&pRenderTarget);
SafeRelease(&pBrush);
}
void MainWindow::OnPaint()
{
HRESULT hr = CreateGraphicsResources();
if (SUCCEEDED(hr))
{
PAINTSTRUCT ps;
BeginPaint(m_hwnd, &ps);
pRenderTarget->BeginDraw();
pRenderTarget->Clear( D2D1::ColorF(D2D1::ColorF::SkyBlue) );
pRenderTarget->FillEllipse(ellipse, pBrush);
hr = pRenderTarget->EndDraw();
if (FAILED(hr) || hr == D2DERR_RECREATE_TARGET)
{
DiscardGraphicsResources();
}
EndPaint(m_hwnd, &ps);
}
}
void MainWindow::Resize()
{
if (pRenderTarget != NULL)
{
RECT rc;
GetClientRect(m_hwnd, &rc);
D2D1_SIZE_U size = D2D1::SizeU(rc.right, rc.bottom);
pRenderTarget->Resize(size);
CalculateLayout();
InvalidateRect(m_hwnd, NULL, FALSE);
}
}
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR, int nCmdShow)
{
MainWindow win;
if (!win.Create(L"Circle", WS_OVERLAPPEDWINDOW))
{
return 0;
}
ShowWindow(win.Window(), nCmdShow);
// Run the message loop.
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT MainWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CREATE:
if (FAILED(D2D1CreateFactory(
D2D1_FACTORY_TYPE_SINGLE_THREADED, &pFactory)))
{
return -1; // Fail CreateWindowEx.
}
return 0;
case WM_DESTROY:
DiscardGraphicsResources();
SafeRelease(&pFactory);
PostQuitMessage(0);
return 0;
case WM_PAINT:
OnPaint();
return 0;
case WM_SIZE:
Resize();
return 0;
}
return DefWindowProc(m_hwnd, uMsg, wParam, lParam);
}
The page you linked says: "The program re-uses the BaseWindow class that was defined in the topic Managing Application State".
That link contains the code for the BaseWindow class, which you should put in basewin.h.
For the most part this is borrowed code from RasterTeks DX11 tutorial that I am modified lightly or my own use and taste. I am getting a read access violation while using the below InputClass to set keystates.
#include "InputClass.h"
InputClass::InputClass() { }
InputClass::InputClass(const InputClass& other) { }
InputClass::~InputClass() { }
void InputClass::Initialize() {
// Initialize all the keys to being released and not pressed.
for (int i = 0; i<256; i++) {
keystate[i] = false;
}
return;
}
void InputClass::KeyDown(unsigned int input) {
// If a key is pressed then save that state in the key array.
keystate[input] = true;
return;
}
void InputClass::KeyUp(unsigned int input) {
// If a key is released then clear that state in the key array.
keystate[input] = false;
return;
}
bool InputClass::IsKeyDown(unsigned int input) {
// Return what state the key is in (pressed/not pressed).
return keystate[input];
}
Below is my main callback loop, the one registered with the WindowClass:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
// this message is read when the window is closed
case WM_DESTROY: {
PostQuitMessage(0);
return 0;
}
// Check if the window is being closed.
case WM_CLOSE: {
PostQuitMessage(0);
return 0;
}
default: { return ApplicationHandle->MessageHandler(hWnd, message, wParam, lParam); }
}
}
Finally, below is the secondary message handler that is a part of my SystemClass:
LRESULT CALLBACK SystemClass::MessageHandler(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {
switch (message) {
case WM_KEYDOWN: { input->KeyDown((unsigned int)wparam); }
case WM_KEYUP: { input->KeyUp((unsigned int)wparam); }
default: { return DefWindowProc(hwnd, message, wparam, lparam); }
}
}
The exception is fired off when the code gets to my switch/case/default list in the secondary message handler. If I comment these lines out the program happily runs but of course, no input.
Any help or clues would be invaluable. Thank you so much for your time.
Try following modification of your code:
void InputClass::KeyDown(unsigned int input) {
if (input < 0 || input > 255)
return;
// If a key is pressed then save that state in the key array.
keystate[input] = true;
return;
}
void InputClass::KeyUp(unsigned int input) {
if (input < 0 || input > 255)
return;
// If a key is released then clear that state in the key array.
keystate[input] = false;
return;
}
(since you haven't any problems in constructor of InputClass, it is not a problem of private status of array)
I tried it with no luck. I will leave the code in just in case of error, but it called an access violation in the same place.
I will include missing information below.
//inputclass.h
class InputClass
{
public:
InputClass();
InputClass(const InputClass&);
~InputClass();
void Initialize();
void KeyDown(unsigned int);
void KeyUp(unsigned int);
bool IsKeyDown(unsigned int);
//private:
bool keystate[256];
};
//systemclass.h
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <windowsx.h>
#include "InputClass.h"
class SystemClass {
public:
SystemClass();
~SystemClass();
void Startup();
bool InitializeWindows(HWND);
void ShutDown();
void Run();
LRESULT CALLBACK MessageHandler(HWND, UINT, WPARAM, LPARAM);
int GetWindowPosX();
int GetWindowPosY();
int GetWindowWidth();
int GetWindowHeight();
private:
HWND hWnd;
InputClass* input;
int posX, posY, windowWidth, windowHeight;
};
static SystemClass* ApplicationHandle = 0;
//main.cpp
#include "systemclass.h"
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreviousInstance, LPSTR lpCmdLine, int nCmdShow) {
WNDCLASSEX wc;
ZeroMemory(&wc, sizeof(WNDCLASSEX));
SystemClass* system;
system = new SystemClass;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.lpszClassName = L"Engine";
RegisterClassEx(&wc);
system->Startup();
if(!(system->InitializeWindows(CreateWindowEx(NULL,
L"Engine",
L"Engine",
WS_POPUP | WS_VISIBLE,
system->GetWindowPosX(),
system->GetWindowPosY(),
system->GetWindowWidth(),
system->GetWindowHeight(),
NULL,
NULL,
hInstance,
NULL)))) return 0;
system->Run();
system->ShutDown();
UnregisterClass(L"Engine", hInstance);
delete system;
system = 0;
return 0;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
// this message is read when the window is closed
case WM_DESTROY: {
PostQuitMessage(0);
return 0;
}
// Check if the window is being closed.
case WM_CLOSE: {
PostQuitMessage(0);
return 0;
}
default: { return ApplicationHandle->MessageHandler(hWnd, message, wParam, lParam); }
}
}
//systemclass.cpp
#include "SystemClass.h"
SystemClass::SystemClass() { }
SystemClass::~SystemClass() { }
void SystemClass::Startup() {
ApplicationHandle = this;
windowWidth = GetSystemMetrics(SM_CXSCREEN);
windowHeight = GetSystemMetrics(SM_CYSCREEN);
input = new InputClass;
input->Initialize();
int fc = MessageBox(NULL, L"Engine", L"Fullscreen?", MB_YESNO);
switch (fc) {
case 7: {
posX = (windowWidth - 800) / 2;
posY = (windowHeight - 600) / 2;
windowWidth = 800;
windowHeight = 600;
}
case 6: {
DEVMODE dmScreenSettings;
posX = posY = 0;
ZeroMemory(&dmScreenSettings, sizeof(dmScreenSettings));
dmScreenSettings.dmSize = sizeof(dmScreenSettings);
dmScreenSettings.dmPelsWidth = (unsigned long)windowWidth;
dmScreenSettings.dmPelsHeight = (unsigned long)windowHeight;
dmScreenSettings.dmBitsPerPel = 32;
dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
// Change the display settings to full screen.
ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN);
}
}
}
bool SystemClass::InitializeWindows(HWND ihWnd) {
hWnd = ihWnd;
if (hWnd) {
//system->InitializeWindows(hWnd);
ShowWindow(hWnd, SW_SHOW);
SetForegroundWindow(hWnd);
SetFocus(hWnd);
return true;
}
else {
MessageBoxEx(NULL, L"Could not create window.", L"ERROR!", MB_OK | MB_ICONEXCLAMATION, NULL);
return false;
}
}
void SystemClass::ShutDown() {
delete input;
input = 0;
DestroyWindow(hWnd);
hWnd = NULL;
ApplicationHandle = NULL;
}
void SystemClass::Run() {
bool done;
MSG msg;
done = false;
while (!done) {
// Handle the windows messages.
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if (input->IsKeyDown(VK_ESCAPE)) {
done = true;
MessageBoxEx(NULL, L"input broken.", L"ERROR!", MB_OK | MB_ICONEXCLAMATION, NULL);
}
// If windows signals to end the application then exit out.
if (msg.message == WM_QUIT) { done = true; }
}
}
int SystemClass::GetWindowPosX(){ return posX; }
int SystemClass::GetWindowPosY() { return posY; }
int SystemClass::GetWindowWidth() { return windowWidth; }
int SystemClass::GetWindowHeight() { return windowHeight; }
LRESULT CALLBACK SystemClass::MessageHandler(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {
switch (message) {
case WM_KEYDOWN: { input->KeyDown((unsigned int)wparam); }
case WM_KEYUP: { input->KeyUp((unsigned int)wparam); }
default: { return DefWindowProc(hwnd, message, wparam, lparam); }
}
}
The error message given when when I hit the escape key:
Unhandled exception at 0x00881E08 in DX11 Engine 2.exe: 0xC0000005: Access violation reading location 0x00000004.
OK: this is where it gets interesting, the values in the local field (specific to the second callback function) are as follows:
lparam: 65537
wparam: 27
message: 256
hwnd: 0x01b80460 {unused=???}
this: 0x00000000
The value of hwnd, wparam, and lparam are all displayed in red.
I feel like the values are supposed to tell me something about what is going on here but I just don't really understand. Is there a reason why the variable "this" is set to adress 0x00000000? this is a pointer to an instance of the systemclass... or it's supposed to be.
Also, the unused comment in hwnd throws me off, though I'm not sure what is going wrong there since the program is very clearly at least DETECTING a keypress attributed to the window.
I hope this helps anyone with any ideas.
EDIT: You got me looking for a misused pointer and I discovered it had EVERYTHING to do with the "this" pointer and the way I was using system and ApplicationHandle. I fixed it by changing ApplicationHandle to system and simply using the same pointer everywhere. The way I was using it before was illogical and senseless.
Thank you all for helping me find it!
i have to event that should insert values in two vectors but when event get called for the first time it inserts the values successfully but when it get called again it will insert the values in the first vector but not in the second vector than when another event get called the second vector's values will be deleted.
here is the full code
#define MAX_LOADSTRING 100
RECT *rect;
const UINT_PTR EVERYTHING_ID=0x1;
const UINT_PTR LBUTTONDOWN_ID=0x3;
const UINT_PTR TDENEMIE1_ID=0x4;
const UINT_PTR TAENEMIE1_ID=0x5;
int conno=2;
int side=0;
int cEnemie1=0;
int dEnemie1=1;
int aEnemie1=0;
int sEnemie1=1;
bool e1=true;
time_t now;
time_t tEnemie1;
vector <POINT> vRegularShots;
vector <POINT> vS1Enemie1;
vector <POINT> vS2Enemie1;
VOID Paint(HDC hdc, HWND hWnd)
{
hdc=GetDC(hWnd);
HDC memDC=CreateCompatibleDC(hdc);
HBITMAP hMemMap=CreateCompatibleBitmap(hdc, 225, 350);
HBITMAP hOldMap=(HBITMAP)SelectObject(memDC, hMemMap);
Graphics draw(memDC);
// Drawing
Image bg(L"bg.jpg");
draw.DrawImage(&bg, 0, 0);
// Regular shots
Image shot(L"RegularShots.png");
long s=vRegularShots.size();
// Draw shots
for(long index=0; index < (long)vRegularShots.size(); ++index)
{
draw.DrawImage(&shot, vRegularShots[index].x, vRegularShots[index].y);
}
// Update the shots
for(long index=0; index < (long)vRegularShots.size(); ++index)
{
vRegularShots[index].y--;
}
// Create Enemies
if(dEnemie1==0)
{
if(cEnemie1<2)
{
if(aEnemie1==0)
{
SetTimer(hWnd, TAENEMIE1_ID, 550, NULL);
}
aEnemie1=1;
cEnemie1++;
}
else
{
KillTimer(hWnd, TDENEMIE1_ID);
}
dEnemie1=1;
}
// Draw enemies
for(long index=0; index < (long)vS1Enemie1.size(); ++index)
{
Image iEnemie1(L"Enemie1.png");
draw.DrawImage(&iEnemie1, vS1Enemie1[index].x, vS1Enemie1[index].y);
}
for(long index=0; index < (long)vS2Enemie1.size(); ++index)
{
Image iEnemie1(L"Enemie1.png");
draw.DrawImage(&iEnemie1, vS2Enemie1[index].x, vS2Enemie1[index].y);
}
// Update enemies
for(long index=0; index < (long)vS1Enemie1.size(); index++)
{
vS1Enemie1[index].x++;
vS1Enemie1[index].y++;
}
for(long index=0; index < (long)vS2Enemie1.size(); index++)
{
vS2Enemie1[index].x--;
vS2Enemie1[index].y++;
}
// Delete enemies
for(long index=0; index < (long)vS1Enemie1.size(); index++)
{
if(vS1Enemie1[index].x>225)
{
vS1Enemie1.erase(vS1Enemie1.begin()+index);
}
}
for(long index=0; index < (long)vS2Enemie1.size(); index++)
{
if(vS2Enemie1[index].x>225)
{
vS2Enemie1.erase(vS2Enemie1.begin()+index);
}
}
BitBlt(hdc, 0, 0, 225, 350, memDC, 0, 0, SRCCOPY);
ReleaseDC(hWnd, hdc);
SelectObject(memDC, hOldMap);
DeleteObject(hMemMap);
DeleteDC(memDC);
}
VOID CheckDead()
{
for(long index=0; index < (long)vRegularShots.size(); ++index)
{
vRegularShots[index].x, vRegularShots[index].y;
}
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
POINT pt;
POINT pts;
switch (message)
{
case WM_CREATE:
SetTimer(hWnd, EVERYTHING_ID, 1, NULL);
break;
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_PAINT:
hdc = BeginPaint(hWnd, &ps);
Paint(hdc, hWnd);
EndPaint(hWnd, &ps);
break;
case WM_LBUTTONDOWN:
GetCursorPos(&pt);
ScreenToClient(hWnd, &pt);
if(conno==1)
{
conno++;
}
else
{
pt.x+=18;
conno--;
}
vRegularShots.push_back(pt);
SetTimer(hWnd, LBUTTONDOWN_ID, 350, NULL);
InvalidateRect(hWnd, rect, false);
break;
case WM_LBUTTONUP:
KillTimer(hWnd, LBUTTONDOWN_ID);
break;
case WM_TIMER:
switch(wParam)
{
case EVERYTHING_ID:
if(e1==true)
{
now=time(NULL);
tEnemie1=now+1;
e1=false;
}
now=time(NULL);
if(now==tEnemie1)
{
SetTimer(hWnd, TDENEMIE1_ID, 550, NULL);
}
InvalidateRect(hWnd, rect, false);
break;
case LBUTTONDOWN_ID:
GetCursorPos(&pt);
ScreenToClient(hWnd, &pt);
if(conno==1)
{
conno++;
}
else
{
pt.x+=18;
conno--;
}
vRegularShots.push_back(pt);
break;
case TDENEMIE1_ID:
pt.y=5;
pt.x=-26;
vS1Enemie1.push_back(pt);
pt.y=52;
pt.x=251;
vS2Enemie1.push_back(pt);
dEnemie1=0;
InvalidateRect(hWnd, rect, false);
break;
case TAENEMIE1_ID:
InvalidateRect(hWnd, rect, false);
break;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
i set a break point at dEnemie1=0 in TAENEMIE1_ID.
anyidea?
For one thing, these two loops have issues:
// Delete enemies
for(long index=0; index < (long)vS1Enemie1.size(); index++)
{
if(vS1Enemie1[index].x>225)
{
vS1Enemie1.erase(vS1Enemie1.begin()+index);
}
}
for(long index=0; index < (long)vS2Enemie1.size(); index++)
{
if(vS2Enemie1[index].x>225)
{
vS2Enemie1.erase(vS2Enemie1.begin()+index);
}
}
One issue with each is that when you erase the POINT at index index, then all POINTs at indices index + 1, index + 2, etc. are shifted to the left by one. So, when you increment index, you skip a POINT. The other issue is that you should be using the unsigned size_type as the type of your indexing variable rather than casting to long, which is signed.
Here is corrected code:
// Delete enemies
vector <POINT>::size_type index;
for(index=0; index < vS1Enemie1.size(); )
{
if(vS1Enemie1[index].x>225)
{
vS1Enemie1.erase(vS1Enemie1.begin()+index);
}
else
++index;
}
for(index=0; index < vS2Enemie1.size(); )
{
if(vS2Enemie1[index].x>225)
{
vS2Enemie1.erase(vS2Enemie1.begin()+index);
}
else
++index;
}
It would be even better if you used iterators:
// Delete enemies
vector <POINT>::iterator it;
for(it=vS1Enemie1.begin(); it != vS1Enemie1.end(); )
{
if(it->x > 225)
{
it = vS1Enemie1.erase(it);
}
else
++it;
}
for(it=vS2Enemie1.begin(); it != vS2Enemie1.end(); )
{
if(it->x > 225)
{
it = vS2Enemie1.erase(it);
}
else
++it;
}