新手做的计算器 有问题待解决

antion692980794 2010-09-17 11:08:02
用SDK做的 刚学不久 有不少问题呢

问题1:不能支持键盘输入 加入WM_KEYDOWN WM_CHAR 消息后不能响应(MessageBox函数)
问题2: 显示数字问题,因为是用SetDlgItemText实现的,只能用字符串,每次显示的数都是保留六位小数的,而且最长支持14位数 不然就越界 有什么方法可以动态的显示数字呢?(比如按下小数点之后才有小数出现)还有解决问题?

下面是源码 各位前辈请多多指教 也可以多提些学习的建议 谢谢了~

#include <windows.h>
#include <stdio.h>
#include "resource.h"


BOOL CALLBACK DialogProc(HWND, UINT, WPARAM, LPARAM);//对话框消息函数

void ShowNumber (HWND hwnd,long double iNumber);//显示输入的数字

double Result(long double iFirstNum, char iOperation,long double iNum);//计算结果函数

int WINAPI WinMain(
HINSTANCE hInstance, // handle to current instance
HINSTANCE hPrevInstance, // handle to previous instance
LPSTR lpCmdLine, // pointer to command line
int nCmdShow // show state of window
)
{
MSG Message;

DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DialogProc, 0);

while (GetMessage (&Message, NULL, 0, 0))
{

TranslateMessage (&Message) ;
DispatchMessage (&Message) ;
}

return Message.wParam;
}

BOOL CALLBACK DialogProc(
HWND hwnd, // handle to dialog box
UINT uMsg, // message
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
)
{
static MSG Message;

static BOOL bEquel_Key=FALSE,bOperation_Key=FALSE,bDigit_Key=FALSE,bPoint=FALSE;//开关值

static char Operation='=';

static int iPoint=0;//判断小数点的位数

static long double iNumber=0,iFirstNumber=0,iResultNumber=0,Index=10;//计算用到的变量

HWND hDisplay;//显示区域句柄

hDisplay=GetDlgItem(hwnd,IDC_DISPLAY);//获取显示区域的句柄

bool KeyShift=FALSE;

//ShowNumber(hwnd,iNumber);//初始化显示区域

if(iPoint==0)
bPoint=FALSE;
switch (uMsg)
{
case WM_COMMAND:
switch(LOWORD(wParam))
{
case 0://输入零
if(bPoint)
{
int i=iPoint;
while(--i)
Index*=10;
ShowNumber(hwnd,iNumber+=(LOWORD(wParam))/Index);
iPoint++;
Index=10;
}
else
ShowNumber(hwnd,iNumber=iNumber*10);
return 0;
case 11:
case 12:
case 13:
case 14:
case 15:
case 16:
case 17:
case 18:
case 19://按下1-9
if(bEquel_Key)//上个消息是等于
{
iFirstNumber=iNumber=iResultNumber=0;//清空所有计算所用的变量
bEquel_Key=FALSE,bOperation_Key=FALSE,bDigit_Key=FALSE;
}
if(bOperation_Key)//上个消息是运算符
{
iFirstNumber=iNumber;
iNumber=0;
}
if(bPoint)//如果按下了小数点
{
int i=iPoint++;
while(--i)
Index*=10;
ShowNumber(hwnd,iNumber+=(LOWORD(wParam)-10)/Index);
Index=10;
}
else
{
iNumber=iNumber*10;
ShowNumber(hwnd,iNumber+=LOWORD(wParam)-10);
}
bDigit_Key=TRUE;
return 0;
case IDC_ADD:
case IDC_SUB:
case IDC_MUL:
case IDC_DIV:
case IDC_REM://输入符号
if(bDigit_Key&&bOperation_Key)//如果连续计算
iNumber=Result(iFirstNumber,Operation,iNumber);
if(bEquel_Key)//如果上一个消息是等号
iNumber=iResultNumber;
GetDlgItemText(hwnd,LOWORD(wParam),&Operation,2);//获取按下的符号
SetDlgItemText(hwnd,IDC_DISPLAY,&Operation);//在显示区域显示符号
bDigit_Key=FALSE;
bEquel_Key=FALSE;
bOperation_Key=TRUE;
bPoint=FALSE;
return 0;
case IDC_EQUEL://等于
if(bDigit_Key)
{
iResultNumber=Result(iFirstNumber,Operation,iNumber);
ShowNumber(hwnd,Result(iFirstNumber,Operation,iNumber));
}
if(bEquel_Key)//连续按下等号的计算
{
iFirstNumber=iResultNumber;
iResultNumber=Result(iFirstNumber,Operation,iNumber);
ShowNumber(hwnd,Result(iFirstNumber,Operation,iNumber));
}
bEquel_Key=TRUE;
bOperation_Key=FALSE;
bDigit_Key=FALSE;
return 0;
case IDC_ESPACE: //清空当行
iPoint=1;
iNumber=0;
bPoint=FALSE;
ShowNumber(hwnd,0);
return 0;
case IDC_BACK://退格
if(iNumber)
{
if(bPoint&&iPoint>2)
{
Index=10;
int i=iPoint-2;
while(--i)
Index*=10;
iNumber=(int)(iNumber*Index);
ShowNumber(hwnd,iNumber/=Index);
iPoint--;
}
else
if(iPoint==2)
{
ShowNumber(hwnd,iNumber=(int)iNumber);
iPoint--;
}
else
ShowNumber(hwnd,iNumber=(int)(iNumber/10));
}

return 0;
case IDC_BEGIN://重新计算 清零
iPoint=1;
iFirstNumber=iNumber=iResultNumber=0;
bPoint=FALSE;
ShowNumber(hwnd,0);
return 0;
case IDC_POINT:
if(!bPoint)
{
bPoint=TRUE;
iPoint=1;
}
return 0;
case IDC_SHIFT:
iNumber=-iNumber;
ShowNumber(hwnd,iNumber);
return 0;
case IDCANCEL://退出
EndDialog(hwnd,LOWORD(wParam));
return 0;
default:
return 0 ;
}
case WM_KEYDOWN:

case WM_CHAR:
MessageBox(hwnd,"1","1",0);
return 0;
case WM_SETFOCUS:
SetFocus(hDisplay);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
return TRUE;
}
return FALSE;
}


