windows游戏编程<十一>封装窗口类

 

本系列文章由jadeshu编写,转载请注明出处。http://blog.csdn.net/jadeshu/article/details/22451353

作者:jadeshu   邮箱: jadeshu@qq.com    欢迎邮件交流

 

1.由于除了少数固定窗口的游戏可以不考虑分辨率的处理,大部分游戏都要考虑不同分辨率的情况,所以需要具备这么能处理分辨率!因此我们将显示模式添加窗口类中,如下,可以简单处理

2.就是一些WIN32创建窗口的方面问题

3.

 

 

#ifndef _JSWND_H_
#define _JSWND_H_

#include <windows.h>
#include <typeinfo.h>
#include <time.h>
#include <sstream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <math.h>
using namespace std;
#include <gdiplus.h>
#pragma comment(lib,"Msimg32.lib")
#pragma comment(lib,"gdiplus.lib")
using namespace Gdiplus;

static const LPCTSTR G_WIN_CLASS	 = TEXT("JS");					//默认注册的窗口类名
static const LPCTSTR G_WIN_TITLE	 = TEXT("JSWnd Ver 1.0");		//默认窗口标题
static const int G_WIN_WIDTH		 = 1024;						//默认游戏窗口宽
static const int G_WIN_HEIGHT		 = 768;							//默认游戏窗口高

//游戏状态枚举常量定义
enum GAME_STATE
{
	GAME_START,				//开始
	GAME_RUN,				//运行
	GAME_PAUSE,				//暂停
	GAME_UPGRADE,			//升级
	GAME_WIN,				//通关
	GAME_OVER,				//结束
	GAME_HELP,				//帮助状态
	GAME_ABOUT,				//关于状态
	GAME_SETTING			//设置状态
};

//按键行为常量
enum KM_ACTION
{
	KEY_SYS_NONE,			//非系统按键处理
	KEY_UP,					//释放按键
	KEY_DOWN,				//按下键
	MOUSE_MOVE,				//鼠标移动
	MOUSE_LCLICK,			//鼠标左键点击
	MOUSE_RCLICK			//鼠标右键点击
};

class CJSWnd
{
	
public:
	CJSWnd(HINSTANCE hInstance, LPCTSTR szWindowClass = G_WIN_CLASS, 
		     LPCTSTR szTitle = G_WIN_TITLE, 
		     WORD Icon = NULL, WORD SmIcon = NULL, 
		     int iWidth = G_WIN_WIDTH, int iHeight = G_WIN_HEIGHT);
	virtual ~CJSWnd();

	inline int GetInterval() { return _IntervalTime; }									//获取游戏帧刷新间隔时间
	inline void SetFrame(int iTime) { _IntervalTime = 1000 / iTime; }					//设置游戏帧刷新间隔时间
	inline BOOL GetSleep() { return _bIsAsleep; }										//获取窗口是否为焦点状态
	inline void SetSleep(BOOL asleep) { _bIsAsleep = asleep; }							//设置窗口是否为焦点状态
	inline void SetFullScreen(BOOL isFull){ _bFullScreen = isFull; }					//设置窗口是否全屏显示
	inline bool CheckKey(WPARAM wParam){ return _bKeys[wParam]; }						//获取当前的按键状态

	BOOL WndInit();																		//注册 创建 显示 更新窗口

	static LONG CALLBACK DefProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam );	//静态回调函数
	
	LONG WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);					//消息处理函数,将被回调函数调用
	void Run();																			//启动游戏引擎

	virtual void GameInit()=0;															//游戏初始化
	virtual void GameLogic()=0;															//游戏逻辑处理
	virtual void GameEnd()=0;															//游戏结束处理
	virtual void GamePaint(HDC hdc)=0;													//根据GAME_STATE值显示游戏界面
	virtual void GameKeyAction(KM_ACTION ActionType=KEY_SYS_NONE)=0;					//处理按键行为
	virtual void GameMouseAction(int x, int y, KM_ACTION ActionType)=0;					//处理鼠标行为

	void SaveMode();																	//存储现在的显示模式
	void ResetMode();																	//还原之前的存储的显示模式
	bool ChangeMode(int ChangeWidth, int ChangeHeight);									//更改显示模式


	static CJSWnd* m_pWnd;				//窗口接口指针
	//CJSWnd *GetPwnd(){ return m_pWnd;}

