读书人

一个最简单的16进制的计算器分析,该怎

发布时间: 2012-05-20 16:03:12 作者: rapoo

一个最简单的16进制的计算器分析
HEXCALC程序可能是写程序偷懒的经典之作,如程序11-5所示。这个程序完全不呼叫CreateWindow,也不处理WM_PAINT消息,不取得设备内容,也不处理鼠标消息。但是它只用了不到150行的原始码,就构成了一个具有完整键盘和鼠标接口以及10种运算的十六进制计算器。计算器如图11-5所示。
HEXCALC.C


#include <windows.h>
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{

static TCHAR szAppName[] = TEXT ("HexCalc") ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = DLGWINDOWEXTRA ; // Note!

wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (hInstance, szAppName) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
if (!RegisterClass (&wndclass))
{
MessageBox ( NULL, TEXT ("This program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}
hwnd = CreateDialog (hInstance, szAppName, 0, NULL) ;
ShowWindow (hwnd, iCmdShow) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ; }
return msg.wParam ;
}
void ShowNumber (HWND hwnd, UINT iNumber)
{
TCHAR szBuffer[20] ;
wsprintf (szBuffer, TEXT ("%X"), iNumber) ;
SetDlgItemText (hwnd, VK_ESCAPE, szBuffer) ;

}


DWORD CalcIt (UINT iFirstNum, int iOperation, UINT iNum)

{
switch (iOperation)
{
case '=': return iNum ;
case '+': return iFirstNum + iNum ;
case '-': return iFirstNum - iNum ;
case '*': return iFirstNum * iNum ;
case '&': return iFirstNum & iNum ;
case '|': return iFirstNum | iNum ;
case '^': return iFirstNum ^ iNum ;
case '<': return iFirstNum << iNum ;
case '>': return iFirstNum >> iNum ;
case '/': return iNum ? iFirstNum / iNum: MAXDWORD ;
case '%': return iNum ? iFirstNum % iNum: MAXDWORD ;

default : return 0 ;
}
}


LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam)
{

static BOOL bNewNumber = TRUE ;
static int iOperation = '=' ;
static UINT iNumber, iFirstNum ;
HWND hButton ;
switch (message)
{
case WM_KEYDOWN: // left arrow --> backspace


if (wParam != VK_LEFT)
break ;
wParam = VK_BACK ;
case WM_CHAR:
if ((wParam = (WPARAM) CharUpper ((TCHAR *) wParam)) == VK_RETURN)
wParam = '=' ;
if (hButton = GetDlgItem (hwnd, wParam))
{
SendMessage (hButton, BM_SETSTATE, 1, 0) ;
Sleep (100) ;
SendMessage (hButton, BM_SETSTATE, 0, 0) ;
}
else
{
MessageBeep (0) ;
break ;
}
case WM_COMMAND:
SetFocus (hwnd) ;
if (LOWORD (wParam) == VK_BACK)
ShowNumber (hwnd, iNumber /= 16) ; else if (LOWORD (wParam) == VK_ESCAPE)
ShowNumber (hwnd, iNumber = 0) ;
else if (isxdigit (LOWORD (wParam)))
{
if (bNewNumber)
{
iFirstNum = iNumber ;
iNumber = 0 ;
}
bNewNumber = FALSE ;
if (iNumber <= MAXDWORD >> 4)
ShowNumber (hwnd, iNumber = 16 * iNumber + wParam -
(isdigit (wParam) ? '0': 'A' - 10)) ;

else
MessageBeep (0) ;
}

else
{
if (!bNewNumber)
ShowNumber (hwnd, iNumber =
CalcIt (iFirstNum, iOperation, iNumber)) ;
bNewNumber = TRUE ;
iOperation = LOWORD (wParam) ;

}

return 0 ;

case WM_DESTROY:

PostQuitMessage (0) ;

return 0 ;

}

return DefWindowProc (hwnd, message, wParam, lParam) ;

}

这个问题实际就是一个16进制的计算器,我想问的是加入我们按下一个5,他就会显示一个5,但是这个代码让我理解不透,特别的if (iNumber <= MAXDWORD >> 4)
ShowNumber (hwnd, iNumber = 16 * iNumber + wParam -
(isdigit (wParam) ? '0': 'A' - 10)) ;
下面这个为什么还要减去10,减去10怎么会是对的呢,还有if (iNumber <= MAXDWORD >> 4)
可以判断最大只能是8位输出,他是怎么控制的,同行门帮我好好看看,也可以互相交流,我不会让你们白回答的,在下先在这里谢谢了


[解决办法]
再来解释下 为何if (iNumber <= MAXDWORD >> 4)?

MAXDWORD 即为0xFFFFFFFF右移四位则表示 除以16(这个你应该懂把)
所以当前大小必须要小于等于 "MAXDWORD >> 4"的值;
不然你刚输入一个16进制码,则iNumber会乘以16 再加上 这个16进制码 必然超过了 MAXDWORD了;
那也就是溢出了!

读书人网 >C++

热点推荐