📄 mainwin.cpp
字号:
//
// 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 + -