private:
        void SubKeyAction(WPARAM wParam);	//附加按键行为处理

protected:
	HWND _hWnd;							//窗口句柄
	HINSTANCE _hInstance;				//实例句柄
	LPCTSTR _wndClass;					//窗口类名
	LPCTSTR _wndTitle;					//窗口标题
	int _wndWidth, _wndHeight;			//窗口高度和宽度
	int _scrnWidth, _scrnHeight;		//屏幕分辨率宽和高
	WORD _wIcon, _wSmIcon;				//程序大图标和小图标
	BOOL _bFullScreen;					//全屏标志

	int _IntervalTime;					//游戏帧刷新间隔时间
	BOOL _bIsAsleep;					//窗口是否处于非焦点状态
	GAME_STATE _GameState;				//游戏状态(为GAME_STATE常量值)
	bool _bKeys[256];					//记录键盘状态的数组(是否按下标志)

	RECT _rcOldRect;					//当前窗口尺寸
	LONG _style;						//窗口基本风格
	LONG _ex_style;						//窗口扩展风格

	HBITMAP _hBufferBitmap;				//内存缓冲位图
	HDC _hBufferDC;						//内存缓冲DC

	
private:
	ULONG_PTR __ptrGdiplusToken;		//对GDI+的引用
	HBITMAP __oldHbitmap;				//旧的内存位图
	
	DEVMODE	__devmodeSaved;
	bool __modeChanged;
};

#endif

 

 

 

#include "JSWnd.h"

CJSWnd *CJSWnd::m_pWnd = NULL;		//引擎类指针

CJSWnd::CJSWnd(HINSTANCE hInstance, LPCTSTR szWindowClass, 
	       LPCTSTR szTitle, WORD Icon /* = NULL */, WORD SmIcon /* = NULL */, 
		   int iWidth /* = G_WIN_WIDTH */, int iHeight /* = G_WIN_HEIGHT */):_hInstance(hInstance),_wndClass(szWindowClass),
		   _wndTitle(szTitle),_wndWidth(iWidth),_wndHeight(iHeight),_wIcon(Icon),_wSmIcon(SmIcon),_bFullScreen(FALSE),
		   _IntervalTime(40),_bIsAsleep(FALSE),/*_GameState(GAME_START),*/__modeChanged(false)
{
	Gdiplus::GdiplusStartupInput gdiplusStartupInput;
	Gdiplus::GdiplusStartup(&__ptrGdiplusToken,&gdiplusStartupInput,NULL);

	m_pWnd = this;
	for (int i=0;i<256;i++)
	{
		_bKeys[i] = false;
	}
	SaveMode();
}

CJSWnd::~CJSWnd()
{
	if (__oldHbitmap)
	{
		::SelectObject(_hBufferDC,__oldHbitmap);
	}
	if (_hBufferBitmap)
	{
		::DeleteObject(_hBufferBitmap);
		_hBufferBitmap = NULL;	
	}
	if (_hBufferDC)
	{
		::DeleteDC(_hBufferDC);
	}
	::DeleteObject(__oldHbitmap);
	__oldHbitmap = NULL;

	ResetMode();

	Gdiplus::GdiplusShutdown(__ptrGdiplusToken);		//关闭GDI+
}

//注册 创建 显示 更新窗口
BOOL CJSWnd::WndInit()
{
	WNDCLASSEX wndClassex;
	wndClassex.cbSize = sizeof(WNDCLASSEX);
	wndClassex.style = CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS;
	wndClassex.lpfnWndProc = DefProc;
	wndClassex.cbClsExtra = wndClassex.cbWndExtra = 0;
	wndClassex.hInstance = _hInstance;
	wndClassex.hIcon = ::LoadIcon(_hInstance,MAKEINTRESOURCE(_wIcon));
	wndClassex.hCursor = ::LoadCursor(NULL,IDC_ARROW);
	wndClassex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
	wndClassex.lpszMenuName = NULL;
	wndClassex.lpszClassName = _wndClass;
	wndClassex.hIconSm = ::LoadIcon(_hInstance,MAKEINTRESOURCE(_wSmIcon));

	if (!::RegisterClassEx(&wndClassex))
	{
		return FALSE;
	}
	//使窗口居中,获取客户区全屏幕宽高(去掉任务栏高度)
	//如果要获取完全全屏幕宽高,包括任务栏高度,使用SM_CXSCREEN和SM_CYSCREEN
	_scrnWidth = ::GetSystemMetrics(SM_CXFULLSCREEN);		//屏幕宽度
	_scrnHeight = ::GetSystemMetrics(SM_CYFULLSCREEN);		//屏幕高度
	int x = (_scrnWidth - _wndWidth)/2;
	int y = (_scrnHeight - _wndHeight)/2;

	//获取窗口边框和标题栏大小
	int iXFrameSize = ::GetSystemMetrics(SM_CXBORDER);
	int iYFrameSize = ::GetSystemMetrics(SM_CYBORDER);
	int iCaptionSize = ::GetSystemMetrics(SM_CYCAPTION);
	_hWnd = ::CreateWindow(_wndClass,_wndTitle,
		WS_OVERLAPPEDWINDOW&~WS_SIZEBOX,									//禁止调整大小
		x,y,_wndWidth+2*iXFrameSize,_wndHeight+iCaptionSize+2*iYFrameSize,	//加上窗口边框和标题栏占用
		NULL,NULL,_hInstance,NULL);

	if (!_hWnd)
	{
		return FALSE;
	}

	//如果是全屏的话,改为全屏模式
	if (_bFullScreen == TRUE)
	{
		::GetWindowRect(_hWnd,&_rcOldRect);
		_style = ::GetWindowLong(_hWnd,GWL_STYLE);
		_ex_style = ::GetWindowLong(_hWnd,GWL_EXSTYLE);
		SaveMode();
		HWND hDesktop;	
		hDesktop = ::GetDesktopWindow();			//获取桌面窗口的句柄
		RECT rc;
		::GetWindowRect(hDesktop,&rc);
		ChangeMode(_wndWidth,_wndHeight);

		//设置为WS_DLGFRAME.WS_BORDER或WS_EX_CLIENTEDGE都可以去掉标题栏
		//设置扩展风格为WS_EX_WINDOWEDGE,去掉窗口边框
		::SetWindowLong(_hWnd,GWL_EXSTYLE,WS_EX_WINDOWEDGE);
		::SetWindowLong(_hWnd,GWL_STYLE,WS_BORDER);
		::SetWindowPos(_hWnd,HWND_TOP,-1,-1,rc.right,rc.bottom,SWP_SHOWWINDOW);
	}

	HDC _hdc = ::GetDC(_hWnd);
	_hBufferDC = ::CreateCompatibleDC(_hdc);
	_hBufferBitmap = ::CreateCompatibleBitmap(_hdc,_wndWidth,_wndHeight);
	__oldHbitmap = (HBITMAP)::SelectObject(_hBufferDC,_hBufferBitmap);
	::ReleaseDC(_hWnd,_hdc);


	::ShowWindow(_hWnd,SW_NORMAL);
	::UpdateWindow(_hWnd);
	return TRUE;
}

//附加按键行为处理(此处处理Esc键)
void CJSWnd::SubKeyAction(WPARAM wParam)
{
	int x,y;
	if (wParam == VK_ESCAPE)			 //按下ESC键
	{
		_bFullScreen = !_bFullScreen;  //设置全屏显示标志
		if (!_bFullScreen)				 //恢复窗口模式
		{
			ResetMode();
			::SetWindowLong(_hWnd,GWL_STYLE,_style);
			::SetWindowLong(_hWnd,GWL_EXSTYLE,_ex_style);
			int oldWidth = _rcOldRect.right - _rcOldRect.left;
			int oldHeight = _rcOldRect.bottom - _rcOldRect.top;
			x = _rcOldRect.left;
			y = _rcOldRect.top;
			::SetWindowPos(_hWnd,HWND_NOTOPMOST,x,y,oldWidth,oldHeight,SWP_SHOWWINDOW);
		}
		else						//显示退出程序对话框
		{
			::ShowCursor(true);		//显示光标
			if (IDOK == ::MessageBox(NULL,L"你确定要退出吗?",_wndTitle,MB_OKCANCEL|MB_ICONQUESTION))
			{
				::DestroyWindow(_hWnd);
			}
		}
	}
}


LONG CALLBACK CJSWnd::DefProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
	return m_pWnd->WindowProc(hWnd,msg,wParam,lParam);		//调用类中的消息处理函数
}

LONG CJSWnd::WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg)
	{
	case WM_SETFOCUS:
		{
			SetSleep(FALSE);
			return 0;
		}
	case WM_KILLFOCUS:
		{
			SetSleep(TRUE);
			return 0;
		}
	case WM_CREATE:
		{
			GameInit();
			return 0;
		}
	case WM_LBUTTONDOWN:							//鼠标左键按下的处理
		{
			GameMouseAction(LOWORD(lParam),HIWORD(lParam),MOUSE_LCLICK);
			return 0;
		}
	case WM_RBUTTONDOWN:							//鼠标右键按下的处理
		{
			GameMouseAction(LOWORD(lParam),HIWORD(lParam),MOUSE_RCLICK);
			return 0;
		}
	case WM_MOUSEMOVE:								//鼠标移动处理
		{
			GameMouseAction(LOWORD(lParam),HIWORD(lParam),MOUSE_MOVE);
			return 0;
		}
	case  WM_KEYDOWN:								//键被按下的处理
		{
			_bKeys[wParam] = true;					//记录对应的按键状态
			GameKeyAction(KEY_DOWN);				//执行游戏按键行为
			SubKeyAction(wParam);					//附加按键行为处理
			return 0;
		}
	case WM_KEYUP:									//释放按键处理
		{
			_bKeys[wParam] = false;
			GameKeyAction(KEY_UP);
			return 0;
		}
	case WM_NCLBUTTONDBLCLK:						//禁止双击窗口标题栏最大化窗口
		{
			if (HTCAPTION == wParam)	return 0;	
		}
	case WM_SYSCOMMAND:
		{
			if (wParam == SC_MAXIMIZE)
			{
				_bFullScreen = !_bFullScreen;					//设置全屏显示标志
				if (_bFullScreen)								//全屏幕显示
				{
					::GetWindowRect(_hWnd,&_rcOldRect);			//记住当前窗口的尺寸
					_style = ::GetWindowLong(_hWnd,GWL_STYLE);
					_ex_style = ::GetWindowLong(_hWnd,GWL_EXSTYLE);
					SaveMode();
					HWND hDesktop;	
					hDesktop = ::GetDesktopWindow();			//获取桌面窗口的句柄
					RECT rc;
					::GetWindowRect(hDesktop,&rc);				//获取桌面窗口的矩形
					ChangeMode(_wndWidth,_wndHeight);

					//设置为WS_DLGFRAME.WS_BORDER或WS_EX_CLIENTEDGE都可以去掉标题栏
					//设置扩展风格为WS_EX_WINDOWEDGE,去掉窗口边框
					::SetWindowLong(_hWnd,GWL_EXSTYLE,WS_EX_WINDOWEDGE);
					::SetWindowLong(_hWnd,GWL_STYLE,WS_BORDER);
					::SetWindowPos(_hWnd,HWND_TOP,-1,-1,rc.right,rc.bottom,SWP_SHOWWINDOW);
				}
			}
			else if (wParam == SC_CLOSE)
			{
				if (IDOK == ::MessageBox(NULL,L"你确定要退出吗?",_wndTitle,MB_OKCANCEL|MB_ICONQUESTION))
				{
					::DestroyWindow(_hWnd);
				}
			}
			else
			{
				//由于WM_SYSCOMMAND消息不是由程序控制的,
				//所以必须将该消息传给DefWindowProc,否则会造成其他消息无法处理
				return ::DefWindowProc(hWnd,WM_SYSCOMMAND,wParam,lParam);
			}
			return 0;
		}
	case WM_CLOSE:
		{
			::DestroyWindow(hWnd);
			return 0;
		}
	case WM_PAINT:					//窗口绘制
		{
			PAINTSTRUCT ps;
			HDC hdc = ::BeginPaint(hWnd,&ps);
			GamePaint(hdc);
			::EndPaint(hWnd,&ps);
			return 0;
		}
	case WM_DESTROY:				//程序销毁
		{
			::PostQuitMessage(0);
			return 0;
		}
	}

	return ::DefWindowProc(hWnd,msg,wParam,lParam);
}