void ShowNumber (HWND hwnd,long double iNumber)//显示数字
{
TCHAR szBuffer[20] ;

sprintf(szBuffer, "%f", iNumber) ;

SetDlgItemText(hwnd,IDC_DISPLAY,szBuffer);
}

double Result(long double iFirstNum, char Operation,long double iNum) //显示计算结果
{

switch (Operation)
{
case '=': return iNum ;
case '+': return iFirstNum+iNum ;
case '-': return iFirstNum-iNum ;
case '*': return iFirstNum*iNum ;
case '/': return iFirstNum/iNum;
case '%': return (int)iFirstNum%(int)iNum;
default : return 0 ;
}
}
...全文
179 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
antion692980794 2010-09-18
  • 打赏
  • 举报
回复
还差一个问题呢 没人解决么 顶顶
antion692980794 2010-09-18
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 hmm7e 的回复:]
引用 8 楼 antion692980794 的回复:

引用 6 楼 hmm7e 的回复:
引用 4 楼 antion692980794 的回复:

引用 1 楼 hmm7e 的回复:
答"问题1":代码没仔细看,因此无法回答.
答"问题2":关于显示小数位数,这个通常是在后台处理后(四舍五入之类的方法,消去末尾的一位或几位)放到界面显示的. 按下小数点后显示数据:这个只能做"输入……
[/Quote]
很感谢你 问题2已经解决了
「已注销」 2010-09-18
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 antion692980794 的回复:]

