|
|
发表于 2006-5-10 00:49:00
|
显示全部楼层
Re:昨天的问题刚解决,又有新的问题了。还望大哥们赐教。
我补充一下。除了用楼上的那种定义一个文件头,用来存储该地图信息的描述的方法之外,还有一种最简单的方法,那就是二进制存储方式。一般C/C++程序员绝大多数都是用这种办法来存储应用程序中的结构等复杂类型!
下面那段代码是引用我之前编写的BFRussia。你可参考参考SDK是怎么做这个的,用VB实现可能会有点难度。不过可用尝试用RtlCopyMemory等内存操作函数来处理。。。
////////////////////////////////////////////////////////////////////////////////////////////////
// 加载存档文件
void LoadGameFile()
{
HANDLE hFile;
DWORD dwBytesRead;
DWORD dwFileSize;
OPENFILENAME ofn;
//OVERLAPPED *Overlap;
// 构造文件名
TCHAR szInitialDir[MAX_PATH] = TEXT("\0");
TCHAR szFileName[MAX_PATH] = TEXT("\0");
TCHAR szFilter[MAX_PATH] = TEXT("\0");
// 内存指针
PBYTE pFileBuffer=NULL, p=NULL;
wsprintf(szInitialDir, TEXT("%ssave"), g_szAppPath);
GetFirstFileName(szFileName, szInitialDir, TEXT("*.bfrs"));
wsprintf(szFilter, TEXT("BFRussia Save File(*.bfrs)\0*.bfrs\0\0"));
// 填充打开文件结构
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = g_hwndMain;
ofn.hInstance = g_hInstance;
ofn.lpstrFilter = szFilter;
ofn.lpstrCustomFilter = NULL;
ofn.nMaxCustFilter = 0;
ofn.nFilterIndex = 0;
ofn.lpstrFile = szFileName;
ofn.nMaxFile = sizeof(szFileName);
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = szInitialDir;
ofn.lpstrTitle = TEXT("打开游戏存档");
ofn.nMaxFileTitle = strlen(ofn.lpstrTitle) + 1;
ofn.nFileOffset = 0;
ofn.nFileExtension = 0;
ofn.lpstrDefExt = NULL;
ofn.lCustData = NULL;
ofn.lpfnHook = NULL;
ofn.lpTemplateName = NULL;
ofn.Flags = OFN_EXPLORER | OFN_LONGNAMES | OFN_CREATEPROMPT |
OFN_NODEREFERENCELINKS | OFN_ALLOWMULTISELECT;
// 如果得到一个存档的文件名,就开始读取数据
if ( GetOpenFileName(&ofn) )
{
hFile = CreateFile( szFileName,
GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
0
);
if ( hFile == INVALID_HANDLE_VALUE )
return;
dwFileSize = GetFileSize(hFile, NULL);
// 检查存档文件
if ( dwFileSize == 0xFFFFFFFF || dwFileSize != GetBufferSize() )
{
CloseHandle(hFile);
MessageBox(g_hwndMain, TEXT("无效的存档文件!"), g_szAppTitle, MB_ICONWARNING );
return;
}
pFileBuffer = (PBYTE) GlobalAlloc(GPTR, dwFileSize);
// 读到数据到内存中
if ( ReadFile(hFile, pFileBuffer, dwFileSize, &dwBytesRead, NULL) )
{
COLORREF clrPrevText = GetTextColor(g_pwdRussia->hdc);
LPTSTR pText = TEXT("成功加载!");
BYTE bColor = 0;
BOOL bEnable;
DWORD dwTimer = 0;
DWORD dwInterval;
UINT uMenuItemDisabled = MF_DISABLED | MF_GRAYED;
UINT gs;
int i;
// 恢复Russia的前景颜色和字体
if ( g_ptdGameOver->hfontBak )
{
SetTextColor(g_pwdRussia->hdc, g_ptdGameOver->clrBak);
SelectObject(g_pwdRussia->hdc, g_ptdGameOver->hfontBak);
g_ptdGameOver->hfontBak = NULL;
}
p = pFileBuffer;
// 暂停当前状态
if ( g_fGameState > GS_PAUSEING )
g_fGameState = GS_PAUSEING;
// GAME_STATE
memcpy((void*)&gs, (void*)p, sizeof(UINT) );
p += sizeof(UINT);
// GAME_LOOP_INTERVAL
memcpy(&GAME_LOOP_INTERVAL, (void*)p, sizeof(UINT) );
p += sizeof(UINT);
// MAX_SHAPE
memcpy((void*)&MAX_SHAPE, (void*)p, sizeof(UINT) );
p += sizeof(UINT);
// g_aGameArea
memcpy((void*)&g_aGameArea, (void*)p, sizeof(g_aGameArea) );
p += sizeof(g_aGameArea);
// g_Player
memcpy((void*)&g_Player, (void*)p, sizeof(PLAYER) );
p += sizeof(PLAYER);
// g_KeyState
memcpy((void*)&g_KeyState, (void*)p, sizeof(VKSTATE) );
p += sizeof(VKSTATE);
// g_uIDTimerGameAreaAct
memcpy((void*)&g_uIDTimerGameAreaAct, (void*)p, sizeof(UINT) );
p += sizeof(UINT);
// Start
memcpy((void*)&bEnable, (void*)p, sizeof(BOOL) );
p += sizeof(BOOL);
EnableWindow(GetDlgItem(g_hwndMain, IDC_BTNSTART), bEnable);
EnableMenuItem(g_hmenuMain, IDM_FILE_NEW, MF_BYCOMMAND | (bEnable?MF_ENABLED:uMenuItemDisabled) );
// Pause
memcpy((void*)&bEnable, (void*)p, sizeof(bEnable) );
p += sizeof(BOOL);
if ( gs == GS_PAUSEING )
SetPauseState(bEnable, TEXT("暂 停"), TEXT("暂停(& )"));
else
SetPauseState(bEnable, TEXT("返 回"), TEXT("返回游戏(&R)"));
// Stop
memcpy((void*)&bEnable, (void*)p, sizeof(BOOL) );
p += sizeof(BOOL);
EnableWindow(GetDlgItem(g_hwndMain, IDC_BTNSTOP), bEnable);
EnableMenuItem(g_hmenuMain, IDM_FILE_STOP, MF_BYCOMMAND | (bEnable?MF_ENABLED:uMenuItemDisabled) );
// Close
memcpy((void*)&bEnable, (void*)p, sizeof(BOOL) );
p += sizeof(BOOL);
EnableWindow(GetDlgItem(g_hwndMain, IDC_BTNCLOSE), bEnable);
EnableMenuItem(g_hmenuMain, IDM_FILE_EXIT, MF_BYCOMMAND | (bEnable?MF_ENABLED:uMenuItemDisabled) );
// Speed
memcpy((void*)&g_dwSpeed, (void*)p, sizeof(DWORD) );
p += sizeof(DWORD);
// Level
memcpy((void*)&g_dwLevel, (void*)p, sizeof(DWORD) );
p += sizeof(DWORD);
// Player Name
memcpy((void*)&g_aTopList[10], (void*)p, sizeof(TOP_LIST) );
p += sizeof(TOP_LIST);
// 游戏者名称
if ( !strlen(g_aTopList[10].szName) )
strcpy(g_aTopList[10].szName, TEXT("<无名>"));
g_aTopList[10].bFromSavedFile = TRUE;
GetLocalTime(&g_aTopList[10].stRuntime);
// 修改主程式窗口标题
{
TCHAR szTitle[MAX_PATH] = TEXT("\0");
wsprintf(szTitle, TEXT("%s - %s"), g_szAppTitle, g_aTopList[10].szName);
SetWindowText( g_hwndMain, szTitle);
}
// 播放打开成功消息
dwInterval = GetTickCount() + 1020;
// 成功
while ( dwTimer < dwInterval )
{
bColor = dwInterval - dwTimer;
SetTextColor( g_pwdRussia->hdc, RGB(0xFF, bColor, bColor) );
TextOut(g_pwdRussia->hdc, 0, 0, pText, strlen(pText) );
Flip();
dwTimer = GetTickCount();
}
SetTextColor( g_pwdRussia->hdc, clrPrevText );
DrawGameArea();
DrawPreview();
DrawToolsArea();
SetGameProperties( SGP_ALL );
SetDlgItemInt( g_hwndMain, IDC_SCORE, g_pPlayer->dwScore, FALSE );
EnableWindow( GetDlgItem(g_hwndMain, IDC_SPINLEVEL), FALSE );
EnableWindow( GetDlgItem(g_hwndMain, IDC_SPINSPEED), FALSE );
// 刷新数据
if ( gs != GS_PAUSEING )
g_fGameState = gs;
else
{
ResumeGame();
}
}
GlobalFree(pFileBuffer);
CloseHandle(hFile);
}
} |
|