iPhone アプリの状況がうらやましい限り。
んー悔しい。何千万円も儲からなくてもいいんだよ。何千円でもおっけーなんだよ。
Appleの事情にはとんと疎いので、iTunesとかも使ったことないけど、うまいこと課金システムが出来上がってるんだろうな。
触発されたわけではないが、明日のためのその1として、Windows Mobile用のアプリを作成すべく、プロトタイプ的なものを作ってみる。
すこしずつ、野望に近づくのだ!
題材は、インド式計算としてみる。最近とんと計算ができなくなってきたため、通勤時等のエクササイズ用として使えれば幸い。
以下手順、はまりポイントメモ。
1.仕様
計算問題を出題。回答入力。正解、不正解と解法を表示
2.プロジェクトの作成
(1) 新規作成-プロジェクト から、MFCスマートデバイスアプリケーションを選ぶ
MFCを使ってみる。SDKプログラミングはよくわからんのでとっつきやすいかと思い。
(2) ウィザードで、Windows Mobile 6 Standard SDKを選択
自機が、Windows Mobile 6 Standard なので。
おっと、ここにくるまでに、準備が結構必要なので、興味ある方は、こちらを参照。
(3) まずは、感じをつかむためなので、ダイアログベースで
3.画面まわりの実装手順
(1) メニューの追加
はまりその1。
もともと、存在している、IDR_MAINFRAME メニューはいくら修正しても、なにもおこらない。以下の対応をするまで、1時間程度のはまり。
IDR_MENUを追加し、メニューを作成。ダイアログ cpp ファイルの、OnInitDialog 関数内の、dlgCommandBar.InsertMenuBarの引数を変更したら、メニューが表示されるようになった。
BOOL CindcalcDlg::OnInitDialog() { CDialog::OnInitDialog(); // このダイアログのアイコンを設定します。アプリケーションのメイン ウィンドウがダイアログでない場合、 // Framework は、この設定を自動的に行います。 SetIcon(m_hIcon, TRUE); // 大きいアイコンの設定 SetIcon(m_hIcon, FALSE); // 小さいアイコンの設定 if (!m_dlgCommandBar.Create(this) || !m_dlgCommandBar.InsertMenuBar(IDR_MENU /* IDR_MAINFRAME */)) { TRACE0("CommandBar の作成に失敗しました\n"); return FALSE; // 作成できませんでした。 } : |
(2) メニューにイベントを追加する
リソースエディタに戻り、メニューが押下されたときのイベントを以下の手順にて作成する。
・メニューのコンテキストメニューから、イベントハンドラの追加を選択
・イベントハンドラ追加先を選択。ダイアログにしておく。
「追加して編集」で、イベントハンドラを編集できるようになる。
(3) ダイアログ画面の作成
ダイアログエディタで、コントロールをぺたぺたはりつつ、ダイアログのメンバー変数として、コントロールを管理するために、コンテキストメニューから変数の追加を選択する。
変数名を適当につけて、完了すると、ダイアログボックスクラスのメンバー変数としてコントロールが作成される。
(4) Enterキーのハンドリング
はまりその2。というほどでもない。ぐぐったらすぐわかった。
ダイアログベースなので、Enterキーを押すと、画面が閉じてしまうので、CDialog::PreTranslateMessage 関数をオーバーライドして、Enterキー押下時の処理を実装する
BOOL CindcalcDlg::PreTranslateMessage(MSG* pMsg) { // TODO: ここに特定なコードを追加するか、もしくは基本クラスを呼び出してください。 if(pMsg->message == WM_KEYDOWN) { switch(pMsg->wParam) { case VK_RETURN: OnAnswer(); // Enterキー押下で、呼び出す処理。 return TRUE; default: break; } } return CDialog::PreTranslateMessage(pMsg); } |
4. 計算練習クラスの追加
(1) 簡単な練習クラス(普通のC++クラス)を作成して、プロジェクトに追加する。
問題の値から、解法を表示させようかと思っていたが、面倒くさくなったのでやめ。
単純に計算問題を作成するだけのクラス
はまりその3.
まいった。2時間程度はまったのが、Windows Mobile を Visual Studioで開発する場合、time_t 関係の関数が利用できないみたい。
乱数のSeedに現在時間を取得したいだけなのに。以下の青字部分のようにして、何とか動いた。
#include "StdAfx.h" #include "CompPractice.h" CompPractice::CompPractice(void) : m_practice_type(0) , m_len(0) , m_answer(0) , m_ope1(0) , m_ope2(0) { } CompPractice::~CompPractice(void) { } // 練習開始 練習タイプ 1:足し算、2:引き算、3:掛け算 と、桁数を与える int CompPractice::Start(int practice_type, int len) { m_practice_type = practice_type; m_len = len; return 0; } // 次の問題 CString CompPractice::NextPractice(void) { int mn = (int)(pow(10, m_len) - 1.0); SYSTEMTIME st; GetSystemTime(&st); CTime ct = CTime(st); srand((unsigned)ct.GetTime()); m_ope1 = rand() % mn; m_ope2 = rand() % mn; CString ope = _T(""); switch(m_practice_type) { case 1: ope = _T("+"); m_answer = m_ope1 + m_ope2; break; case 2: ope = _T("-"); m_answer = m_ope1 - m_ope2; break; case 3: ope = _T("×"); m_answer = m_ope1 * m_ope2; break; default: break; } CString exp = _T(""); exp.Format(_T("%d %s %d ="), m_ope1, ope, m_ope2); return exp; } // 回答のチェック bool CompPractice::Answer(int ans_num) { return (m_answer == ans_num); } // 正答の取得 int CompPractice::GetAnswer(void) { return m_answer; } |
(2) 計算クラスを呼び出す
先ほどの、ダイアログのイベントハンドラから、上記計算クラスの関数を呼び出す。
MFCのCStringクラスの利用法などもにわかには覚えきれないので、使いそうなのをこちらにまとめておく。
void CindcalcDlg::OnAnswer(void) { // 次の問題 CString str_ans = NULL; CString old_practice = NULL; m_txt_ans.GetWindowTextW(str_ans); m_txt_ans.SetWindowTextW(_T("")); m_lbl_exp.GetWindowTextW(old_practice); int ans = _ttoi(str_ans); bool ret = m_practice->Answer(ans); CString msg = _T(""); msg.Format(_T("【正答】%s %d \r\n【%s】あなたの答え %s") , old_practice , m_practice->GetAnswer() , (ret)?_T("正解"):_T("不正解") , str_ans ); m_lbl_ans.SetWindowTextW(msg); m_lbl_exp.SetWindowTextW(m_practice->NextPractice()); } |
5.動かす
エミュレータだとこんな感じ。実機でもちゃんと動いている感じ。
6.まとめ
また一歩野望に近づいた!
次は、サンプルアプリのリリースバージョンをどうやって作成するか調べる。
※ インストーラの作成へ