One Note Jam

Windows Mobile開発・VS2005のMFC上では、DS_MODALFRAMEスタイルのダイアログは生成できない (2008-07-31)

前回の記事(2008-07-27)にも書いたとおり、開発環境をeVC++4.0(eMbedded Visual C++ 4.0)からVS2005(Visual Studio 2005)に変更した際に、いろいろと細かい点でソースコードの移行に苦しんだわけですが、その中の一つを紹介します。

非常に単純な話で、ダイアログリソースでDS_MODALFRAMEスタイルを指定した場合、CDialog::DoModal()などでのダイアログ生成時に実行時エラーになります。表示されるはずのダイアログが表示されず、見た目上は何も起きないように見えます。eVC++4.0ではこのような現象は起きなかったので、原因がわかるまでは戸惑いました。

MFCのソースを追いかけてみれば一目瞭然。VS2005のMFCでの該当ソース(dlgcore.cpp)は以下のとおり。

        // create modeless dialog
        AfxHookWindowCreate(this);
#ifdef _WIN32_WCE
        int aygshellUIModel = AfxGetAygshellUIModel();
        if ((aygshellUIModel == PocketPC || aygshellUIModel == Smartphone) && (lpDialogTemplate->style & DS_MODALFRAME))
        {
            // Fail DS_MODALFRAME can't be set for Pocket PC and Smartphone
            TRACE(traceAppMsg, 0, _T("ERROR: dialog template has DS_MODALFRAME set, which is not supported for Pocket PC and Smartphone\n"));
            return FALSE;
        }

        // CreateDialogIndirect is a macro, so just the last parameter can't be preprocessed differently
        hWnd = ::CreateDialogIndirect(hInst, lpDialogTemplate,
            pParentWnd->GetSafeHwnd(), AfxDlgProcEx);
#else // _WIN32_WCE
        hWnd = ::CreateDialogIndirect(hInst, lpDialogTemplate,
            pParentWnd->GetSafeHwnd(), AfxDlgProc);
#endif // _WIN32_WCE

これに対して、eVC++4.0のMFCのソースでは以下のようになっています。こちらは、DS_MODALFRAMEスタイルが指定された際にエラーにするのではなく、DS_MODALFRAMEスタイルを除去しているようです。

        // create modeless dialog
        AfxHookWindowCreate(this);

#if defined(_WIN32_WCE_PSPC) && (_WIN32_WCE >= 300)
        if (lpDialogTemplate->style & DS_MODALFRAME)
        {
            LPDLGTEMPLATE lpTemplate = (LPDLGTEMPLATE)lpDialogTemplate;
            DWORD dwResult;
            MEMORY_BASIC_INFORMATION mbiMemory;

            memset (&mbiMemory, 0, sizeof(MEMORY_BASIC_INFORMATION));
            dwResult = VirtualQuery (lpTemplate, &mbiMemory, sizeof(MEMORY_BASIC_INFORMATION));
            if (sizeof(MEMORY_BASIC_INFORMATION) == dwResult)
            {
                if (mbiMemory.Protect == PAGE_READWRITE)
                {
                    lpTemplate->style &= ~DS_MODALFRAME;
                }
                else if (mbiMemory.Protect == PAGE_READONLY)
                {
                    // Mark the dialog template as read-write.
                    VirtualProtect(lpTemplate, sizeof(DLGTEMPLATE), PAGE_READWRITE, &dwResult);
                    lpTemplate->style &= ~DS_MODALFRAME;
                }
            }
        }
#endif

        hWnd = ::CreateDialogIndirect(hInst, lpDialogTemplate,
            pParentWnd->GetSafeHwnd(), WCE_IF(wce_FirstDlgProc, AfxDlgProc));

ところでこのソースコードですが、かなり無理やりにDS_MODALFRAMEスタイルを除去しようとしているコードに見えますが、これって大丈夫なのでしょうか……?

posted at 2008-07-31 | Permalink

「えいご漬けDS風ソフト」未だ完成せず (2008-07-27)

モチベーションを維持するのに一苦労

以前(2008-04-30)開発を始めた「えいご漬けDS風ソフト」ですが、開発に着手してから3ヶ月、ようやく形になってきました。

「えいご漬けDS風ソフト」開発中画面

正直なところ、開発に数ヶ月もかかるような規模のソフトではないのですが、時間が経つにつれて当初の勢いがなくなって、やる気が低下しているために時間がかかっています。当初はゴールデンウィーク中に集中的に開発を進める予定だったのですが、勢いのあるうちにさっさと仕上げないとだめですね……。

なお、開発当初はeVC++4.0(eMbedded Visual C++ 4.0)で開発していたのですが、さすがに古い開発環境なので細かい点でいろいろな問題が出てきたため、VS2005(Visual Studio 2005)に移行することにしました。世間ではとっくに次のバージョンであるVS2008(Visual Studio 2008)がリリースされているわけですが、

  • VS2005では、スマートデバイス開発のためには「Standard Edition」以上が必要
  • しかし、VS2008では「Professional Edition」以上が必要

ということになっていて、かなり高価であるVS2008 Professional Editionには手が出ないため、VS2005 Standard Editionを購入した次第です。また、VS2005もすでに3年近く前の製品であり、後継バージョンであるVS2008が発売された今、Windows XPのように販売終了になる日も近そうなので、移行に踏み切ることにしました。

その際、eVC++4.0からVS2005へのソースコードの移行にもかなり苦労しました(これがやる気をなくす要因のひとつだったわけですが)。結局のところ、VS2005で新たにプロジェクトを作り直して、そこにeVC++4.0用のソースコードを継ぎ足すことでどうにか移行しました。

スクリーンショット撮影にも一苦労

ところで、この「えいご漬けDS風ソフト」のスクリーンショットですが、手書き文字入力のSIP(ソフト入力パネル)を使っている画面を取ろうとして難儀しました。Advanced/W-ZERO3[es]でスクリーンショットを撮影する場合、[Fn]キーを押しながら(テンキー側の)[文字]キーを押すと、画像ファイルがルートフォルダに保存されるわけですが、[Fn]キーを押しても[文字]キーを押してもSIPが閉じてしまうので、SIPが表示されている画面を取ることができません。試行錯誤した結果、スクリーンショットの撮影タイミングが「[文字]キーを離した瞬間」であることがわかったため、以下のような操作でようやく撮影に成功しました。

  1. [Fn]キーを押す(押したままでもよい)
  2. [文字]キーを押したままにする
  3. 画面上の「SIPボタン(メニューバーの中央の部分)」をタップして、SIPを表示させる
  4. 押したままの状態の[文字]キーを離す

一応、備忘録として残しておきます。

posted at 2008-07-27 | Permalink

© 2004-2008 ENDO