⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mainwin.cpp

📁 用MFC写的RPG游戏
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// Main Window
//
//		Copyright (c) 2000-2001 Chihiro.SAKAMOTO (HyperWorks)
//
#include "StdAfx.h"
#include "Sample.h"
#include "Window.h"
#include "MainWin.h"
#include "AboutDlg.h"
#include "Script.h"
#include "Battle.h"
#include "LoadSave.h"
#include "Misc.h"
#include "dc.h"
#include "resource.h"

//
// 构造函数
//
//	变量的初始化
//	当window由OnCreate初始化时,不会带出任何东西
//
CMainWin::CMainWin():
	TextRect(MSG_X, MSG_Y, MSG_X + MSG_W, MSG_Y + MSG_H),
	SaveRect(SAVE_X, SAVE_Y, SAVE_X + SAVE_W, SAVE_Y + SAVE_H),
	WaitMarkRect(MsgX(WAITMARK_X), MsgY(WAITMARK_Y),
		MsgX(WAITMARK_X) + MessageFont, MsgY(WAITMARK_Y) + MessageFont),
	InvalidRect(0, 0, 0, 0)
{
	CurX = CurY = 0;
	BgColor = BlackPixel;
	TextDisplay = FALSE;
	WaitMarkShowing = FALSE;

	BackShow = FALSE;
	OverlapShow = FALSE;
	TextShow = FALSE;
	MenuShow = FALSE;
	SaveShow = FALSE;

	Action = new CAction(this);	// 虚拟动作(dummy action)
	hFont = 0;

	// 开始播放CD
	// 若没有CD则在Open时设成Off
	MusicMode = MusicCD;
	music = &cdaudio;
	MusicNo = 0;

	TIMECAPS	timeCaps;
	timeGetDevCaps(&timeCaps, sizeof(timeCaps));
	TimePeriod = max(timeCaps.wPeriodMin, 1U);
	timeBeginPeriod(TimePeriod);

	ViewEffect = 0;
}

//
// 析构函数
//
CMainWin::~CMainWin()
{
	timeEndPeriod(TimePeriod);

	if (hFont) {
		DeleteObject(hFont);
		hFont = 0;
	}
	DeleteAllAction();
}

//
// window产生的前置处理
//
//	指定样式和大小
//
BOOL CMainWin::PreCreateWindow(CREATESTRUCT &cs)
{
	cs.dwExStyle = WS_EX_CLIENTEDGE;
	cs.style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;

	CRect	rect(0, 0, WindowWidth, WindowHeight);
	::AdjustWindowRectEx(&rect, cs.style, TRUE, cs.dwExStyle);

	int width = rect.Width();
	int height = rect.Height();

	CRect rcArea;
	SystemParametersInfo(SPI_GETWORKAREA, NULL, &rcArea, NULL);

	int	x = rcArea.left + (rcArea.Width() - width) / 2;
	int	y = rcArea.top + (rcArea.Height() - height) / 2;

	cs.x = x;
	cs.y = y;
	cs.cx = width;
	cs.cy = height;
	cs.lpszClass = "MainWindow";

	if (!Application->RegisterWndClass(cs.lpszClass,
		CS_VREDRAW | CS_HREDRAW | CS_OWNDC, LoadCursor(NULL, IDC_ARROW),
		(HBRUSH)::GetStockObject(BLACK_BRUSH), Application->LoadIcon(IDC_APPICON)))
		return FALSE;
	return TRUE;
}

