背景相关介绍
1.LOL,英雄联盟,由美国Riot Games公司开发,目前由国内由腾讯代{过}{滤}理,
2.LOL地图位于安装目录下的Game文件夹内,默认以MapX.zip命名方式,此处只对Map1.zip进行操作,也就是召唤师峡谷地图
3.开发工具VS2013
需要准备的材料
1.LOL地图包,网上可以随意扒下来,此处注意,S4或之前地图已不可用
2.几张图片,用于预览。
核心实现分析
将已有的地图包拷贝到LOLGame目录下并命名为Map1.zip
界面说明
1.为了美观,选择两个GroupBox,
2.使用四个按钮,标题分别为,选择路径、修改地图、一键还原、分别为其为其定义ID
3.使用Combo Box用于选择地图,ComboBox需要去掉sort属性,在加上sort属性后,ComboBox会为其内项目自动排序,可能会
打乱选择与预览图片的对应关系。
4.使用Picutre Control控件显示与预览图5.gif图的加载可自行百度"MFC加载gif图",此处有用到开源代码PictureEx
代码说明
1.获取正确的LOL安装目录。
为按钮创建相应的消息函数,并添加如下代码。函数及结构体解释可参考百度或MSDN。
首先,打开一个路径选择对话框,在获取到用户的选择后,通过简单的验证目录名是否为“英雄联盟”来判断用户的选择是否正确。此处的判断并不严谨,为保证正确性及可靠性,应加入更加严谨的判断。如果正确,那么将这个路径存取到一个文件中。此处的存取方式可以选择,这里简单的存为一个二进制文件。不采用文本存取的原因是目录中包含中文字符,存为文本会导致存取错误。
[C++] 纯文本查看 复制代码 void CLOLMapChangeDlg::OnBnClickedBtnChosePath()
{
BROWSEINFO Bi;
memset(&Bi,0,sizeof(BROWSEINFO));
WCHAR wcDisplayName[MAX_PATH];
Bi.hwndOwner = this->m_hWnd;
Bi.pidlRoot = NULL;
Bi.pszDisplayName = wcDisplayName;
Bi.lpszTitle = TEXT("LOL地图修改器,请选择LOL安装目录");
Bi.ulFlags = BIF_STATUSTEXT;
Bi.lpfn = NULL;
Bi.lParam = 0;
Bi.iImage = IDR_MAINFRAME;
LPITEMIDLIST lpDList = SHBrowseForFolder(&Bi);
if(lpDList && SHGetPathFromIDList(lpDList,m_lpFolderPath))
{
if (0 != wcscmp(wcDisplayName, TEXT("英雄联盟")))
{
MessageBox(TEXT("您指定的目录不是英雄联盟的安装目录"), TEXT("LOL地图修改器"), MB_OK | MB_ICONERROR);
}
else
{
SetDlgItemText(IDC_STATIC_SHOWPATH,m_lpFolderPath);
//将选取的文件路径保存到文本,以便下次读取
CFileException fileException;
if (m_ConfigFile.Open(TEXT("./Config.dat"),
CFile::modeWrite | CFile::typeText |CFile::shareExclusive|CFile::modeCreate),&fileException)
{
char* oldlocal = _strdup(setlocale(LC_CTYPE, NULL));
setlocale(LC_CTYPE, "chs");
m_ConfigFile.WriteString(m_lpFolderPath);
m_ConfigFile.Close();
setlocale(LC_CTYPE, oldlocal);
free(oldlocal);
}
}
}else
{
MessageBox(TEXT("请指定正确的LOL安装路径"),TEXT("LOL地图修改器"),MB_OK|MB_ICONERROR);
}
}
LOL安装目录用户点击选择地图并且获得正确的路径后,我们会将其存入一个文件,所以在第二次打开软件的时候,可以直接从文件内获取,找到OnInitDialog函数,并在其后添加如下代码,将这个目录显示到一个静态文本框内。同时将其放入一个类成员变量中。以便后面使用
[Asm] 纯文本查看 复制代码 //读取文件获取英雄联盟所在目录
if (m_ConfigFile.Open(TEXT("./Config.dat"),
CFile::modeRead))
{
char* oldlocal = _strdup(setlocale(LC_CTYPE, NULL));
setlocale(LC_CTYPE, "chs");
m_ConfigFile.ReadString(m_lpFolderPath,MAX_PATH);
if (wcslen(m_lpFolderPath) > 0)
{
SetDlgItemText(IDC_STATIC_SHOWPATH,m_lpFolderPath);
}
m_ConfigFile.Close();
setlocale(LC_CTYPE, oldlocal);
free(oldlocal);
}
2.选择地图
通过下拉combobox的项选择地图,程序读取选择获得选择的地图,首先为ComboBox添加一个Control变量,同时在OnInitDialog中初始化Combobox的项
[C++] 纯文本查看 复制代码 //初始化组合框
m_cbChoseMap.AddString(TEXT("银花满地"));
m_cbChoseMap.AddString(TEXT("金沙遍野"));
m_cbChoseMap.AddString(TEXT("傲雪凌霜 "));
m_cbChoseMap.AddString(TEXT("绿草如荫"));
m_cbChoseMap.AddString(TEXT("鲜血战场"));
m_cbChoseMap.AddString(TEXT("黄昏战场"));
m_cbChoseMap.AddString(TEXT("紫色风情 "));
m_cbChoseMap.AddString(TEXT("烈焰战场"));
m_cbChoseMap.SetCueBanner(TEXT("在此选择地图"));
同时,为了良好的用户体验,应当在程序启动时显示一个默认图片(楼主显得蛋疼此处后面改成gif图了)同样在OninitDialog中添加代码
[C++] 纯文本查看 复制代码 //默认显示图片
CString str( ".//Map//Preview//defalut.jpg");
if (S_OK == m_ImagePrive.Load(str))
{
CWnd* pWnd = GetDlgItem(IDC_PREVIEW);
CRect rect;
pWnd->GetWindowRect(&rect);
InvalidateRect(rect);
}
else
{
MessageBox(TEXT("预览图片加载失败1"));
}
为了再用户通过下拉框选择地图的时候实时显示对应的地图预览。为ComboBox添加消息响应函数,每当用户点击Combobox的时候,通过UpdateData获得项,并选择对应的预览图片。图片的显示及加载都是用CImage类,
[C++] 纯文本查看 复制代码 //根据用户的选择显示图片
void CLOLMapChangeDlg::OnCbnSelchangeComboChosemap()
{
UpdateData(TRUE);
int nIndex = m_cbChoseMap.GetCurSel();
WCHAR wcPicName[200] = {TEXT('\0')};
char cstrPicName[400] = {0};
swprintf_s(wcPicName, TEXT(".\\Map\\Preview\\%d.jpg"), nIndex);
CString str = wcPicName;
if (S_OK == m_ImagePrive.Load(str))
{
CWnd* pWnd = GetDlgItem(IDC_PREVIEW);
CRect rect;
pWnd->GetWindowRect(&rect);
InvalidateRect(rect);
}else
{
MessageBox(TEXT("预览图片加载失败"));
}
}
为了正确的显示图片,我们做强制刷新,并在OnPaint函数中添加代码,最终如下
[C++] 纯文本查看 复制代码 <pre name="code" class="cpp" style="font-size:14px; font-family: 'Microsoft YaHei'; ">void CLOLMapChangeDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// 使图标在工作区矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
CWnd* pWnd = GetDlgItem(IDC_PREVIEW);
CRect rect;
CDC* pDC = pWnd->GetDC();
pWnd->GetClientRect(&rect);
pDC->SetStretchBltMode(STRETCH_HALFTONE);
if (0 == m_ImagePrive.Draw(pDC->GetSafeHdc(), rect))
MessageBox(TEXT("绘图失败"));
}
}
3.地图修改为修改地图按钮添响应函数,在真正的修改前,应当备份原地图。最后将指定地图包拷贝到LOL地图目录下并替换原有地图,代码如下
[C++] 纯文本查看 复制代码 <pre name="code" class="cpp"> //备份官方地图
WCHAR wcOldMap[MAX_PATH] = { 0 };
WCHAR wcNewMap[MAX_PATH] = { 0 };
if (wcslen(m_lpFolderPath) > 1)
{
wcscpy_s(wcOldMap, MAX_PATH, m_lpFolderPath);
wcscpy_s(wcNewMap, MAX_PATH, m_lpFolderPath);
wcscat_s(wcOldMap, MAX_PATH, TEXT("\\Game\\Map1.zip"));
wcscat_s(wcNewMap, MAX_PATH, TEXT("\\Game\\Map1_backup.zip"));
if (0 == CopyFile(wcOldMap, wcNewMap, FALSE))
{
MessageBox(TEXT("地图备份失败,请正确指定LOL安装目录后重试"),TEXT("LOL地图修改器"),MB_OK|MB_ICONERROR);
}
//根据用户的选择选择正确的地图加载
UpdateData(TRUE);
int nIndex = m_cbChoseMap.GetCurSel();
wcscpy_s(wcNewMap, MAX_PATH, m_lpFolderPath);
wcscat_s(wcNewMap, MAX_PATH, TEXT("\\Game\\Map1.zip"));
swprintf_s(wcOldMap,TEXT(".\\Map\\%d.zip"),nIndex);
if (0 == CopyFile(wcOldMap, wcNewMap, FALSE))
{
MessageBox(TEXT("地图修改失败,请正确指定地图后重试"), TEXT("LOL地图修改器"), MB_OK | MB_ICONERROR);
}else
{
MessageBox(TEXT("恭喜,地图修改成功!!!!"));
}
}else
{
MessageBox(TEXT("地图修改失败,英雄联盟目录不正确"), TEXT("LOL地图修改器"), MB_OK | MB_ICONERROR);
}
对地图的还原,此处可以选择将在修改目录中备份的文件复制用于还原。实现的时候我是将默认地图拷贝出来与新地图包放在一起的。所以我是拷贝的软件目录下的文件。
[C++] 纯文本查看 复制代码 <pre name="code" class="cpp">void CLOLMapChangeDlg::OnBnClickedBtnRestor()
{
if (wcslen(m_lpFolderPath) >1)
{
WCHAR wcOldMap[MAX_PATH] = { 0 };
WCHAR wcNewMap[MAX_PATH] = { 0 };
wcscpy_s(wcOldMap, MAX_PATH, TEXT(".\\Map\\default.zip"));
wcscpy_s(wcNewMap, MAX_PATH, m_lpFolderPath);
wcscat_s(wcNewMap, MAX_PATH, TEXT("\\Game\\Map1.zip"));
if (0 == CopyFile(wcOldMap, wcNewMap, FALSE))
{
MessageBox(TEXT("还原失败,请正确指定文件后重试"), TEXT("LOL地图修改器"), MB_OK | MB_ICONERROR);
}
else
{
MessageBox(TEXT("一键还原成功!!"));
}
}else
{
MessageBox(TEXT("还原失败,英雄联盟目录不正确"), TEXT("LOL地图修改器"), MB_OK | MB_ICONERROR);
}
}
→_→,,居然有个人叫多说点,好吧,如果字数越多经验越多我应该能拿挺多经验了
|