📄 winecalc.c
字号:
case VK_DELETE:
calc.next = 1;
calc.buffer[0] = TEXT('\0');
calc_buffer_display(&calc);
return 0;
default:
break;
}
return 0;
case WM_CHAR:
if (debug)
show_debug(&calc, TEXT("Start WM_CHAR"), wParam, lParam);
switch (wParam) {
case TEXT('\x13'): // Ctrl+S Sta Statistics
if (hWndDlgStats) { // Statistics Box already displayed, focus but don't create another one
// SetFocus(hWndDlgStats);
// SendMessage(hWndDlgStats, WM_SETFOCUS, 0, 0);
}
else {
int i;
if (lParam == 1) {
for (i=0;i<4;i++)
EnableWindow((HWND)calc.cb[sta[i]].hBtn, FALSE);
}
else {
for (i=0;i<4;i++)
EnableWindow((HWND)calc.cb[sta[i]].hBtn, TRUE);
hWndDlgStats = CreateDialog( // modeless dialog
calc.hInst, // handle to application instance
TEXT("DLG_STATS"), // identifies dialog box template name
hWnd, // handle to owner window
StatsDlgProc); // pointer to dialog box procedure
if (!hWndDlgStats)
exit(1);
SendMessage(hWndDlgStats, WM_SETFOCUS, 0, 0);
}
}
break;
case TEXT('\x01'): // Ctrl+A Ave Statistics
case TEXT('\x04'): // Ctrl+D s Standard Deviation Statistics
case TEXT('\x14'): // Ctrl+T Sum Statistics
{
int i;
int n;
TCHAR s[CALC_BUF_SIZE];
double val = 0L;
double avg = 0L;
double total = 0L;
double x[1024];
// This is all lame. Here we are querying the list control for items and calculating the total.
// We should have an array of intermediate results to work with to avoid roundoff errors, etc.
n = SendMessage(hWndListBox, LB_GETCOUNT, 0, 0);
for (i=0;i<n;i++) {
SendMessage(hWndListBox, LB_GETTEXT, i, (LPARAM)s);
val = calc_atof(s,calc.numBase);
total += val;
x[i] = val;
}
if (LOWORD(wParam) != TEXT('\x14')) // not sum only
avg = total / n;
if (LOWORD(wParam == TEXT('\x04'))) { // standard deviation is sqrt(sum( xbar - x )^2 / (n-1))
val = 0L;
for (i=0;i<n;i++)
val += pow(x[i] - avg, 2);
if (calc.invMode)
total = sqrt(val / n); // complete population
else
total = sqrt(val / (n - 1)); // sample of population
}
if (LOWORD(wParam) == TEXT('\x01')) // average or mean
total = avg;
calc_ftoa(&calc, total, s);
_tcscpy(calc.buffer, s);
calc_buffer_display(&calc);
}
break;
case TEXT('\x03'): // Ctrl+C Copy
{
int i;
int len;
TCHAR *s;
HGLOBAL hGlobalMemory;
LPTSTR pGlobalMemory;
if (!(len = _tcslen(calc.display)))
return 0;
if (!(s = calc.display))
return 0;
if (s[len - 1] == TEXT('.') || s[len - 1] == TEXT(','))
len--;
if (!(hGlobalMemory = GlobalAlloc(GHND, (len + 1) * sizeof(TCHAR))))
return 0;
if (!(pGlobalMemory = GlobalLock(hGlobalMemory)))
return 0;
for (i = 0; i < len; i++)
*pGlobalMemory++ = *s++;
pGlobalMemory[len - 1] = 0;
GlobalUnlock(hGlobalMemory); // call GetLastError() for exception handling
if (!OpenClipboard(hWnd))
return 0;
if (!EmptyClipboard())
return 0;
if (!SetClipboardData(CF_TTEXT, hGlobalMemory))
return 0;
if (!CloseClipboard())
return 0;
}
break;
case TEXT('\x16'): // Ctrl+V Paste
{
TCHAR *s;
TCHAR c;
int cmd = 0;
size_t size = 0;
size_t i = 0;
HGLOBAL hGlobalMemory;
LPTSTR pGlobalMemory;
if (IsClipboardFormatAvailable(CF_TTEXT)) {
if (!OpenClipboard(hWnd))
return 0;
if (!(hGlobalMemory = GetClipboardData(CF_TTEXT)))
return 0;
if (!(size = GlobalSize(hGlobalMemory)))
return 0;
if (!(s = (TCHAR *)malloc(size)))
return 0;
if (!(pGlobalMemory = GlobalLock(hGlobalMemory)))
return 0;
_tcscpy(s, pGlobalMemory);
GlobalUnlock(hGlobalMemory);
if (!CloseClipboard())
return 0;
// calc paste protocol
//
// :c clear memory WM_CHAR, 0x0c
// :e enable scientific notation WM_CHAR, 'v'
// :m store display in memory WM_CHAR, 0x0d
// :p add display to memory WM_CHAR, 0x10
// :q clear current calculation WM_CHAR, '\x1b'
// :r read memory into display WM_CHAR, 0x12
// \ Dat WM_CHAR, VK_INSERT
//
// parse the pasted data, validate and SendMessage it one character at a time.
// it would appear wincalc does it this way (slow), although very slow appearing on Wine.
while ((c = *s++) && (i++ < size / sizeof(TCHAR))) {
if (c == TEXT(':')) {
cmd = 1;
}
else if (c == TEXT('\\')) {
SendMessage(hWnd, WM_KEYDOWN, VK_INSERT, lParam);
}
else {
if (cmd) {
cmd = 0;
switch(c) {
case TEXT('c'): // clear memory
case TEXT('C'):
SendMessage(hWnd, WM_CHAR, 0x0c, lParam);
break;
case TEXT('e'): // enable scientific notation
case TEXT('E'):
SendMessage(hWnd, WM_CHAR, 'v', lParam);
break;
case TEXT('m'): // store display in memory
case TEXT('M'):
SendMessage(hWnd, WM_CHAR, 0x0d, NUMBER_OF_THE_BEAST);
break;
case TEXT('p'): // add display to memory
case TEXT('P'):
SendMessage(hWnd, WM_CHAR, 0x10, lParam);
break;
case TEXT('q'): // clear current calculation
case TEXT('Q'):
SendMessage(hWnd, WM_CHAR, TEXT('\x1b'), lParam);
break;
case TEXT('r'): // read memory into display
case TEXT('R'):
SendMessage(hWnd, WM_CHAR, 0x12, lParam);
break;
default: // just eat it but complain
MessageBeep(0);
break;
}
}
else {
if ((calc.numBase == NBASE_HEX) &&
((c >= TEXT('0') && c <= TEXT('9')) ||
(c >= TEXT('a') && c <= TEXT('f')) ||
(c >= TEXT('A') && c <= TEXT('F')))) {
SendMessage(hWnd, WM_CHAR, c, lParam);
}
else if ((calc.numBase == NBASE_DECIMAL) &&
(c >= TEXT('0') && c <= TEXT('9'))) {
SendMessage(hWnd, WM_CHAR, c, lParam);
}
else if ((calc.numBase == NBASE_OCTAL) &&
(c >= TEXT('0') && c <= TEXT('7'))) {
SendMessage(hWnd, WM_CHAR, c, lParam);
}
else if ((calc.numBase == NBASE_BINARY) &&
(c == TEXT('0') || c == TEXT('1'))) {
SendMessage(hWnd, WM_CHAR, c, lParam);
}
else if (c == TEXT('.') || c == TEXT(',') ||
c == TEXT('e') || c == TEXT('E') ||
c == TEXT('+') || c == TEXT('-')) {
SendMessage(hWnd, WM_CHAR, c, lParam);
}
else if (c == TEXT(' ') || // eat harmless trash here
c == TEXT(';') ||
c == TEXT(':')) {
; // noop
}
else { // extra spicy trash gets noticed
MessageBeep(0); // uh, beeps can get annoying. maybe rate limit.
}
}
}
}
}
}
break;
default:
{
parse(wParam, lParam);
}
} // switch WM_CHAR
calc_buffer_display(&calc);
return 0;
case WM_COMMAND:
switch(LOWORD(wParam)) {
case IDM_COPY:
SendMessage(hWnd, WM_CHAR, TEXT('\x03'), lParam);
return 0;
case IDM_PASTE:
SendMessage(hWnd, WM_CHAR, TEXT('\x16'), lParam);
return 0;
case IDM_MODE_STANDARD:
if (!calc.sciMode) {
int i;
RECT lpRect;
calc.sciMode = 1;
calc.trigMode = TRIGMODE_DEGREES;
calc.numBase = NBASE_DECIMAL;
EnableWindow(hWnd, FALSE);
for (i=1;i<COUNT_MENUS;i++) {
if (calc.numBase != ID_CALC_NS_DEC) {
CheckMenuItem(menus[i], ID_CALC_NS_HEX, MF_UNCHECKED);
CheckMenuItem(menus[i], ID_CALC_NS_DEC, MF_CHECKED);
CheckMenuItem(menus[i], ID_CALC_NS_OCT, MF_UNCHECKED);
CheckMenuItem(menus[i], ID_CALC_NS_BIN, MF_UNCHECKED);
}
}
for (i=1;i<COUNT_MENUS;i++) {
CheckMenuItem(menus[i], ID_CALC_MS_DEGREES, MF_CHECKED);
CheckMenuItem(menus[i], ID_CALC_MS_RADIANS, MF_UNCHECKED);
CheckMenuItem(menus[i], ID_CALC_MS_GRADS, MF_UNCHECKED);
}
SetMenu(hWnd, menus[MENU_STD]);
// SendMessage(hWnd, WM_SIZE, SIZE_RESTORED, CALC_STANDARD_WIDTH | (CALC_STANDARD_HEIGHT << 8));
GetWindowRect(hWnd, &lpRect);
MoveWindow(hWnd, lpRect.left, lpRect.top, CALC_STANDARD_WIDTH, CALC_STANDARD_HEIGHT, TRUE);
DestroyCalc(&calc);
InitCalc(&calc);
EnableWindow(hWnd, TRUE);
}
return 0;
case IDM_MODE_SCIENTIFIC:
if (calc.sciMode) {
RECT lpRect;
calc.sciMode = 0;
EnableWindow(hWnd, FALSE);
SetMenu(hWnd, menus[MENU_SCIMS]);
GetWindowRect(hWnd, &lpRect);
MoveWindow(hWnd, lpRect.left, lpRect.top, CALC_SCIENTIFIC_WIDTH, CALC_SCIENTIFIC_HEIGHT, TRUE);
DestroyCalc(&calc);
InitCalc(&calc);
if (calc.invMode)
SendMessage(calc.cb[67].hBtn, BM_SETCHECK, TRUE, 0);
if (calc.hypMode)
SendMessage(calc.cb[68].hBtn, BM_SETCHECK, TRUE, 0);
EnableWindow(hWnd, TRUE);
}
return 0;
case IDM_DIGIT_GROUPING:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -