第53章 超簡単電卓


今回は、超簡単電卓を作ります。
まずは、左の図を見てください。これが今回作る「超簡単電卓」です。 最初に使い方を説明しておきます。

「105+2=」この場合は数式通りに入力すれば答えが得られます。

「10.2/3.14=」小数点の計算も数式通りにボタンを押せばOKです。

「-12*4=」まず12を入力、その後プラスマイナスキー(+/-)を押します。 表示は「-12」となります。あとは数式通り入力します。

「2-(-3)=」「2-」まではその通り入力。次に「3」を入力してプラスマイナスキーを 押します。そして、イコールキーを押せば解答が得られます。

イコールキーを押した後、新たな計算をする場合はそのまま入力を続けます。

「A+B」のAやBを押し間違えたときは「C」ボタンを押します。

「A+B-C*D」などの連続計算はできません。

なにやら前置きが長くなってしまいましたが、上のような仕様の電卓を 作ってみましょう。いわば電卓の原型です。

まず、どのように作ればよいのでしょうか。 上の図を見ると電卓そのものはダイアログボックスのようです。 もちろん、普通の親ウィンドウにボタンをつけてもできますが ダイアログボックスを使うのが簡単そうです。

上の方の四角い欄はエジットボックスのようです。

まず、ボタンを1,2,3という順番でおして、エジットボックスに 「123」と表示させる仕組みを考えてみましょう。

まず、1を押すと「1」と表示させることは簡単そうです。 続けて2を押して「12」と表示させるにはどうしたらよいのでしょうか。 文字列をstr(最初は何も持っていない)とすると1が押されたときに この文字列に「1」を追加します。そして、これをエジットボックスに表示します。 つぎに、2が押されたときにこの文字列に「2」を追加します。 そして、この文字列を表示させます。これで「12」と表示されますね。 後は同じです。文字列strに次々と文字を追加して表示してやればよいのです。

文字列に文字列を追加する関数はstrcat関数です。

次に、演算記号(+-*/)が押されたときはどのような演算をするのかを記憶させます。 そして、次の数値入力に備えて新たな文字列を用意します。 ここで、最初に用意する文字列をstr[2][32]のように配列にしておくと便利です。 演算記号が押される前にはstr[0]に「123」などの文字列を記憶して、 演算記号が押された後にはstr[1]に「456」などの文字列を記憶します。 イコールキーが押されたら、

(str[0]を数値になおしたもの)(演算の種類)(str[1]を数値になおしたもの)

の計算をすればよいことになります。

文字列を数値に直す関数にはatoi, atof, atol関数などがあります。 いずれも、DOSのプログラムを書くときによく使います。

では、具体的にプログラムを作ってみましょう。 まずは、リソースエジタで外観を作ります。 コントロールのIDはリソーススクリプトを参照してください。

/////////////////////////////////////////////////////////// // // Dialog // MYDLG DIALOG DISCARDABLE 0, 0, 119, 161 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION CAPTION "猫でもわかる電卓" FONT 9, "MS Pゴシック" BEGIN DEFPUSHBUTTON "OFF",IDOK,7,7,50,14 PUSHBUTTON "C",IDCANCEL,89,78,16,19 EDITTEXT IDC_EDIT1,7,24,98,17,ES_AUTOHSCROLL PUSHBUTTON "0",IDC_0,13,129,16,19 PUSHBUTTON "1",IDC_1,13,104,16,19 PUSHBUTTON "2",IDC_2,32,104,16,19 PUSHBUTTON "3",IDC_3,51,104,16,19 PUSHBUTTON "4",IDC_4,13,78,16,19 PUSHBUTTON "5",IDC_5,32,78,16,19 PUSHBUTTON "6",IDC_6,51,78,16,19 PUSHBUTTON "7",IDC_7,13,51,16,19 PUSHBUTTON "8",IDC_8,32,51,16,19 PUSHBUTTON "9",IDC_9,51,51,16,19 PUSHBUTTON "+",IDC_PLUS,70,51,16,19 PUSHBUTTON "-",IDC_MINUS,70,78,16,19 PUSHBUTTON "*",IDC_KAKE,70,104,16,19 PUSHBUTTON "/",IDC_WARI,71,129,16,19 PUSHBUTTON "=",IDC_EQUAL,89,51,16,19 PUSHBUTTON "AC",IDC_ALLCLEAR,89,104,16,19 PUSHBUTTON ".",IDC_POINT,50,129,16,19 PUSHBUTTON "+/-",IDC_PLUSMINUS,90,129,16,19 END

自前でリソースを作るときはwindows.hとID定義のヘッダーファイル をインクルードしておきます。ヘッダーファイルには自分で IDの値を定義します。

つぎに、本文(ソース・ファイル)を見てみましょう。

// dentak01.cpp #define STRICT #include <windows.h> #include <windowsx.h> #include <string.h> //memset, strcat, strcpy #include <stdio.h> //sprintf #include <math.h> //atof #include <stdlib.h> //atof #include "resource.h" LRESULT CALLBACK MyDlgProc(HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) { DialogBox(hCurInst, "MYDLG", NULL, (DLGPROC)MyDlgProc); return 0; }

