一、简述
记--使用WindowsAPI开发图形界面应用--简单的计算器。
例子:链接: https://pan.baidu.com/s/1SDg5RByN4xQohoi-ao8Wzg 提取码: kv42
二、效果
三、工程结构
四、源文件
main.cpp文件
#define _CRT_SECURE_NO_WARNINGS //有一些函数有新的安全版本,使用就之前的会报警告
#include
#include "resource.h"
#include
#define EXP_MAX_LEN 22
char gSign[3] = {0};//运算符×÷+-
//判断指定的字符是否是运算符
int IsASign(const char* _char,unsigned char _flag)
{
if(NULL == _char)
{
return 0;
}
if(1 == _flag)//ASCII模式
{
if(_char[0] == '+' )
{
return 3;
}
else if(_char[0] == '-' )
{
return 4;
}
}
if(strlen(_char)>1)//×÷是中文字符,占2个字节
{
if(_char[0] == "×"[0] && _char[1] == "×"[1] )
{
return 1;
}
if(_char[0] == "÷"[0] && _char[1] == "÷"[1] )
{
return 2;
}
if(2 == _flag)//判断最后一个字符的时候
{
if(_char[1] == '+' )
{
return 3;
}
else if(_char[1] == '-' )
{
return 4;
}
}
}
return 0;
}
//判断表达式是否含有运算符
int ExpIsHasSign(const char* _exp)
{
int i;
int len;
if(NULL != _exp)
{
len = strlen(_exp);
for(i=0; i0)
{
return 1;
}
}
}
return 0;
}
//计算两个运算数的结果
int GetResult(long long _leftVal, long long _rightVal, char _sign, long long* _result)
{
int ret = 0;
if(_sign == '*')
{
*_result = _leftVal*_rightVal;
ret = 1;
}
else if(_sign == '/')
{
if(0 != _rightVal)
{
*_result = _leftVal/_rightVal;
ret = 1;
}
}
else if(_sign == '+')
{
*_result = _leftVal+_rightVal;
ret = 1;
}
else if(_sign == '-')
{
*_result = _leftVal-_rightVal;
ret = 1;
}
return ret;
}
//判断字符串最后一个字符是否是运算符
int StrLastCharIsSign(char* _str)
{
UINT len = 0;
if(NULL == _str)
{
return 0;
}
len = strlen(_str);
if(len>512)
{
len = 511;
_str[512] = '\0';
}
if(len>0)
{
if(IsASign(&(_str[len-1]),1)>0 )
{
return 1;
}
if(len>1)
{
if(IsASign(&(_str[len-2]),2)>0)
{
return 1;
}
}
}
return 0;
}
//判断表达式最后一个字符是否是运算符
int LastCharIsSign(HWND _hwndDlg, int _nID)
{
char buf[512] = {0};
GetDlgItemText(_hwndDlg, _nID, buf, sizeof(buf));
return StrLastCharIsSign(buf);
}
//判断一个字符是否是数字
char IsANum(const char _ch)
{
if(_ch>= '0' && _ch<='9')
{
return _ch;
}
return -1;
}
//将字符串形式的运算数转化为数字
int StrToDec(const char* strNum, long long* num)
{
if(NULL == strNum)
{
return -1;
}
*num = 0;
int len = strlen(strNum);
int i;
for(i=0; i0)
{
*num = (*num*10) + (strNum[i] - '0');
}
}
return 0;
}
//计算表达式结果
int GetExpResult(HWND hwndDlg, int nID)
{
char buf[512] = {0};
GetDlgItemText(hwndDlg, nID, buf, sizeof(buf));
char* bufPtr = buf;
int len = strlen(gSign);
if(len<=0)
{
return -1;
}
int isNagtive = 0;//标识左值是否是负数
if(buf[0] == '-')
{
isNagtive = 1;
bufPtr++;
}
len = strlen(bufPtr);
if(len<3)
{
return -2;
}
char* signPtr = strstr(bufPtr, gSign);
if(NULL != signPtr && 0 == StrLastCharIsSign(bufPtr))//有运算符并且不是最后一个字符的(也就是用户输入了两个运算数和一个运算符了才进行运算)
{
int signIndex = strlen(signPtr);
char chLeftVal[512] = {0};//左值
char chRightVal[512] = {0};//右值
long long numLeftVal = 0;
long long numRightVal = 0;
long long result = 0;//结果
int sign = IsASign(gSign,1);
memcpy(chLeftVal,bufPtr,len-signIndex);
memcpy(chRightVal,&bufPtr[len-signIndex+1+(sign/3+1)%2],signIndex-strlen(gSign));
int ret1, ret2, ret3 = 0;
ret1 = StrToDec(chLeftVal, &numLeftVal);
ret2 = StrToDec(chRightVal, &numRightVal);
if(1 == isNagtive)
{
numLeftVal = -numLeftVal;
}
if(ret1 == 0 && ret2 == 0)
{
switch(sign)
{
case 1:
ret3 = GetResult(numLeftVal, numRightVal, '*', &result);
break;
case 2:
ret3 = GetResult(numLeftVal, numRightVal, '/', &result);
break;
case 3:
ret3 = GetResult(numLeftVal, numRightVal, '+', &result);
break;
case 4:
ret3 = GetResult(numLeftVal, numRightVal, '-', &result);
break;
default:
ret3 = GetResult(numLeftVal, numRightVal, '+', &result);
break;
}
if(1 == ret3)
{
char tmp[128] = {0};
sprintf(tmp, "%lld", result);
if(strlen(tmp)<=0)
{
memcpy(tmp, "0", 2);
}
SetDlgItemText(hwndDlg, IDC_EXP, tmp);//设置结果
memset(gSign,0,3);
}
}
}
return 0;
}
//追加文本到编辑框
int AppendText(HWND hwndDlg, int nID, const char* str)
{
if(NULL == str)
{
return 0;
}
char buf[EXP_MAX_LEN+2] = {0};
int len1,len2;
GetDlgItemText(hwndDlg, nID, buf, sizeof(buf));
len1 = strlen(buf);
len2 = strlen(str);
if(len1+len2>=EXP_MAX_LEN)
{
return 0;
}
memcpy(&buf[len1], str, EXP_MAX_LEN-len1);
len1 = strlen(buf);
if(0 >= len1)
{
SetDlgItemText(hwndDlg, IDC_EXP, "0");
return 0;
}
int i = 0;
if(len1>1)
{
for(i=0; i0 )//如果全是0,或者首个非0字符是运算符就可以保留一个0
{
if(buf[0] != '-' &&buf[i] != '-')//如果上一次计算结果不是负数
{
i--;
}
}
SetDlgItemText(hwndDlg, IDC_EXP, &buf[i]);
return 0;
}
//退格--将编辑框文本内容最后一个字符删除
int DeleteAChar(HWND hwndDlg, int nID)
{
char buf[512] = {0};
UINT len = 0;
GetDlgItemText(hwndDlg, nID, buf, sizeof(buf));
len = strlen(buf);
if(len>512)
{
len = 511;
buf[512] = '\0';
}
if(len > 0)
buf[len-1] = '\0';
len = strlen(buf);
if(len == 0)//表达式不为空
{
buf[0] = '0';
buf[1] = '\0';
}
SetDlgItemText(hwndDlg, IDC_EXP, buf);
return 0;
}
//回调函数--接受并处理 点击(操作)窗口、控件 后产生的各种消息
INT_PTR CALLBACK MyDialogProcess(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
unsigned short id = 0;
switch(uMsg)
{
case WM_INITDIALOG://初始化对话框的时候,将编辑框内容设置为0
SetDlgItemText(hwndDlg, IDC_EXP, "0");
//窗体句柄,窗体的顺序,窗体位置x,y;窗体大小宽高,参数可选项
SetWindowPos(hwndDlg,HWND_TOPMOST,200,200,100,100,SWP_NOSIZE);//设置窗体位置,HWND_TOPMOST:窗体置顶,SWP_NOSIZE:忽略设置的窗体大小设置,即不改变窗体大小。
break;
case WM_COMMAND:
id = LOWORD(wParam);
switch(id)
{
case IDCANCEL:
EndDialog(hwndDlg, IDCANCEL);//退出,关闭对话框
break;
case IDC_BUTTON9:
AppendText(hwndDlg, IDC_EXP, "9");
break;
case IDC_BUTTON8:
AppendText(hwndDlg, IDC_EXP, "8");
break;
case IDC_BUTTON7:
AppendText(hwndDlg, IDC_EXP, "7");
break;
case IDC_BUTTON6:
AppendText(hwndDlg, IDC_EXP, "6");
break;
case IDC_BUTTON5:
AppendText(hwndDlg, IDC_EXP, "5");
break;
case IDC_BUTTON4:
AppendText(hwndDlg, IDC_EXP, "4");
break;
case IDC_BUTTON3:
AppendText(hwndDlg, IDC_EXP, "3");
break;
case IDC_BUTTON2:
AppendText(hwndDlg, IDC_EXP, "2");
break;
case IDC_BUTTON1:
AppendText(hwndDlg, IDC_EXP, "1");
break;
case IDC_BUTTON0:
AppendText(hwndDlg, IDC_EXP, "0");
break;
case IDC_BUTTONPlus:
GetExpResult(hwndDlg, IDC_EXP);
if(1 != LastCharIsSign(hwndDlg,IDC_EXP))//前面不是运算符时,才能添加(两个运算符不能在一块)
{
AppendText(hwndDlg, IDC_EXP, "+");
memcpy(gSign,"+",2);
}
break;
case IDC_BUTTONSub:
GetExpResult(hwndDlg, IDC_EXP);
if(1 != LastCharIsSign(hwndDlg,IDC_EXP))
{
AppendText(hwndDlg, IDC_EXP, "-");
memcpy(gSign,"-",2);
}
break;
case IDC_BUTTONMul:
GetExpResult(hwndDlg, IDC_EXP);
if(1 != LastCharIsSign(hwndDlg,IDC_EXP))
{
AppendText(hwndDlg, IDC_EXP, "×");
memcpy(gSign,"×",2);
}
break;
case IDC_BUTTONDiv:
GetExpResult(hwndDlg, IDC_EXP);
if(1 != LastCharIsSign(hwndDlg,IDC_EXP))
{
AppendText(hwndDlg, IDC_EXP, "÷");
memcpy(gSign,"÷",2);
}
break;
case IDC_BUTTONClear:
SetDlgItemText(hwndDlg, IDC_EXP, "0");
memset(gSign,0,3);
break;
case IDC_BUTTONDel:
DeleteAChar(hwndDlg, IDC_EXP);
break;
case IDC_BUTTONEqual://计算结果
GetExpResult(hwndDlg, IDC_EXP);
break;
case IDC_MenuAbout:
//参数:父窗口 内容 标题 按钮类型及个数
MessageBox(NULL, "这是一个简单的计算器!!!", "提示", MB_ICONINFORMATION|MB_OKCANCEL);//消息框,返回的是按钮编号
break;
}
break;
}
return 0;
}
//程序主入口
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrev, LPSTR lpCmd, int nCmdShow)
{
//添加图标,直接添加即可
//参数:资源 对话框ID 父窗口 回调函数
DialogBox(hInstance,(LPSTR)IDD_DIALOG1, NULL, MyDialogProcess);//弹出一个对话框
return 0;
}
五、总结
5.1 一些函数的简单介绍
hwnd:窗口句柄
nID:控件ID
int GetDlgItemInt(hwnd, nID, NULL, TRUE);获取编辑框内容为一个数字
SetDlgItemInt(hwnd, nID, aNumber, TRUE);设置编辑框内容为一个数字,aNumber:要设置的数字
GetDlgItemText(hwnd, nID, str, sizeof(str));获取编辑框文本内容,(放到str中,通常str是字符数组)
SetDlgItemText(hwnd, nID, str);设置编辑框文本内容,str:要设置的文本
SetWindowText(hwnd, str);设置窗口标题,str:要设置的标题
SetWindowPos(hwnd,HWND_TOPMOST,X,Y,cx,cy,uFlags);设置窗体位置,HWND_TOPMOST:窗口显示在最前面
以上API函数相关细节请参考:WinUser.h
5.2 添加资源
-