void CJSWnd::Run()
{
	MSG msg;
	WndInit();							//初始化窗口
	::srand((unsigned)time(NULL));		//初始化随机数

	static int TickElapsed = 0;
	int nowTick;
	while (TRUE)
	{
		if (::PeekMessage(&msg,NULL,0,0,PM_REMOVE))
		{
			if (msg.message == WM_QUIT)
			{
				break;
			}
			::TranslateMessage(&msg);
			::DispatchMessage(&msg);
		}
		else
		{
			if (!_bIsAsleep)			//确保游戏没有进入睡眠状态
			{
				nowTick = ::GetTickCount();
				if (nowTick > TickElapsed)		//判断游戏循环的时间
				{
					TickElapsed = nowTick + _IntervalTime;
					GameLogic();				//处理游戏逻辑
					GamePaint(_hBufferDC);		//在内存中绘制内容
					HDC hDc = ::GetDC(_hWnd);	//获取游戏窗口句柄及绘图设备
					::BitBlt(hDc,0,0,_wndWidth,_wndHeight,_hBufferDC,0,0,SRCCOPY);		//将内存设备中绘制的内容绘制到屏幕上
					::ReleaseDC(_hWnd,hDc);		//释放设备
				}
			}
		}
	}

	m_pWnd->GameEnd();							//游戏结束处理
}

void CJSWnd::SaveMode()
{
	HDC dc = ::GetDC(0);
	__devmodeSaved.dmSize = sizeof(DEVMODE);
	__devmodeSaved.dmDriverExtra = 0;
	__devmodeSaved.dmPelsWidth = ::GetDeviceCaps(dc,HORZRES);
	__devmodeSaved.dmPelsHeight = ::GetDeviceCaps(dc,VERTRES);
	__devmodeSaved.dmBitsPerPel = ::GetDeviceCaps(dc,BITSPIXEL); 
	__devmodeSaved.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
	//判断windows版本是否为windows NT/2000
	if (::GetVersion() & 0x80000000 == 0)
	{
		__devmodeSaved.dmFields |= DM_DISPLAYFREQUENCY;
		__devmodeSaved.dmDisplayFrequency = GetDeviceCaps(dc,VREFRESH);
	}
	::ReleaseDC(0,dc);
}

void CJSWnd::ResetMode()
{
	if (__modeChanged)
	{
		::ChangeDisplaySettings(&__devmodeSaved,0);
		__modeChanged = false;
	}
}

