2007-07-04

Today画面作成

WM6 SDKのサンプルを見ながら、Today画面用アプリの作成方法を調べていました。
まだ不明確なところがあるのですが、とりあえずメモ代わりにまとめておきます。
 
新しいプロジェクトを作成します。
後でセットアップ用のCABプロジェクトを作らないといけないので、「ソリューションのディレクトリを作成」にチェックしましょう。
 
 
プラットフォームにはWindows Mobile 6を選択します。
 
プロジェクトの設定でアプリケーションの種類をDLLに設定します。
お好みでATL、MFCサポートを追加します。
 
作成されたコード。
#include "stdafx.h"
#include <windows.h>
#include <commctrl.h>

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
                      )
{
    return TRUE;
}
 
リソースを追加します。
自動的にresource.hが作成されます。
 
が、ファイルは作成されるものの どこからも参照されていません。
(しばらく悩みました)
 
手動でstdafx.hにinclude句を追加します。
(ついでにTODAY画面関連のヘッダ?も追加しておきます)
// TODO: プログラムに必要な追加ヘッダーをここで参照してください。
#include "resource.h"
#include <todaycmn.h>
 
DllMainとWndProcを実装します。
DllMainではDLL_PROCESS_ATTACHとDLL_PROCESS_DETACHを処理します。
WndProcではWM_TODAYCUSTOM_QUERYREFRESHCACHE、WM_CREATE、WM_PAINT、WM_DESTROY、WM_ERASEBKGNDを処理します。
WM_CREATEはDefWindowProc任せ、WM_DESTROYはreturn 0するだけ、WM_ERASEBKGNDはサンプルプログラムの丸写しです。
HINSTANCE           g_hInst;
HWND                g_hWnd;

static INT InitializeClasses();

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
      )
{
    switch (ul_reason_for_call) {

        case DLL_PROCESS_ATTACH:
            g_hInst = (HINSTANCE)hModule;

            UnregisterClass((LPCWSTR)LoadString(g_hInst, IDS_APP_NAME, 0, 0), g_hInst);
            InitializeClasses();
            g_hWnd = 0;
            break;

        case DLL_PROCESS_DETACH:
            UnregisterClass((LPCWSTR)LoadString(g_hInst, IDS_APP_NAME, 0, 0), g_hInst);
            g_hInst = NULL;
            break;
    }
    return TRUE;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT uimessage, WPARAM wParam, LPARAM lParam) {

    switch (uimessage) {
        case WM_TODAYCUSTOM_QUERYREFRESHCACHE:
            {
                TODAYLISTITEM   *ptliItem;
                BOOL            bReturn     = FALSE;

                ptliItem = (TODAYLISTITEM*)wParam;
                 if ((NULL == ptliItem) || (WaitForSingleObject(SHELL_API_READY_EVENT, 0) == WAIT_TIMEOUT)) {
                     return FALSE;
                 }
                 
                 if (0 == ptliItem->cyp) {
                     ptliItem->cyp = DRA::SCALEY(20);
                     bReturn = TRUE;
                 }
                 return bReturn;
            }

        case WM_CREATE:
            break;

        case WM_PAINT:
            PAINTSTRUCT     ps;
            RECT            rcWindBounds; 
            RECT            rcMyBounds;
            HDC             hDC;
            COLORREF        crText;

            GetWindowRect(hwnd, &rcWindBounds);
            rcMyBounds.left = 0;
            rcMyBounds.top = DRA::SCALEY(2);
            rcMyBounds.right = rcWindBounds.right - rcWindBounds.left;
            rcMyBounds.bottom = rcWindBounds.bottom - rcWindBounds.top;          
            hDC = BeginPaint(hwnd, &ps);

            SetBkMode(hDC, TRANSPARENT);

            crText = SendMessage(GetParent(hwnd), TODAYM_GETCOLOR, (WPARAM) TODAYCOLOR_TEXT, NULL);
            SetTextColor(hDC, crText);

            DrawText(hDC, (LPCWSTR)LoadString(g_hInst, IDS_MESSAGE, 0, 0), -1, &rcMyBounds, DT_CENTER | DT_VCENTER);

            EndPaint(hwnd, &ps);
            return 0;

        case WM_DESTROY:
            return 0;

        case WM_ERASEBKGND:
            TODAYDRAWWATERMARKINFO dwi;
            dwi.hdc = (HDC)wParam;
            GetClientRect(hwnd, &dwi.rc);
            
            dwi.hwnd = hwnd;
            SendMessage(GetParent(hwnd), TODAYM_DRAWWATERMARK, 0,(LPARAM)&dwi);
            return TRUE;
    }
    return DefWindowProc (hwnd, uimessage, wParam, lParam);
}

INT InitializeClasses()
{
        WNDCLASS         wc; 
        memset(&wc, 0, sizeof(wc));

        wc.style         = 0;                   
        wc.lpfnWndProc   = (WNDPROC)WndProc;
        wc.hInstance     = g_hInst;
        wc.hIcon         = 0;
        wc.hCursor       = 0;
        wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
        wc.lpszClassName = (LPCTSTR)LoadString(g_hInst, IDS_APP_NAME, 0, 0);

        //register our window
        if(!RegisterClass(&wc))
        { 
          return 0 ;
        }

        return 1;
}
 
InitializeCustomItem、CustomItemOptionsDlgProcを実装します。
尚、プロトタイプ宣言はtodaycmn.hで宣言済みです。
(うっかりプロトタイプ宣言を追加してしばらく悩みました)
HWND InitializeCustomItem(TODAYLISTITEM *ptli, HWND hwndParent) 
{
    LPCTSTR appName = (LPCTSTR)LoadString(g_hInst,IDS_APP_NAME, 0, 0);

    g_hWnd = CreateWindow(appName, appName, WS_VISIBLE | WS_CHILD,
        CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, hwndParent, NULL, g_hInst, NULL) ;

    ShowWindow (g_hWnd, SW_SHOWNORMAL);
    UpdateWindow (g_hWnd) ;  

    return g_hWnd;
}

LRESULT WINAPI CustomItemOptionsDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    return FALSE;
}
 
続いてDLLエクスポート用のファイルを作成します。
新しい項目の追加から、カテゴリ「コード」-テンプレート「モジュール定義ファイル(.def)」を選択します。
 
作成された.defファイルにInitializeCustomItem、CustomItemOptionsDlgProcのエントリを追加します。
@240, @241はどうやら固定のようです。
LIBRARY "WMSample03"
EXPORTS
InitializeCustomItem            @240    NONAME
CustomItemOptionsDlgProc        @241    NONAME
 
セットアップ用のCABプロジェクトを作成します。
 
CABプロジェクトを右クリック->プロパティを表示して出力ファイル名を修正しておきます。
 
また、CABプロジェクトのプロパティタブを表示して、Manufacturerに日本語名が使われていれば変更します。
(さもないとビルドエラー「The INF file contains Unicode characters that could not be converted correctly to ANSI」が出ます。)
 
CABプロジェクト右クリック->表示->ファイルシステムと進み、アプリケーションフォルダに対象プロジェクトのプライマリ出力を追加します。
 
CABプロジェクト右クリック->表示->レジストリと進み、レジストリ項目を追加します。  
この状態でソリューションをビルドするとセットアップ用のCABファイルができ、エミュレータ等でもインストールすることができます。
 
ただ、これだとデバッグすることができません。
まずは通常アプリとして作成して、完成してからToday画面に組み込むようにしないといけないのかもしれませんね。
 

0 件のコメント: