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);
}
运行结果:
windows游戏编程封装窗口类的更多相关文章
- 《逐梦旅程 WINDOWS游戏编程之从零开始》笔记5——Direct3D中的顶点缓存和索引缓存
第12章 Direct3D绘制基础 1. 顶点缓存 计算机所描绘的3D图形是通过多边形网格来构成的,网网格勾勒出轮廓,然后在网格轮廓的表面上贴上相应的图片,这样就构成了一个3D模型.三角形网格是构建物 ...
- windows游戏编程 创建WIN32一个HelloWOrld程序
本系列文章由jadeshu编写,转载请注明出处.http://blog.csdn.net/jadeshu/article/details/22449085 作者:jadeshu 邮箱: jades ...
- Windows游戏编程之从零开始d
Windows游戏编程之从零开始d I'm back~~恩,几个月不见,大家还好吗? 这段时间真的好多童鞋在博客里留言说或者发邮件说浅墨你回来继续更新博客吧. woxiangnifrr童鞋说每天都在来 ...
- 《逐梦旅程 WINDOWS游戏编程之从零开始》笔记1——创建窗口&GDI
第1章 创建窗口 步骤: 窗口类的设计 窗口类的注册 窗口的正式创建 窗口的显示与更新 消息循环体系 窗口过程函数处理消息 1. 设计:使用WNDCLASSEX结构体,这里注意的是C++中的结构体中的 ...
- 《逐梦旅程 WINDOWS游戏编程之从零开始》笔记4——Direct3D编程基础
第11章 Direct3D编程基础 2D游戏是贴图的艺术,3D游戏是渲染的艺术.这句话在我学过了之前的GDI编程之后,前一句算是有所体会,现在是来理解后一句的时候了. 安装DirectX SDK配置啥 ...
- 《逐梦旅程 WINDOWS游戏编程之从零开始》笔记6——四大变换&光照与材质
第13章 四大变换 在Direct3D中,如果为进行任何空间坐标变换而直接绘图的话,图形将始终处于应用程序窗口的中心位置,默认这个位置就成为世界坐标系的原点(0,0,0).而且我们也不能改变观察图形的 ...
- 《逐梦旅程 WINDOWS游戏编程之从零开始》笔记2——透明贴图,动画技术
第5章 透明贴图 像这样直接贴图会产生这种情况,所以我们需要透明贴图. 透明遮罩法:主要利用BitBlt函数中Raser(光栅)值的运算,需要准备素材图和遮罩图: 这个方法的原理解释见书131页. 示 ...
- 《逐梦旅程 WINDOWS游戏编程之从零开始》笔记3——输入消息处理,物理建模与粒子系统初步
第7章 Windows游戏输入消息处理 1. 键盘消息处理 之前提到的窗口过程函数有两参数与消息输出有关——wParam和llParam LRESULT CALLBACK WindowProc( _I ...
- windows游戏编程 绘图基础
本系列文章由jadeshu编写,转载请注明出处.http://blog.csdn.net/jadeshu/article/details/22451353 作者:jadeshu 邮箱: jades ...
随机推荐
- 怎样理解script标签的defer属性和async属性
如果script标签是引用的外部js文件, 那就会有一个下载js文件这一过程, 为了不因为这个下载过程而阻塞页面解析与渲染, 我们需要一种机制来解决这一问题, 方法之一就是使用 defer和async ...
- (十八)SpringBoot之发送QQ邮件
一.引入maven依赖 <dependencies> <dependency> <groupId>org.springframework.boot</grou ...
- java计算接口调用时间
方法一: LocalDateTime beginTime = LocalDateTime.now(); Long opetime = Duration.between(between,LocalDat ...
- iOS开发 iOS10推送必看(基础篇)-转
iOS10更新之后,推送也是做了一些小小的修改,下面我就给大家仔细说说.希望看完我的这篇文章,对大家有所帮助. 一.简单入门篇---看完就可以简单适配完了 相对简单的推送证书以及环境的问题,我就不在这 ...
- C#面向对象 什么是面向对象
1.面向对象(Object Oriented,OO) 是当前计算机界关心的重点,它是90年代软件开发方法的主流.面向对象的概念和应用已超越了程序设计和软件开发,扩展到很宽的范围.如数据库系统.交互式界 ...
- Image Processing and Analysis_8_Edge Detection:Local Scale Control for Edge Detection and Blur Estimation——1998
此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...
- 用arduino的uno开发板为nano板子烧写bootloader
这篇文章,是为了记录下某宝上淘到的一个没有bootloader的nano开发板的历程(比较坑),自己搜索资料而记录的. 如果没有bootloader,板子就不能接收上传的程序,什么也干不了. 烧写bo ...
- python之闲聊数据类型及常用操作符
Day 1-afternoon 所谓闲聊,也称gossip.下面开始... 整型 python3 的整型与长整型进行了无缝结合,长度不受限制. 浮点型 包括科学计数法 E.(用法同C) 布尔类型 即特 ...
- lvs+keepalived+application部署(只使用两台机器)
目前大家用LVS+Keepalived + APP 架构都是 2台LVS +Keepalived 然后后端跟着 应用设备 然而针对小客户来说, 2台LVS平常没什么压力 还有一台备着(虽然可以跑双主 ...
- java实现网络请求超时自动熔断
原文:https://www.jianshu.com/p/326465500d1c?utm_campaign 使用场景 之前在实现熔断降级组件时,需要实现一个接口的超时中断,意思是,业务在使用熔断降级 ...