自前でリソーススクリプトを作った人は、resource.hではなく、 自前のヘッダーファイルをインクルードしてください。

普通の?親ウィンドウは作りません。従ってWinMain関数はこれだけです。 当然DialogBox関数の3番目の引数はNULLになります。(親はない)

LRESULT CALLBACK MyDlgProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { static char str[2][32], ans_str[32], tmp[32]; static HWND hEWnd; //エジットボックスのウィンドウハンドル static double ans; enum {plus, minus, kake, wari}; static int op, mode; //op:演算の種類 mode:演算子の前か後ろか switch (msg) { case WM_INITDIALOG: hEWnd = GetDlgItem(hWnd, IDC_EDIT1); Edit_SetText(hEWnd, "0"); return TRUE; case WM_COMMAND: switch (LOWORD(wp)) { case IDOK: EndDialog(hWnd, 0); return TRUE; case IDCANCEL: memset(str[mode], '\0', sizeof(str[mode])); Edit_SetText(hEWnd, str[mode]); return TRUE; case IDC_ALLCLEAR: memset(str, '\0', sizeof(str)); memset(ans_str, '\0', sizeof(ans_str)); mode = 0; Edit_SetText(hEWnd, ans_str); return TRUE; case IDC_POINT: strcat(str[mode], "."); Edit_SetText(hEWnd, str[mode]); return TRUE; case IDC_1: strcat(str[mode], "1"); Edit_SetText(hEWnd, str[mode]); return TRUE; case IDC_2: strcat(str[mode], "2"); Edit_SetText(hEWnd, str[mode]); return TRUE; case IDC_3: strcat(str[mode], "3"); Edit_SetText(hEWnd, str[mode]); return TRUE; case IDC_4: strcat(str[mode], "4"); Edit_SetText(hEWnd, str[mode]); return TRUE; case IDC_5: strcat(str[mode], "5"); Edit_SetText(hEWnd, str[mode]); return TRUE; case IDC_6: strcat(str[mode], "6"); Edit_SetText(hEWnd, str[mode]); return TRUE; case IDC_7: strcat(str[mode], "7"); Edit_SetText(hEWnd, str[mode]); return TRUE; case IDC_8: strcat(str[mode], "8"); Edit_SetText(hEWnd, str[mode]); return TRUE; case IDC_9: strcat(str[mode], "9"); Edit_SetText(hEWnd, str[mode]); return TRUE; case IDC_0: strcat(str[mode], "0"); Edit_SetText(hEWnd, str[mode]); return TRUE; case IDC_PLUS: mode = 1; op = plus; return TRUE; case IDC_MINUS: mode = 1; op = minus; return TRUE; case IDC_KAKE: mode = 1; op = kake; return TRUE; case IDC_WARI: mode = 1; op = wari; return TRUE; case IDC_PLUSMINUS: strcpy(tmp, "-"); strcat(tmp, str[mode]); strcpy(str[mode], tmp); Edit_SetText(hEWnd, str[mode]); return TRUE; case IDC_EQUAL: switch (op) { case plus: ans = atof(str[0]) + atof(str[1]); break; case minus: ans = atof(str[0]) - atof(str[1]); break; case kake: ans = atof(str[0]) * atof(str[1]); break; case wari: ans = atof(str[0]) / atof(str[1]); break; } sprintf(ans_str, "%.10f", ans); Edit_SetText(hEWnd, ans_str); memset(str, '\0', sizeof(str)); mode = 0; return TRUE; } break; } return FALSE; }

ダイアログプロシージャはかなり長いですね。 でも大して難しくありません。

WM_INITDIALOGメッセージが来たら、エジットボックスのウィンドウハンドルを 調べて保存しておきます。そして、0を表示しておきます。

OKボタン(実際の表示はOFFボタンになっている)が押されたら、 ダイアログボックスを終了します。

数値ボタンおよび小数点ボタンが押されたら、文字列str[mode]に どんどん追加していきます。modeは最初は0です。演算記号が押された後は1 となります。

イコールボタンが押されたら、演算の種類(op)によって場合分けします。 opが足し算ならstr[0],str[1]をdoubleに変換して足し算を行います。 そして、その結果を表示します。modeは次の演算に備えて0に戻しておきます。

ざっとこんな感じです。

今回は、簡単な電卓のプログラムをやりました。 いろいろ不満な点がありますね。まず、連続計算ができません。 これは、ちょっと工夫するとできそうです。挑戦してみてください。 それと、キーボードから数値を入力できません。 電卓では、テンキーから数値を入力できるようにした方が便利です。 これも挑戦してみてください。

今回は、Windowsのプログラミングというより DOSのプログラムみたいでしたね。そうなんです、プログラムの 外観を作るのはDOSの時とは全く違う方法ですが、中身(考え方)はDOS のプログラムと全く同じです。DOSのプログラムがすらすら書ける人は Windowsのプログラムでもそう困ることはありません。(筆者は大いに困りましたが・・)


[SDK Index] [総合Index] [Previous Chapter] [Next Chapter]

Update Jul/01/1997 By Y.Kumei
当ホーム・ページの一部または全部を無断で複写、複製、 転載あるいはコンピュータ等のファイルに保存することを禁じます。