//
// 事件处理
//
LRESULT CMainWin::WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg) {
	  case WM_FIRSTACTION:		// 最初传送的事件
		OnFirstAction();
		break;

	  case WM_CLOSE:			// 关闭窗口
		OnClose();
		break;

	  case WM_ERASEBKGND:		// 删除背景
		return FALSE;			// 无动作

	  case WM_LBUTTONDOWN:		// 按下鼠标左键
		Action->LButtonDown(wParam, CPoint(lParam));
		break;

	  case WM_LBUTTONUP:		// 放开鼠标左键
		Action->LButtonUp(wParam, CPoint(lParam));
		break;

	  case WM_RBUTTONDOWN:		// 按下鼠标右键
		Action->RButtonDown(wParam, CPoint(lParam));
		break;

	  case WM_RBUTTONUP:		// 放开鼠标右键
		Action->RButtonUp(wParam, CPoint(lParam));
		break;

	  case WM_MOUSEMOVE:		// 鼠标指标移动
		Action->MouseMove(wParam, CPoint(lParam));
		break;

	  case WM_KEYDOWN:			// 按下键盘
		Action->KeyDown(wParam);
		break;

	  case WM_DESTROY:			// 取消窗口
		OnDestroy();
		break;

	  case WM_TIMER:			// 计时器到期
		OnTimer(wParam);
		break;

	  case MM_MCINOTIFY:		// MCI的事件
		OnMciNotify(wParam, LOWORD(lParam));
		break;

	  default:
		return CWindow::WindowProc(uMsg, wParam, lParam);
	}
	return 0L;
}

//
// IDLE的处理
//
BOOL CMainWin::OnIdle(long count)
{
	if (ViewEffect) {							// 是否在特效中?
		if (ViewEffect->Step(timeGetTime()))	// 特效执行
			return TRUE;						// 特效继续
		StopWipe();								// 特效结束
		Action->WipeDone();						// 结束通报给动作
	}
	return Action->IdleAction();
}

//
// WM_CREATE的处理
//
BOOL CMainWin::OnCreate(CREATESTRUCT *cs)
{
	LoadAccelTable(IDC_APPACCEL);

	CClientDC	dc(this);

	// 确认图像内存空间
	if (!ViewImage.Create(dc, WindowWidth, WindowHeight)
	 || !MixedImage.Create(dc, WindowWidth, WindowHeight)
	 || !BackLayer.Create(WindowWidth, WindowHeight)
	 || !OverlapLayer.Create(WindowWidth, WindowHeight)) {
		MessageBox("没有足够的内存空间。/n"
			"请先结束其他使用中的应用程序后,再重新启动。");
		return FALSE;
	}

	// 清除显示用图像
	ViewImage.Clear();

	// 先行产生字型
	if ((hFont = CreateFont(-MessageFont, 0, 0, 0, MessageStyle, FALSE, FALSE, FALSE,
		GB2312_CHARSET, OUT_DEFAULT_PRECIS, CLIP_CHARACTER_PRECIS,
		DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "冼极")) == 0) {
		MessageBox("没有新细明体。");
		return FALSE;
	}

	// 发送触发的第一个事件
	while (!PostMessage(WM_FIRSTACTION)) {
		// 若伫列已满,则PostMessage会发生error,故反覆传送
#ifdef	_DEBUG
		TRACE("PostMessage Error code = %d\n", GetLastError());
#endif
		::Sleep(110);	// 重送事件的动作再稍等一下
	}

	Param.Clear();		// 清除参数内的东西

	return TRUE;
}

//
// 游戏的“第一个”动作
//
void CMainWin::OnFirstAction()
{
	// 如果需要,CD-DA会开启
	if (music) {
		if (!music->Open(this) && MusicMode == MusicCD) {
			MusicMode = MusicOff;
			music = 0;
		}
	}
	wave.Open(this);

	StartMainMenu();
}

//
// WM_CLOSE的处理
//
void CMainWin::OnClose()
{
		if (MessageBox("确定要结束程序吗?", ApplicationTitle,
		MB_ICONQUESTION|MB_OKCANCEL) == IDOK) {
		::DestroyWindow(hWnd);
	}
}

//
// WM_PAINT的处理(重新绘制)
//
void CMainWin::OnPaint()
{
	CPaintDC	dc(this);
	ViewImage.Draw(dc, dc.ps.rcPaint);
}