引用 6 楼 hmm7e 的回复:
引用 4 楼 antion692980794 的回复:

引用 1 楼 hmm7e 的回复:
答"问题1":代码没仔细看,因此无法回答.
答"问题2":关于显示小数位数,这个通常是在后台处理后(四舍五入之类的方法,消去末尾的一位或几位)放到界面显示的. 按下小数点后显示数据:这个只能做"输入过虑",在后台做缓存,把所有输入的字符连起来存入缓存,再重新……
[/Quote]

可以,只你把这个函数里面的代码改改就成了,
sprintf(szBuffer, "%f", iNumber) ;这个函数中的第二个参数,可以控制输出的小数位数.详细情况MSDN或搜索"C语言 + printf + 格式控制符".这样只完成输出部分,显示小数点那部分,你还得自己写.
antion692980794 2010-09-18
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 hmm7e 的回复:]
引用 4 楼 antion692980794 的回复:

引用 1 楼 hmm7e 的回复:
答"问题1":代码没仔细看,因此无法回答.
答"问题2":关于显示小数位数,这个通常是在后台处理后(四舍五入之类的方法,消去末尾的一位或几位)放到界面显示的. 按下小数点后显示数据:这个只能做"输入过虑",在后台做缓存,把所有输入的字符连起来存入缓存,再重新显示到界面,碰到小数点,就连到缓存数据的……
[/Quote]
额 那你看我的实现方法可以不?ShowNumber()
antion692980794 2010-09-18
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 visualeleven 的回复:]
引用 3 楼 antion692980794 的回复:
引用 2 楼 visualeleven 的回复:
1. 在你的
while(GetMessage(&amp;amp;msg, NULL, 0, 0))
{
if(WM_KEYDOWN == msg.message)
{
// ...
}
TranlateMessage(&amp;amp;msg);
Disp……
[/Quote]
我的意思是这样一弄 结构完全被破坏了 还没学MFC。。。。那样可以实现 但是有没有在消息函数处理的方法呢?
「已注销」 2010-09-18
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 antion692980794 的回复:]

引用 1 楼 hmm7e 的回复:
答"问题1":代码没仔细看,因此无法回答.
答"问题2":关于显示小数位数,这个通常是在后台处理后(四舍五入之类的方法,消去末尾的一位或几位)放到界面显示的. 按下小数点后显示数据:这个只能做"输入过虑",在后台做缓存,把所有输入的字符连起来存入缓存,再重新显示到界面,碰到小数点,就连到缓存数据的后面,如果小数点后面还继续按下数字,则继续连在小数点后面.每……
[/Quote]

缓存.......弄个字符串数组就行了啊...
Eleven 2010-09-18
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 antion692980794 的回复:]
引用 2 楼 visualeleven 的回复:
1. 在你的
while(GetMessage(&amp;msg, NULL, 0, 0))
{
if(WM_KEYDOWN == msg.message)
{
// ...
}
TranlateMessage(&amp;msg);
DispatchMessage(&amp;msg);
}
不会吧 这样……
[/Quote]
有什么不合理呢?就相当于MFC中对话框程序的PreTranslateMessage虚函数中拦截处理WM_KEYDOWN消息一样的
antion692980794 2010-09-18
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 hmm7e 的回复:]
答"问题1":代码没仔细看,因此无法回答.
答"问题2":关于显示小数位数,这个通常是在后台处理后(四舍五入之类的方法,消去末尾的一位或几位)放到界面显示的. 按下小数点后显示数据:这个只能做"输入过虑",在后台做缓存,把所有输入的字符连起来存入缓存,再重新显示到界面,碰到小数点,就连到缓存数据的后面,如果小数点后面还继续按下数字,则继续连在小数点后面.每按一次按键就检测一次,直到其它操作插入(……
[/Quote]
缓存不太懂......如果有时间请看一下代码 很简单的代码 谢谢了 ....
antion692980794 2010-09-18
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 visualeleven 的回复:]
1. 在你的
while(GetMessage(&msg, NULL, 0, 0))
{
if(WM_KEYDOWN == msg.message)
{
// ...
}
TranlateMessage(&msg);
DispatchMessage(&msg);
}
[/Quote]不会吧 这样处理不符合结构啊?能不能在消息处理函数中实现呢?
antion692980794 2010-09-18
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 xianglitian 的回复:]
引用 18 楼 antion692980794 的回复:
引用 17 楼 xianglitian 的回复:
2楼的方法没什么问题
你就放心大胆的使吧

