Windows Mobile アプリを作ってみる

iPhone アプリの状況がうらやましい限り。

んー悔しい。何千万円も儲からなくてもいいんだよ。何千円でもおっけーなんだよ。

Appleの事情にはとんと疎いので、iTunesとかも使ったことないけど、うまいこと課金システムが出来上がってるんだろうな。

触発されたわけではないが、明日のためのその1として、Windows Mobile用のアプリを作成すべく、プロトタイプ的なものを作ってみる。

すこしずつ、野望に近づくのだ!

題材は、インド式計算としてみる。最近とんと計算ができなくなってきたため、通勤時等のエクササイズ用として使えれば幸い。

以下手順、はまりポイントメモ。

1.仕様

計算問題を出題。回答入力。正解、不正解と解法を表示

2.プロジェクトの作成

(1) 新規作成-プロジェクト から、MFCスマートデバイスアプリケーションを選ぶ

MFCを使ってみる。SDKプログラミングはよくわからんのでとっつきやすいかと思い。

wmapp01

(2) ウィザードで、Windows Mobile 6 Standard  SDKを選択

自機が、Windows Mobile 6 Standard なので。

wmapp02

おっと、ここにくるまでに、準備が結構必要なので、興味ある方は、こちらを参照。

(3) まずは、感じをつかむためなので、ダイアログベースで

wmapp03

3.画面まわりの実装手順

(1) メニューの追加

wmapp_mnu01

はまりその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;      // 作成できませんでした。
    }

                   :

wmapp_mnu03 

(2) メニューにイベントを追加する

リソースエディタに戻り、メニューが押下されたときのイベントを以下の手順にて作成する。

・メニューのコンテキストメニューから、イベントハンドラの追加を選択

wmapp_proc01

・イベントハンドラ追加先を選択。ダイアログにしておく。

「追加して編集」で、イベントハンドラを編集できるようになる。

wmapp_proc02

(3) ダイアログ画面の作成

ダイアログエディタで、コントロールをぺたぺたはりつつ、ダイアログのメンバー変数として、コントロールを管理するために、コンテキストメニューから変数の追加を選択する。

wmapp_proc03

変数名を適当につけて、完了すると、ダイアログボックスクラスのメンバー変数としてコントロールが作成される。

wmapp_proc04

(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.動かす

エミュレータだとこんな感じ。実機でもちゃんと動いている感じ。

wmapp_proc06

6.まとめ

また一歩野望に近づいた!

次は、サンプルアプリのリリースバージョンをどうやって作成するか調べる。

インストーラの作成

Follow me!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です