//
// WM_DESTROY的处理(重新安排)
//
void CMainWin::OnDestroy()
{
	// 如果正在播放音乐就停止,
	// 若是用MCI,应用程序虽然结束但播放仍然会继续,
	// 所以要是窗口被关掉的时候就强制停止。

	if (music) {
		music->Stop();
		music->Close();
		music = 0;
	}
	CWindow::OnDestroy();
}

//
// WM_TIMER的处理
//
void CMainWin::OnTimer(int id)
{
	if (Action->TimedOut(id))
		KillTimer(id);
}

//
// WM_COMMAND的处理(菜单处理)
//
void CMainWin::OnCommand(UINT notifyCode, UINT id, HWND ctrl)
{
	switch (id) {
	  case ID_APP_EXIT:			// 结束
		SendMessage(WM_CLOSE);
		break;

	  case ID_APP_ABOUT:			// 版本信息
		CAboutDlg().DoModal(IDD_ABOUT, hWnd);
		break;

	  case ID_MUSIC_CD:				// BGM/ON
		ChangeMusicMode(MusicCD);
		break;

	  case ID_MUSIC_OFF:			// BGM/OFF
		ChangeMusicMode(MusicOff);
		break;

	  case ID_LOADGAME:				// 载入
		if (IsLoadOK())
			SetGameLoadAction();
		break;

	  case ID_SAVEGAME:				// 储存
		if (IsSaveOK())
			SetGameSaveAction();
		break;

	  case ID_STOPSCRIPT:			// 脚本中断
		if (IsSaveOK()
		 && MessageBox("要中断吗?", ApplicationTitle,
		 	MB_ICONQUESTION|MB_OKCANCEL) == IDOK)
			Action->Abort();
		break;

	  default:
		break;
	}
}

//
// 菜单项目的初始化
//
void CMainWin::OnInitSubMenu(HMENU hMenu, UINT id)
{
	switch (id) {
	  case ID_MUSIC_CD:				// BGM/ON
		// 检查菜单项目
		CheckMenuItem(hMenu, id, MusicMode == MusicCD? MF_CHECKED: MF_UNCHECKED);
		break;

	  case ID_MUSIC_OFF:			// BGM/OFF
		// 检查菜单项目
		CheckMenuItem(hMenu, id, MusicMode == MusicOff? MF_CHECKED: MF_UNCHECKED);
		break;

	  case ID_LOADGAME:				// 载入
		// 只有在可以载入时菜单上的项目才有作用
		EnableMenuItem(hMenu, id, IsLoadOK()? MF_ENABLED: (MF_DISABLED | MF_GRAYED));
		break;

	  case ID_SAVEGAME:				// 储存
		// 只有在可以储存时菜单上的项目才有作用
		EnableMenuItem(hMenu, id, IsSaveOK()? MF_ENABLED: (MF_DISABLED | MF_GRAYED));
		break;

	  case ID_STOPSCRIPT:			// 脚本中断
		// 只有在可以中断时菜单上的项目才有作用
		EnableMenuItem(hMenu, id, IsSaveOK()? MF_ENABLED: (MF_DISABLED | MF_GRAYED));
		break;
	}
}

//
// MCI的事件
//
// 透过play指定Call Back,所以会在播放结束时被调用
//
void CMainWin::OnMciNotify(unsigned flag, unsigned id)
{
	if (flag == MCI_NOTIFY_SUCCESSFUL) {
		if (music && music->GetId() == id) {
			Action->MusicDone(MusicNo);
		}
		else if (wave.GetId() == id) {
			wave.Stop();
			Action->WaveDone();
		}
	}
}

//
// 音乐播放换成新的
//
void CMainWin::ChangeMusicMode(int mode)
{
	if (MusicMode != mode) {		// 若变更模式的话
		MusicMode = mode;
		if (music) {				// 播放中就停止
			music->Stop();
			music->Close();
			music = 0;
		}
		switch (MusicMode) {
		  case MusicCD:
			music = &cdaudio;
			if (!music->Open(this)) {
				MusicMode = MusicOff;
				music = 0;
			}
			break;
		}
		if (music && MusicNo > 0)
			music->Play(MusicNo);	// 播放现在所指定的曲子
	}
}