问题2已经弄好了 还有问题1呢
2楼就是解决问题1啊
[/Quote]
看错 我试过了 没反应。。。。我在if语句里价格个消息框 按键的时候不弹出.....
向立天 2010-09-18
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 antion692980794 的回复:]
引用 17 楼 xianglitian 的回复:
2楼的方法没什么问题
你就放心大胆的使吧

问题2已经弄好了 还有问题1呢
[/Quote]2楼就是解决问题1啊
schlafenhamster 2010-09-18
  • 打赏
  • 举报
回复
“我只需要一个对话框 所以.....”就违背常理?
应该:
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
BOOL bl;
HDC hdc;
HPEN hPen;
HPEN hOldPen;

HINSTANCE hInstance=(HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE);
switch(message)
{
case WM_CREATE:
MessageBeep(48);
m_hMain=hwnd;
// CreateDialog(hInstance, MAKEINTRESOURCE(101), hwnd, DialogProc) ;

DialogBox((HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE),
MAKEINTRESOURCE(101), hwnd, DialogProc);

//在DialogProc中相应WM_KEYDOWN
antion692980794 2010-09-18
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 xianglitian 的回复:]
2楼的方法没什么问题
你就放心大胆的使吧
[/Quote]
问题2已经弄好了 还有问题1呢
向立天 2010-09-18
  • 打赏
  • 举报
回复
2楼的方法没什么问题
你就放心大胆的使吧
antion692980794 2010-09-18
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 dingshaofengbinbin 的回复:]
PreTanslateMessage(MSG *m)
{
if(m->message==WM_CHAR)
{
::SendMessage(hWnd,m->message,m->wparam,m->lparam);
}
}
[/Quote]
我查了MSDN SDC里面没有这个函数啊 不是MFC
dingshaofengbinbin 2010-09-18
  • 打赏
  • 举报
回复
PreTanslateMessage(MSG *m)
{
if(m->message==WM_CHAR)
{
::SendMessage(hWnd,m->message,m->wparam,m->lparam);
}
}
dingshaofengbinbin 2010-09-18
  • 打赏
  • 举报
回复
问题1:
你应该在PreTranslateMessage()虚函数中截获WM_KEYDOWN WM_CHAR这个消息,然后SendMessage()把他发送到指定的窗口过程中。。。。
antion692980794 2010-09-18
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 schlafenhamster 的回复:]
//没看到注册窗体
if(!RegisterClassEx(&wcex))
{
return 0;
}
//和产生窗口
hParentWnd = CreateWindow(szWindowClass, szTitle,WS_OVERLAPPEDWINDOW ,
CW_USEDEFAULT,
[/Quote]
我只需要一个对话框 所以.....
schlafenhamster 2010-09-18
  • 打赏
  • 举报
回复
//没看到注册窗体
if(!RegisterClassEx(&wcex))
{
return 0;
}
//和产生窗口
hParentWnd = CreateWindow(szWindowClass, szTitle,WS_OVERLAPPEDWINDOW ,
CW_USEDEFAULT,
Eleven 2010-09-17
  • 打赏
  • 举报
回复
1. 在你的
while(GetMessage(&msg, NULL, 0, 0))
{
if(WM_KEYDOWN == msg.message)
{
// ...
}
TranlateMessage(&msg);
DispatchMessage(&msg);
}
加载更多回复(1)

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