bool CJSWnd::ChangeMode(int ChangeWidth, int ChangeHeight)
{
	DEVMODE devmode;
	devmode = __devmodeSaved;
	devmode.dmPelsWidth = ChangeWidth;
	devmode.dmPelsHeight = ChangeHeight;
	devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
	if (::ChangeDisplaySettings(&devmode,CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL)
	{
		__modeChanged = true;
		return true;
	}
	return false;
}

 

 

 

 

 

 

 

 

 

例子1.进行测试一个简单窗口程序 HELLO WORLD!

首先从上个窗口类派生一个自己的游戏窗口类

#pragma once
#include "JSWnd.h"

class CTestWnd :public CJSWnd
{
public:
	CTestWnd(HINSTANCE hInstance, LPCTSTR szWindowClass, LPCTSTR szTitle, 
		WORD Icon = NULL, WORD SmIcon = NULL, 
		int iWidth = G_WIN_WIDTH, int iHeight = G_WIN_HEIGHT);
	virtual ~CTestWnd();

public:
	virtual void GameInit(){};															//游戏初始化
	virtual void GameLogic(){};															//游戏逻辑处理
	virtual void GameEnd(){};															//游戏结束处理
	virtual void GamePaint(HDC hdc);													//根据GAME_STATE值显示游戏界面
	virtual void GameKeyAction(KM_ACTION ActionType=KEY_SYS_NONE){};							//处理按键行为
	virtual void GameMouseAction(int x, int y, KM_ACTION ActionType){};						//处理鼠标行为
};

 

#include "TestWnd.h"

CTestWnd::CTestWnd(HINSTANCE hInstance, LPCTSTR szWindowClass, LPCTSTR szTitle, 
						 WORD Icon /*= NULL*/, WORD SmIcon /*= NULL*/, 
						 int iWidth /*= WIN_WIDTH*/, int iHeight/* = WIN_HEIGHT*/):CJSWnd(hInstance,szWindowClass,szTitle,Icon,SmIcon,iWidth,iHeight)
{
}

CTestWnd::~CTestWnd()
{
}

void CTestWnd::GamePaint(HDC hdc)
{
	HGDIOBJ mbrush,oldbrush;
	HGDIOBJ mpen,oldpen;
	RECT mrect;
	int cell_width = _wndWidth/20;
	int cell_height = _wndHeight/20;
	for (int r=0;r<20;r++)
	{
		for (int c=0;c<20;c++)
		{
			mpen = ::CreatePen(PS_SOLID,0,RGB(240,240,240));
			oldpen = ::SelectObject(hdc,mpen);
			mbrush = ::CreateSolidBrush(RGB(rand()%255,rand()%255,rand()%255));
			oldbrush = ::SelectObject(hdc,mbrush);
			mrect.left = c*cell_width;
			mrect.right = mrect.left + cell_width;
			mrect.top = r*cell_height;
			mrect.bottom = mrect.top + cell_height;
			::FillRect(hdc,&mrect,(HBRUSH)mbrush);
			::Rectangle(hdc,mrect.left,mrect.top,mrect.right,mrect.bottom);
			::SelectObject(hdc,oldbrush);
			::DeleteObject(mbrush);
			::SelectObject(hdc,oldpen);
			::DeleteObject(mpen);
		}
	}
}

 


 

主程序

 

#include "TestWnd.h"

int WINAPI WinMain( __in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in_opt LPSTR lpCmdLine, __in int nShowCmd )
{
	CJSWnd *ptest = new CTestWnd(hInstance,G_WIN_CLASS,L"HELLO WORLD",NULL,NULL,800,600);
	ptest->SetFrame(20);
	ptest->Run();
	delete ptest;
	return 0;
}

 

 

运行结果:

 

 

例子2.根据鼠标移动,窗口显示鼠标的坐标

首先从上个窗口类派生一个自己的游戏窗口类

#pragma once
#include "JSWnd.h"

class CTestWnd :public CJSWnd
{
public:
	CTestWnd(HINSTANCE hInstance, LPCTSTR szWindowClass, LPCTSTR szTitle, 
		WORD Icon = NULL, WORD SmIcon = NULL, 
		int iWidth = G_WIN_WIDTH, int iHeight = G_WIN_HEIGHT);
	virtual ~CTestWnd();

public:
	virtual void GameInit(){};															//游戏初始化
	virtual void GameLogic(){};															//游戏逻辑处理
	virtual void GameEnd(){};															//游戏结束处理
	virtual void GamePaint(HDC hdc){};													//根据GAME_STATE值显示游戏界面
	virtual void GameKeyAction(KM_ACTION ActionType=KEY_SYS_NONE){};							//处理按键行为
	virtual void GameMouseAction(int x, int y, KM_ACTION ActionType);						//处理鼠标行为
};

 

#include "TestWnd.h"
#include <tchar.h>

CTestWnd::CTestWnd(HINSTANCE hInstance, LPCTSTR szWindowClass, LPCTSTR szTitle, 
						 WORD Icon /*= NULL*/, WORD SmIcon /*= NULL*/, 
						 int iWidth /*= G_WIN_WIDTH*/, int iHeight/* = G_WIN_HEIGHT*/):CJSWnd(hInstance,szWindowClass,szTitle,Icon,SmIcon,iWidth,iHeight)
{
}

CTestWnd::~CTestWnd()
{
}
void CTestWnd::GameMouseAction(int x, int y, KM_ACTION ActionType)
{
	if (ActionType == MOUSE_MOVE)
	{
		TCHAR str[20] = _T("");
		TextOut(_hBufferDC,10,10,_T("鼠标坐标是:"),_tcslen(_T("鼠标坐标是:")));
		_stprintf_s(str,sizeof(_T("鼠标坐标x是:%d")),_T("鼠标坐标x是:%d"),x);
		TextOut(_hBufferDC,20,40,str,_tcslen(str));
		_stprintf_s(str,sizeof(_T("鼠标坐标Y是:%d")),_T("鼠标坐标x是:%d"),y);
		TextOut(_hBufferDC,20,60,str,_tcslen(str));
	}
}

运行结果


 

 

例子3.窗口显示一副图片

首先从上个窗口类派生一个自己的游戏窗口类

#pragma once
#include "JSWnd.h"

class CTestWnd :public CJSWnd
{
public:
	CTestWnd(HINSTANCE hInstance, LPCTSTR szWindowClass, LPCTSTR szTitle, 
		WORD Icon = NULL, WORD SmIcon = NULL, 
		int iWidth = G_WIN_WIDTH, int iHeight = G_WIN_HEIGHT);
	virtual ~CTestWnd();

	HBITMAP hBKBmp;

public:
	virtual void GameInit();															//游戏初始化
	virtual void GameLogic(){};															//游戏逻辑处理
	virtual void GameEnd(){};															//游戏结束处理
	virtual void GamePaint(HDC hdc);													//根据GAME_STATE值显示游戏界面
	virtual void GameKeyAction(KM_ACTION ActionType=KEY_SYS_NONE){};							//处理按键行为
	virtual void GameMouseAction(int x, int y, KM_ACTION ActionType){};						//处理鼠标行为
};

 

#include "TestWnd.h"
#include <tchar.h>

CTestWnd::CTestWnd(HINSTANCE hInstance, LPCTSTR szWindowClass, LPCTSTR szTitle, 
						 WORD Icon /*= NULL*/, WORD SmIcon /*= NULL*/, 
						 int iWidth /*= G_WIN_WIDTH*/, int iHeight/* = G_WIN_HEIGHT*/):CJSWnd(hInstance,szWindowClass,szTitle,Icon,SmIcon,iWidth,iHeight)
{
}

CTestWnd::~CTestWnd()
{
     if(hBKBmp)
     {
         //删除位图对象
         ::DeleteObject(hBKBmp);
     }
}

void CTestWnd::GamePaint(HDC hdc)
{
     //创建缓冲的内存设备
     HDC memDC = ::CreateCompatibleDC(hdc);
     //将图选进内存设备HBITMAP 
     oldFrameBmp = (HBITMAP)::SelectObject(memDC,hBKBmp);
     //设置指定设备环境中的位图拉伸模式
     //COLORONCOLOR:删除像素。该模式删除所有消除的像素行,不保留其信息。
     ::SetStretchBltMode(hdc,COLORONCOLOR);
     ::StretchBlt(hdc,0,0,800,600,memDC,0,0,600,450,SRCCOPY);
     
     //还原内存设备环境中的原来的位图对象
     ::SelectObject(memDC,oldFrameBmp);
     //删除内存设备
     ::DeleteDC(memDC);
     //删除位图对象
     ::DeleteObject(oldFrameBmp);
     oldFrameBmp = NULL;
}

void CTestWnd::GameInit()
{
     hBKBmp = (HBITMAP)::LoadImage(_hInstance,_T("bg.bmp"),IMAGE_BITMAP,600,450,LR_LOADFROMFILE);
}




运行结果:

 

 

 

 

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页