MFC实现CSGO汰换合同磨损计算器(长期更新)
开发环境:Visual Studio 2019
目录
Version 0.1 完成项目基本部分
首先在VS2019中搜索到MFC应用。(此文章不提供安装方法)
点击下一步,到达此页面选择创建。
点击创建,并在应用程序类型中选择基于对话框。
正确进入时的界面。
在右侧工具箱中选择Edit Control并添加十一个到窗口中。(直接拖过去)
完成效果如下图。
在右侧工具箱中选择Static Text并添加十个到窗口中的Edit Control左边。
完成效果如下图。
然后单击第最后一个示例编辑框(正确的前提是前十个示例编辑框的范围在1~10,最后一个为11)在右侧属性页修改ID,修改为IDC_RESULT。
然后双击确定和取消。
进入CSGODlg.cpp开始编辑代码。
将void CCSGODlg::OnBnClickedOk()的代码修改为如下。
void CCSGODlg::OnBnClickedOk()
{
CString WFloat[10], Result;
double strResult{};
GetDlgItem(IDC_EDIT1)->GetWindowText(WFloat[0]);
GetDlgItem(IDC_EDIT2)->GetWindowText(WFloat[1]);
GetDlgItem(IDC_EDIT3)->GetWindowText(WFloat[2]);
GetDlgItem(IDC_EDIT4)->GetWindowText(WFloat[3]);
GetDlgItem(IDC_EDIT5)->GetWindowText(WFloat[4]);
GetDlgItem(IDC_EDIT6)->GetWindowText(WFloat[5]);
GetDlgItem(IDC_EDIT7)->GetWindowText(WFloat[6]);
GetDlgItem(IDC_EDIT8)->GetWindowText(WFloat[7]);
GetDlgItem(IDC_EDIT9)->GetWindowText(WFloat[8]);
GetDlgItem(IDC_EDIT10)->GetWindowText(WFloat[9]);
for (int i = 0; i < 10; i++)
{
strResult += _ttof(WFloat[i]);
}
strResult /= 10;
Result.Format((CString)"%0.15f",strResult );
GetDlgItem(IDC_RESULT)->SetWindowText(Result);
}
然后对窗口的界面进行一下修改,0.1版本汰换磨损计算器就做好了。
测试效果如下。
Version 0.2 项目功能强化
Version 0.1仅仅只能做到十个数求平均值,还不能真正的日常使用。
待完成目标列表如下:
1.使用CSGO的汰换合同算法来完成计算。
2.磨损输出精确位数提升到极限。
3.提供正反向的精确计算功能。
4.增加一个界面用于输出提示信息。
5.对输入错误的值弹出警告。
Version 0.2将完成以上的目标1和4。
先将界面修改如下。将ID为IDC_RESULT的窗口移至右上角、添加两个Edit Control并将ID修改为IDC_LOWEST和IDC_HIGHEST、右下角添加一个提示按钮并修改ID为IDC_MESSAGE
双击提示进入代码编辑页面。
加入如下代码。
void CCSGODlg::OnBnClickedMessage()
{
CString Message{ "CSGO汰换计算 Version 0.2\r\n" }, Temp;
GetDlgItem(IDC_RESULT)->GetWindowText(Temp);
Temp += Message;
GetDlgItem(IDC_RESULT)->SetWindowText(Temp);
}
然后在属性中将IDC_RESULT窗口的多行和想要返回设置为True。
自此第四个目标已经初步实现,接下来,Introducing CSGO汰换合同磨损算法。
最终目标磨损=(目标最高磨损-目标最低磨损)*十件材料的平均磨损+目标最低磨损
将确定的函数修改为如下。
void CCSGODlg::OnBnClickedOk()
{
CString WFloat[10], Result, HF, LF;
double strResult{};
GetDlgItem(IDC_EDIT1)->GetWindowText(WFloat[0]);
GetDlgItem(IDC_EDIT2)->GetWindowText(WFloat[1]);
GetDlgItem(IDC_EDIT3)->GetWindowText(WFloat[2]);
GetDlgItem(IDC_EDIT4)->GetWindowText(WFloat[3]);
GetDlgItem(IDC_EDIT5)->GetWindowText(WFloat[4]);
GetDlgItem(IDC_EDIT6)->GetWindowText(WFloat[5]);
GetDlgItem(IDC_EDIT7)->GetWindowText(WFloat[6]);
GetDlgItem(IDC_EDIT8)->GetWindowText(WFloat[7]);
GetDlgItem(IDC_EDIT9)->GetWindowText(WFloat[8]);
GetDlgItem(IDC_EDIT10)->GetWindowText(WFloat[9]);
GetDlgItem(IDC_HIGHEST)->GetWindowText(HF);
GetDlgItem(IDC_LOWEST)->GetWindowText(LF);
if (HF == "" || _ttof(HF) <= 0 || _ttof(HF) > 1)//当最高磨损的输入错误时,将其设为默认值1
HF = "1";
if (LF == "" || _ttof(LF) >= 1 || _ttof(LF) <= 0 || _ttof(LF) > _ttof(HF))//当最低磨损的输入错误时,将其设为默认值0
{
HF = "1";
LF = "0";
}
for (int i = 0; i < 10; i++)
{
strResult += _ttof(WFloat[i]);
}
strResult = (_ttof(HF) - _ttof(LF)) * strResult / 10 + _ttof(LF);
Result.Format((CString)"%0.15f", strResult);
GetDlgItem(IDC_RESULT)->SetWindowText(Result);
}
在最高最低磨损输入错误的情况下会默认输出最低磨损为0最高磨损为1时的值。
Version 0.3 增加自定义函数
在CSGODlg.h中类的Public下声明要自定义的函数,我在此声明的是:
afx_msg void GetFloat(CString Weapon[10]);
然后在CSGODlg.cpp中将此函数实例化。
void CCSGODlg::GetFloat(CString Weapon[10])
{
GetDlgItem(IDC_EDIT1)->GetWindowText(Weapon[0]);
GetDlgItem(IDC_EDIT2)->GetWindowText(Weapon[1]);
GetDlgItem(IDC_EDIT3)->GetWindowText(Weapon[2]);
GetDlgItem(IDC_EDIT4)->GetWindowText(Weapon[3]);
GetDlgItem(IDC_EDIT5)->GetWindowText(Weapon[4]);
GetDlgItem(IDC_EDIT6)->GetWindowText(Weapon[5]);
GetDlgItem(IDC_EDIT7)->GetWindowText(Weapon[6]);
GetDlgItem(IDC_EDIT8)->GetWindowText(Weapon[7]);
GetDlgItem(IDC_EDIT9)->GetWindowText(Weapon[8]);
GetDlgItem(IDC_EDIT10)->GetWindowText(Weapon[9]);
}
然后将void CCSGODlg::OnBnClickedOk()的代码进行修改以使用此函数。
void CCSGODlg::OnBnClickedOk()
{
CString WFloat[10], Result, HF, LF;
double strResult{};
GetFloat(WFloat);
GetDlgItem(IDC_HIGHEST)->GetWindowText(HF);
GetDlgItem(IDC_LOWEST)->GetWindowText(LF);
if (HF == "" || _ttof(HF) <= 0 || _ttof(HF) > 1)//当最高磨损的输入错误时,将其设为默认值1
HF = "1";
if (LF == "" || _ttof(LF) >= 1 || _ttof(LF) <= 0 || _ttof(LF) > _ttof(HF))//当最低磨损的输入错误时,将其设为默认值0
{
HF = "1";
LF = "0";
}
for (int i = 0; i < 10; i++)
{
strResult += _ttof(WFloat[i]);
}
strResult = (_ttof(HF) - _ttof(LF)) * strResult / 10 + _ttof(LF);
Result.Format((CString)"%0.15f", strResult);
GetDlgItem(IDC_RESULT)->SetWindowText(Result);
}
Version 0.4 自定义函数以及输入检查
在CSGODlg.h头文件类下的Public中,声明一个函数,用于保持窗口原有内容的情况下附加内容。声明如下:
afx_msg void DisplayInResult(CString Message);
然后在CSGODlg.cpp中将此函数实例化。
void CCSGODlg::DisplayInResult(CString Message)
{
CString Temp;
GetDlgItem(IDC_RESULT)->GetWindowText(Temp);
Temp += Message;
GetDlgItem(IDC_RESULT)->SetWindowText(Temp);
}
使用此函数可将之前的提示按钮的函数的内容减少到一行:
void CCSGODlg::OnBnClickedMessage()
{
DisplayInResult((CString)"CSGO汰换计算 Version 0.4\r\n");
}
确定按钮的函数可修改为如下:
void CCSGODlg::OnBnClickedOk()
{
int Warn{};
CString WFloat[10], Result, HF, LF, WarnS{};
double strResult{};
GetFloat(WFloat);
GetDlgItem(IDC_HIGHEST)->GetWindowText(HF);
GetDlgItem(IDC_LOWEST)->GetWindowText(LF);
if (HF == "" || _ttof(HF) <= 0 || _ttof(HF) > 1)//当最高磨损的输入错误时,将其设为默认值1
HF = "1";
if (LF == "" || _ttof(LF) >= 1 || _ttof(LF) <= 0 || _ttof(LF) > _ttof(HF))//当最低磨损的输入错误时,将其设为默认值0
{
HF = "1";
LF = "0";
}
for (int i = 0; i < 10; i++)
{
if (_ttof(WFloat[i]) < 0 || _ttof(WFloat[i]) > 1)//当磨损输入错误时,将其设为默认值0
{
WFloat[i] = "0";
Warn += 1;
}
strResult += _ttof(WFloat[i]);
}
strResult = (_ttof(HF) - _ttof(LF)) * strResult / 10 + _ttof(LF);
Result.Format((CString)"%0.15f", strResult);
DisplayInResult(Result);
if (Warn != 0)//对输入错误的值的数量进行提示_0.4更新
{
WarnS.Format((CString)"%d", Warn);
DisplayInResult((CString)"警告,输入的十个值中出现了" + WarnS + (CString)"个错误的值,当前已复原为0\r\n");
}
}
以上代码包含了对输入错误的值的判断,具体代码节选如下:
Warn初始化为0,每次出现不满足数值的值就给Warn+1,如果最后Warn不为0则弹出提示。
if (_ttof(WFloat[i]) < 0 || _ttof(WFloat[i]) > 1)//当磨损输入错误时,将其设为默认值0
{
WFloat[i] = "0";
Warn += 1;
}
if (Warn != 0)
{
WarnS.Format((CString)"%d", Warn);
DisplayInResult((CString)"警告,输入的十个值中出现了" + WarnS + (CString)"个错误的值,当前已复原为0\r\n");
}
运行效果如下:
Version 0.5 细节完善以及清理窗口
193行用于输出汰换计算的磨损结果,在此处加上换行符(\r\n)。
Result.Format((CString)"%0.15f\r\n", strResult);
删除198行开头的\r\n。
DisplayInResult((CString)"警告,输入的十个值中出现了" + WarnS + (CString)"个错误的值,当前已复原为0\r\n");
增加对最高磨损&最低磨损输入错误的提示。
if (HF == "" || _ttof(HF) <= 0 || _ttof(HF) > 1)//当最高磨损的输入错误时,将其设为默认值1
{
DisplayInResult((CString)"输入的最高值出现了错误,当前已复原为1!\r\n");
HF = "1";
}
if (LF == "" || _ttof(LF) >= 1 || _ttof(LF) <= 0 || _ttof(LF) > _ttof(HF))//当最低磨损的输入错误时,将其设为默认值0
{
DisplayInResult((CString)"输入的最低值出现了错误,当前已复原为0!\r\n");
LF = "0";
}
添加一个名为IDC_CLEAR的按钮。
双击按钮对其进行编辑,其内容如下。
void CCSGODlg::OnBnClickedClear()
{
GetDlgItem(IDC_RESULT)->SetWindowText(NULL);
}
顺便修改一下提示按钮的内容:
void CCSGODlg::OnBnClickedMessage()
{
DisplayInResult((CString)"CSGO汰换计算 Version 0.5\r\n更新内容:细节完善以及清理窗口\r\n");
}
对窗口进行微调,以适应四个按钮。
运行效果如下:
Version 0.6 错误修复以及反向计算
182行的if在最低磨损为0时会错误的得到True的bool值,将_ttof(LF)<=0改为_ttof(LF)<0即可
将IDC_RESULT的Auto HScroll设置为False,这样就不会输出到范围以外。
因为取消的功能和右上角的×重复了,所以将取消按钮IDCANCEL改为IDC_RECAL,作为反向计算按钮。
在源文件中删除对Cancel按钮的定义。
添加一个用于反向计算时输入主材料数量的Edit_Control,ID为IDC_NUM。
目前仅在函数中添加计算主材料平均磨损的功能,后续将会得到完善。
修改确认与取消的名称。
运行效果如下。