//
// 删除动作
//
void CMainWin::DeleteAllAction()
{
	while (Action) {
		CAction *action = Action->GetOldAction();
		delete Action;
		Action = action;
	}
}

//
// Script结束
//
void CMainWin::ScriptDone()
{
	StopWipe();
	StopMusic();	// 停止音乐播放

	CAction *action = Action->GetOldAction();
	delete Action;
	Action = action;
	if (Action == 0)		// 没有被储存的动作
		StartMainMenu();	// 回到主菜单
}

//
// 切换到载入画面操作
//
void CMainWin::SetGameLoadAction()
{
	ShowLoadSaveMenu(FALSE);
	Action->Pause();
	Action = new CGameLoadAction(this, Action);
	PostMessage(WM_KICKIDLE);	// 为了慎重起见发送空事件
}

//
// 切换的储存画面操作
//
void CMainWin::SetGameSaveAction()
{
	ShowLoadSaveMenu(TRUE);
	Action->Pause();
	Action = new CGameSaveAction(this, Action);
	PostMessage(WM_KICKIDLE);	// 为了慎重起见发送空事件
}

//
// 执行Script
//
bool CMainWin::StartScript(const char *name, int mode)
{
	CScriptAction *action = new CScriptAction(this, Action, mode);
	if (!action->Load(name)) {			// 读入脚本
		delete action;
		return false;
	}

	Action = action;
	PostMessage(WM_KICKIDLE);	// 为了慎重起见发送空事件
	return true;
}

//
// 主菜单
//
// 执行主菜单Script
//
void CMainWin::StartMainMenu()
{
	DeleteAllAction();
	if (!StartScript("main", CScriptAction::MODE_SYSTEM))
		::DestroyWindow(hWnd);
}

//
// 在事件范围中写内容
//
void CMainWin::WriteMessage(const char *msg)
{
	FormatMessage(msg);

	WaitMarkShowing = TRUE;

	ShowMessageWindow();
}

//
// 消除“等待按键”符号
//
void CMainWin::HideWaitMark()
{
	if (WaitMarkShowing) {
		WaitMarkShowing = FALSE;
		if (TextShow) {
			Mixing(WaitMarkRect, TextWaitMark);
			CopyAndRepaint(WaitMarkRect);
		}
	}
}

//
// 描绘菜单
//
void CMainWin::OpenMenu()
{
	int		maxlen = MENU_MIN_WIDTH;

	{
		CMemoryDC	memdc(0);
		HFONT	oldFont = memdc.SelectObject(hFont);

		for (int i=0; i<MenuCount; i++) {
			CSize	size;
			memdc.GetTextExtentPoint32(MenuBuffer[i].text, MenuBuffer[i].length, &size);
			if (maxlen < size.cx)
				maxlen = size.cx;
		}
		memdc.SelectObject(oldFont);
	}

	MenuRect.top = MENU_Y - ((MENU_FRAME_HEIGHT * 2) + MenuCount * MENU_ITEM_HEIGHT
		- MENU_ITEM_SPACE);
	MenuRect.left = MENU_X;
	MenuRect.bottom = MENU_Y;
	MenuRect.right = MENU_X + (MENU_FRAME_WIDTH * 2) + maxlen;

	MenuShow = TRUE;
	Mixing(MenuRect);
	CopyAndRepaint(MenuRect);
}

//
// 选取/非选取显示菜单项目
//
void CMainWin::SelectMenu(int index, bool select)
{
	if (index >= 0) {
		MenuBuffer[index].color = select? RedPixel: WhitePixel;
		CRect	r;
		r.left = MenuRect.left + MENU_FRAME_WIDTH;
		r.top = MenuRect.top + MENU_FRAME_HEIGHT + MENU_ITEM_HEIGHT * index;
		r.right = r.left + MenuRect.Width() - MENU_FRAME_WIDTH * 2;
		r.bottom = r.top + MessageFont;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -