Today プラグインサンプルプログラム
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
#analog
#norelated
#contents
* Today プラグインサンプルプログラム [#l3bd18a2]
** 手順 [#ca9d4d47]
基本的には[[Windows Mobileサンプルプログラム]]とプロジェ...
シンボルは後で、defファイルを使ってエクスポートするので、...
#ref(Application.png,left,nowrap,アプリケーションの設定)
これで、DllMainのみのソースが作成されますので、ここに必要...
** シェルからコールされる関数のエクスポート [#cf76846c]
Todayプラグインは、シェルからロードされる時に呼び出される...
まだ設定画面を作るかどうかはわかりませんが、一応、両方定...
まずはソース(DllMainの下にでも)に、以下を追加します。~
HWND APIENTRY InitializeCustomItem( TODAYLISTITEM *ptli,...
{
return NULL;
}
BOOL APIENTRY CustomItemOptionsDlgProc( HWND hDlg, UINT ...
{
return FALSE;
}
TODAYLISTITEMの定義が、デフォルトでは参照できないので、以...
プリコンパイルヘッダ(stdafx.h)の一番下のTODO以下でいいと...
// TODO: プログラムに必要な追加ヘッダーをここで参照して...
#include <todaycmn.h>
InitializeCustomItemは、これから、today画面に表示するWind...
CustomItemOptionsDlgProcは、設定ダイアログを作った場合、...
ダイアログプロシージャは、メッセージを処理した場合にTRUE...
次に、追加した関数を、DLLの外から見えるようにしてやる必要...
しかも、これらの関数は、外からコールする際の関数の番号(序...
このために、defファイルを使用したエクスポートの設定をして...
まずは、ソリューションエクスプローラの追加したい箇所で右...
ソースにでも追加しておきますかね。~
#ref(adddef.png,left,nowrap,新しい項目)
で、コードのモジュール定義ファイルを選んで、適当に名前を...
#ref(adddef2.png,left,nowrap,新しい項目の追加)
出来たdefファイルには、ライブラリ名だけが記述されています...
LIBRARY "todaytest"
EXPORTS
InitializeCustomItem @240
CustomItemOptionsDlgProc @241
上記手順で作れば、自動的にプロジェクトのプロパティに、モ...
手動でファイルを追加した場合は、モジュール定義ファイルの...
#ref(moduledef.png,left,nowrap,モジュール定義ファイル)
この状態でビルドしてやれば、dllとexp(エクスポートファイル...
とはいえ、シェルはダイナミックにdllをロードして、序数指定...
** ウィンドウクラス登録 [#ke025966]
InitializeCustomItemで、表示するWindowを作成するために、...
登録は普通のWin32プログラムとほとんど変わらないのですが、...
InitializeCustomItem内でウィンドウクラスの登録を行なおう...
これを防ぐために、DllMainで、プロセスにアタッチされた時に...
ウィンドウクラスに登録する名前とかは、定数でもいいんです...
どうせ後で、他のことにもリソースは使いそうなので、リソー...
というわけで、先ほどと同じように、リソースに追加します。~
#ref(addres.png,left,nowrap,新しい項目)
で、リソースのリソースファイルを選んで、適当に名前を入力...
#ref(addres2.png,left,nowrap,新しい項目の追加)
リソースを追加すると、リソースのIDが記述されるresource.h...
使用するソースでは、こいつをincludeしてやる必要があります...
#include "resource.h"
ちなみに、DllMainの前にincludeされているwindows.hとcommct...
というか、windows.hは既にstdafx.h内に記述されているので、...
基本的に変更されることがないヘッダファイルは、プリコンパ...
次に、リソースファイルを作ったので、ここにストリングテー...
右クリックでリソースの追加を選んで……。~
#ref(addstrtbl.png,left,nowrap,リソースの追加)
String Tableを選択して、新規作成。~
#ref(addstrtbl2.png,left,nowrap,リソースの追加)
作成できたら、ウィンドウクラス名を登録するIDと文字列を入...
#ref(addstrtbl3.png,left,nowrap,リソースの追加)
ストリングテーブルの他に、ウィンドウクラスには、そのウィ...
とりあえず、何もしない(デフォルトの処理のみを行う)ウィン...
LRESULT CALLBACK WndProc( HWND hwnd, UINT uiMsg, WPARAM ...
{
return ::DefWindowProc( hwnd, uiMsg, wParam, lParam );
}
これで、下準備は出来ました。~
適当なクラスでも作って、インスタンスハンドルを保持したり...
というわけで、出来たクラスと使用側のDllMainがこんな感じで...
まだ動かして試すところまでいっていないので、ちゃんと動く...
#ref(ウィンドウクラスソース.zip,left,nowrap,ウィンドウク...
使用APIはLoadStringとRegisterClassとUnregisterClassです。~
LoadStringは、WindowsMobile版では、文字列バッファにNULLを...
RegisterClassは、通常のWin32プログラムとは違って、結構意...
まぁ、必要なものだけ設定という感じで。~
** ウィンドウ作成 [#m36b94a0]
InitializeCustomItemが呼ばれたときにWindowを作成しますが...
HWND APIENTRY InitializeCustomItem( TODAYLISTITEM *ptli,...
hwndParentの方はまぁ、親Windowのハンドルということで、Tod...
自分が作成するWindowは、これの子Windowとして作成すると。~
リモートスパイを立ち上げて、Window構成を見てみると、Deskt...
しかし、Todayプラグインは時計を含めて4つ表示しているはず...
Todayプラグインの情報が入っているレジストリの場所「HKEY_L...
#ref(todayinfo.png,left,nowrap,Today関連情報)
もう一つの引数は、TODAYLISTITEMという構造体のポインタです...
この構造体は、以下のようなメンバとなっているらしいですが...
埋められているってのは、基本的にはレジストリに書かれてい...
レジストリ内容については、また後日。~
typedef struct _TODAYLISTITEM {
TCHAR szName[MAX_ITEMNAME];
TODAYLISTITEMTYPE tlit;
DWORD dwOrder;
DWORD cyp;
BOOL fEnabled;
BOOL fOptions;
DWORD grfFlags;
TCHAR szDLLPath[MAX_PATH];
HINSTANCE hinstDLL;
HWND hwndCustom;
BOOL fSizeOnDraw;
BYTE * prgbCachedData;
DWORD cbCachedData;
} TODAYLISTITEMTYPE;
fEnabledがFALSEだったらNULLを返し、そうでない場合は、適当...
ウィンドウ作成は、以下のような感じでしょうか。~
m_hwnd = ::CreateWindow( lpCApp->getClassName(), lpCApp...
WS_VISIBLE | WS_CHILD, CW_USEDEFAULT, CW_USEDEFAULT, C...
hwndParent, NULL, lpCApp->getInstance(), ( LPVOID )thi...
ウィンドウタイトルはとりあえずクラス名と同じにしておくと...
位置とサイズが全部CW_USEDEFAULTになっていますが、ウィンド...
(高さだけは、後で書くWM_TODAYCUSTOM_QUERYREFRESHCACHEメッ...
あとは、パラメータとしてウィンドウ管理クラスのポインタを...
ウィンドウの管理クラスポインタをグローバルにすると、上位...
デフォルトのウィンドウメッセージは、<windowsx.h>をinclude...
。~
stdafx.hの、windows.hのincludeの後にでも追加しておくとい...
あらかじめ、windowsx.h内の定義に従って、WM_CREATEとWM_DES...
BOOL Today_OnCreate( HWND hwnd, LPCREATESTRUCT lpCreateS...
void Today_OnDestroy( HWND hwnd ); // WM_DESTROY処理
ウィンドウプロシージャの記述を、以下のように。~
LRESULT CALLBACK WndProc( HWND hwnd, UINT uiMsg, WPARAM ...
{
switch( uiMsg ){
HANDLE_MSG( hwnd, WM_CREATE, Today_OnCreate );
HANDLE_MSG( hwnd, WM_DESTROY, Today_OnDestroy );
}
return ::DefWindowProc( hwnd, uiMsg, wParam, lParam );
}
実際の処理は、これでいいかな……?~
BOOL Today_OnCreate( HWND hwnd, LPCREATESTRUCT lpCreateS...
{
LPCTodayWnd lpCTodayWnd = ( LPCTodayWnd )lpCreateStruct...
if( NULL == lpCTodayWnd ){
return FALSE;
}
if( !::SetWindowLong( hwnd, GWL_USERDATA, ( LONG )lpCTo...
return FALSE;
}
return TRUE;
}
void Today_OnDestroy( HWND hwnd )
{
LPCTodayWnd lpCTodayWnd = NULL; // Todayウィンドウクラス
lpCTodayWnd = ( LPCTodayWnd )::GetWindowLong( hwnd, GWL...
if( NULL != lpCTodayWnd ){
::SetWindowLong( hwnd, GWL_USERDATA, NULL );
delete lpCTodayWnd;
lpCTodayWnd = NULL;
}
}
さて、作ったウィンドウを表示させるには、あと一つやらなけ...
上でちょっと書きましたが、このアイテムを表示する高さを、W...
WM_TODAYCUSTOM_QUERYREFRESHCACHE
wParam = (WPARAM) lptli;
lParam = (LPARAM) res;
このメッセージは、WPARAMとして、TODAYLISTITEM構造体のポイ...
InitializeCustomItemの時に出てきたやつですね。~
このメンバの中に、cypというものがあり、これはアイテムのピ...
この値の初期値は0ですので、0であればアイテムの高さを変え...
初期値でない場合にも、アイテムの高さを変更する必要があれ...
高さを変更しない場合には、FALSEを返せばいいようです。~
あと、WindowsMobileSDKのTodayプラグインサンプルを見ると、...
これについては、情報が少なく、どういう意図で行われている...
では実際のソース。~
まず、WM_TODAYCUSTOM_QUERYREFRESHCACHEメッセージをハンド...
このあたりのメッセージは、windowsx.hでは定義されていない...
/* BOOL Cls_OnTCQueryRefreshCache(HWND hwnd, TODAYLISTIT...
#define HANDLE_WM_TODAYCUSTOM_QUERYREFRESHCACHE(hwnd, wP...
((fn)((hwnd), (TODAYLISTITEM*)(wParam)))
#define FORWARD_WM_TODAYCUSTOM_QUERYREFRESHCACHE(hwnd, l...
(BOOL)(DWORD)(fn)((hwnd), WM_TODAYCUSTOM_QUERYREFRESHCA...
ソースの方にプロトタイプも追加して……。~
BOOL Today_OnTCQueryRefreshCache( HWND hwnd, TODAYLISTIT...
ウィンドウプロシージャにメッセージのハンドリングを追加し...
LRESULT CALLBACK WndProc( HWND hwnd, UINT uiMsg, WPARAM ...
{
switch( uiMsg ){
HANDLE_MSG( hwnd, WM_CREATE, Today_OnCreate );
HANDLE_MSG( hwnd, WM_DESTROY, Today_OnDestroy );
HANDLE_MSG( hwnd, WM_TODAYCUSTOM_QUERYREFRESHCACHE, To...
}
return ::DefWindowProc( hwnd, uiMsg, wParam, lParam );
}
実際の処理は以下のように。~
BOOL Today_OnTCQueryRefreshCache( HWND hwnd, TODAYLISTIT...
{
if(( NULL == lptli ) || ( WAIT_TIMEOUT == ::WaitForSing...
return FALSE;
}
if( 0 == lptli->cyp ){
lptli->cyp = 40;
return TRUE;
}
return FALSE;
}
今回は暫定的に、アイテムの高さを40ピクセルに指定していま...
ここまでのソースは、配置の説明の後につけておきます。~
** 配置 [#wecf9d0f]
さて、作ったソフトは、実行する前にインストールの必要があ...
なのでまず、インストール用のCABファイルを作成しましょう。~
一度インストールしてしまった後は、基本的にはdllを差し替え...
というわけで、ソリューションに新規プロジェクトを追加しま...
#ref(newprj.png,left,nowrap,新規プロジェクト)
「セットアップと配置」から、「スマートデバイスCABプロジェ...
#ref(newprjcab.png,left,nowrap,スマートデバイスCABプロジ...
プロジェクトを選択した状態で、プロパティウィンドウを開き...
#ref(cabproperty.png,left,nowrap,CABプロジェクトプロパティ)
プロジェクトの右クリックメニューからのプロパティも開いて...
Debug構成だけじゃなく、Release構成も、変更が必要であれば...
#ref(cabproperty2.png,left,nowrap,CABプロジェクトプロパテ...
#ref(cabproperty3.png,left,nowrap,CABプロジェクトプロパテ...
そして、作成したDLLを、CABに含めるように設定します。~
プロジェクトの右クリックメニューから、「追加」の「プロジ...
#ref(addprj.png,left,nowrap,プロジェクト出力追加)
DLL出力プロジェクトの、プライマリ出力を選択します。~
#ref(primary.png,left,nowrap,プライマリ出力)
これで、出力されたDLLがCABに含まれます。~
プライマリ出力は、「アプリケーションフォルダ」内に配置さ...
他に、「プログラムファイルフォルダ」というのがファイルシ...
他に、マクロ文字列は以下のような場所を指しているようです...
%CE1% \Program Files
%CE2% \Windows
%CE4% \Windows\StartUp
%CE5% \My Documents
%CE8% \Program Files\Games
%CE11% \Windows\Start Menu\Programs
%CE14% \Windows\Start Menu\Programs\Games
%CE15% \Windows\Fonts
%CE17% \Windows\Start Menu
そうそう、このままではスマートデバイスCABプロジェクトのビ...
こちらも、Debug構成だけじゃなく、Release構成も忘れずに。~
#ref(commgr.png,left,nowrap,構成マネージャ)
#ref(commgr2.png,left,nowrap,構成マネージャ)
最後に、インストール時に登録するレジストリの設定をしまし...
プロジェクトから、レジストリを開きます。~
#ref(prjreg.png,left,nowrap,レジストリ)
HKEY_LOCAL_MACHINE以下にキーを追加していき、「HKEY_LOCAL_...
#ref(prjreg2.png,left,nowrap,レジストリ)
そしてこの中に、以下の値を設定する必要があります。~
|Type|DWORD|このアイテムのタイプを指定します|
|Enabled|DWORD|このアイテムの有効/無効を指定します|
|Options|DWORD|このアイテムが設定ダイアログを持つかどうか...
|DLL|文字列|DLLが格納されている位置を指定します|
|Selectability|DWORD|このアイテムの選択方式を指定します|
Typeは通常、4(カスタムプラグイン)を指定しておけばよいです...
0はオーナー情報、1は予定、2はメール、3は仕事を表すようで...
Enabledは、インストール直後に表示させたくなければ0にして...
ユーザーが設定からチェックを入れれば表示されるようになり...
Optionsは、設定ダイアログを持つ場合は1にする必要がありま...
今回はまだ、CustomItemOptionsDlgProcの中身を実装していな...
DLLは、そのまんま、DLLのパスを指定します。~
今回の例では、「%InstallDir%\todaytest.dll」を指定すれば...
Selectabilityは、そのアイテムを選択できるかどうか、選択で...
このあたりの動作はまだ決めていないので、今回は0を指定して...
#ref(prjreg3.png,left,nowrap,レジストリ)
というわけで、ここまでできたらビルドしてみましょう。~
CABファイルが作成されているはずです。~
出来ていたら、ActiveSync経由で実機の適当な場所に置き、実...
#ref(install.png,left,nowrap,インストール)
インストールが終了したら、ActiveSyncのエクスプローラから...
実機のエクスプローラだと、デフォではdllが表示されない上に...
確認できたら、レジストリにも正しく登録されているか、リモ...
#ref(install2.png,left,nowrap,インストール)
ここまでできたら、実際にプラグインを動かせますが、毎回ソ...
なので、インストール先のdllを、VCから直接書き換えられるよ...
DLLのプロジェクトのプロパティを開き、構成プロパティの「配...
そして、配置デバイスを「Windows Mobile 6 Professional Dev...
#ref(deploy.png,left,nowrap,配置デバイス)
プログラムをビルド後、メニューからソリューションの配置(プ...
(おそらく、使用中だとダメだと思うので、書き換え時はToday...
#ref(deploy2.png,left,nowrap,ソリューション/プロジェクト...
以上で、配置については終了です。~
ここまでのソリューション、プロジェクトとソースは、こんな...
ウィンドウクラスの時のソースとはちょっと変わってるところ...
#ref(ウィンドウ表示ソース.zip,left,nowrap,ウィンドウ表示...
これを実際に動かしてみると、表示は下図のようになります。~
#ref(sample.png,left,nowrap,サンプル表示)
Optionsを無効にしているので、設定ボタンもちゃんと無効にな...
Today画面で黒く表示されている部分が、今回作成したアイテム...
黒いのは、ウィンドウクラスの設定時に、GetStockObject( BLA...
WM_ERASEBKGNDでクリアされた背景が表示されている状態です。~
今後は、このメッセージを処理して、壁紙を透かして表示する...
** デバッグ [#dfa29a6a]
基本的には、上記の配置を使って、以下のような順番でデバッ...
プラグイン無効状態→配置→プロセス(shell32.exe)にアタッチ→...
まず、ActiveSyncでPCと実機を繋ぎ、プラグインは無効状態に...
ソースをビルドして前述の手順で配置したら、デバッグまたは...
#ref(attach.png,left,nowrap,プロセスにアタッチ)
トランスポートをスマートデバイスにして、修飾子の参照から...
エミュレータ上でデバッグする場合は、そのエミュレータを選...
すると、接続が行われ、現在動いているプロセスの一覧が表示...
#ref(attach2.png,left,nowrap,プロセスにアタッチ)
すると、デバッガが起動しますので、DLL_PROCESS_ATTACHの処...
この時点では、まだshell32.exeが自分のDLLをロードしていな...
この状態で、実機のTodayの設定を開いてアイテムタブを押すと...
そのままステップ実行等が可能ですので、リソースのロード、...
一通りアタッチの処理をデバッグしたら、再度実行します。~
自分のアイテムを有効にして、OKを押してみましょう。~
ここからは私の環境だけかもしれませんが、ブレークポイント...
ブレークポイントのリストを見ると、ブレークポイント自体は...
原因はよくわかっていませんが、shell32.exeがDLLをロードす...
動作が安定してからブレークポイントを置くと、ちゃんと捕ま...
しかしこのままでは、起動時のInitializeCustomItemのデバッ...
というわけで、苦肉の策。~
起動直後のデバッグをしたい場合は、InitializeCustomItemの...
HWND APIENTRY InitializeCustomItem( TODAYLISTITEM *ptli,...
{
LPCTodayWnd lpCTodayWnd = NULL; // Todayウィンドウクラス
::Sleep( 10000 );
if( FALSE == ptli->fEnabled || NULL == g_lpCApp ){
return NULL;
}
上の例では10000msで10秒Sleepさせています。~
Sleepの次の行にブレークポイントを置き、ブレークポイントが...
10秒あれば、その間に安定すると思いますので、置き直せばち...
ウィンドウメッセージは、CreateWindow内でのWM_CREATE発行が...
というわけで、一通り作って動作、デバッグまでの流れを書い...
ひとまず一旦ここで区切って、次回以降、作り込み部分を書い...
終了行:
#analog
#norelated
#contents
* Today プラグインサンプルプログラム [#l3bd18a2]
** 手順 [#ca9d4d47]
基本的には[[Windows Mobileサンプルプログラム]]とプロジェ...
シンボルは後で、defファイルを使ってエクスポートするので、...
#ref(Application.png,left,nowrap,アプリケーションの設定)
これで、DllMainのみのソースが作成されますので、ここに必要...
** シェルからコールされる関数のエクスポート [#cf76846c]
Todayプラグインは、シェルからロードされる時に呼び出される...
まだ設定画面を作るかどうかはわかりませんが、一応、両方定...
まずはソース(DllMainの下にでも)に、以下を追加します。~
HWND APIENTRY InitializeCustomItem( TODAYLISTITEM *ptli,...
{
return NULL;
}
BOOL APIENTRY CustomItemOptionsDlgProc( HWND hDlg, UINT ...
{
return FALSE;
}
TODAYLISTITEMの定義が、デフォルトでは参照できないので、以...
プリコンパイルヘッダ(stdafx.h)の一番下のTODO以下でいいと...
// TODO: プログラムに必要な追加ヘッダーをここで参照して...
#include <todaycmn.h>
InitializeCustomItemは、これから、today画面に表示するWind...
CustomItemOptionsDlgProcは、設定ダイアログを作った場合、...
ダイアログプロシージャは、メッセージを処理した場合にTRUE...
次に、追加した関数を、DLLの外から見えるようにしてやる必要...
しかも、これらの関数は、外からコールする際の関数の番号(序...
このために、defファイルを使用したエクスポートの設定をして...
まずは、ソリューションエクスプローラの追加したい箇所で右...
ソースにでも追加しておきますかね。~
#ref(adddef.png,left,nowrap,新しい項目)
で、コードのモジュール定義ファイルを選んで、適当に名前を...
#ref(adddef2.png,left,nowrap,新しい項目の追加)
出来たdefファイルには、ライブラリ名だけが記述されています...
LIBRARY "todaytest"
EXPORTS
InitializeCustomItem @240
CustomItemOptionsDlgProc @241
上記手順で作れば、自動的にプロジェクトのプロパティに、モ...
手動でファイルを追加した場合は、モジュール定義ファイルの...
#ref(moduledef.png,left,nowrap,モジュール定義ファイル)
この状態でビルドしてやれば、dllとexp(エクスポートファイル...
とはいえ、シェルはダイナミックにdllをロードして、序数指定...
** ウィンドウクラス登録 [#ke025966]
InitializeCustomItemで、表示するWindowを作成するために、...
登録は普通のWin32プログラムとほとんど変わらないのですが、...
InitializeCustomItem内でウィンドウクラスの登録を行なおう...
これを防ぐために、DllMainで、プロセスにアタッチされた時に...
ウィンドウクラスに登録する名前とかは、定数でもいいんです...
どうせ後で、他のことにもリソースは使いそうなので、リソー...
というわけで、先ほどと同じように、リソースに追加します。~
#ref(addres.png,left,nowrap,新しい項目)
で、リソースのリソースファイルを選んで、適当に名前を入力...
#ref(addres2.png,left,nowrap,新しい項目の追加)
リソースを追加すると、リソースのIDが記述されるresource.h...
使用するソースでは、こいつをincludeしてやる必要があります...
#include "resource.h"
ちなみに、DllMainの前にincludeされているwindows.hとcommct...
というか、windows.hは既にstdafx.h内に記述されているので、...
基本的に変更されることがないヘッダファイルは、プリコンパ...
次に、リソースファイルを作ったので、ここにストリングテー...
右クリックでリソースの追加を選んで……。~
#ref(addstrtbl.png,left,nowrap,リソースの追加)
String Tableを選択して、新規作成。~
#ref(addstrtbl2.png,left,nowrap,リソースの追加)
作成できたら、ウィンドウクラス名を登録するIDと文字列を入...
#ref(addstrtbl3.png,left,nowrap,リソースの追加)
ストリングテーブルの他に、ウィンドウクラスには、そのウィ...
とりあえず、何もしない(デフォルトの処理のみを行う)ウィン...
LRESULT CALLBACK WndProc( HWND hwnd, UINT uiMsg, WPARAM ...
{
return ::DefWindowProc( hwnd, uiMsg, wParam, lParam );
}
これで、下準備は出来ました。~
適当なクラスでも作って、インスタンスハンドルを保持したり...
というわけで、出来たクラスと使用側のDllMainがこんな感じで...
まだ動かして試すところまでいっていないので、ちゃんと動く...
#ref(ウィンドウクラスソース.zip,left,nowrap,ウィンドウク...
使用APIはLoadStringとRegisterClassとUnregisterClassです。~
LoadStringは、WindowsMobile版では、文字列バッファにNULLを...
RegisterClassは、通常のWin32プログラムとは違って、結構意...
まぁ、必要なものだけ設定という感じで。~
** ウィンドウ作成 [#m36b94a0]
InitializeCustomItemが呼ばれたときにWindowを作成しますが...
HWND APIENTRY InitializeCustomItem( TODAYLISTITEM *ptli,...
hwndParentの方はまぁ、親Windowのハンドルということで、Tod...
自分が作成するWindowは、これの子Windowとして作成すると。~
リモートスパイを立ち上げて、Window構成を見てみると、Deskt...
しかし、Todayプラグインは時計を含めて4つ表示しているはず...
Todayプラグインの情報が入っているレジストリの場所「HKEY_L...
#ref(todayinfo.png,left,nowrap,Today関連情報)
もう一つの引数は、TODAYLISTITEMという構造体のポインタです...
この構造体は、以下のようなメンバとなっているらしいですが...
埋められているってのは、基本的にはレジストリに書かれてい...
レジストリ内容については、また後日。~
typedef struct _TODAYLISTITEM {
TCHAR szName[MAX_ITEMNAME];
TODAYLISTITEMTYPE tlit;
DWORD dwOrder;
DWORD cyp;
BOOL fEnabled;
BOOL fOptions;
DWORD grfFlags;
TCHAR szDLLPath[MAX_PATH];
HINSTANCE hinstDLL;
HWND hwndCustom;
BOOL fSizeOnDraw;
BYTE * prgbCachedData;
DWORD cbCachedData;
} TODAYLISTITEMTYPE;
fEnabledがFALSEだったらNULLを返し、そうでない場合は、適当...
ウィンドウ作成は、以下のような感じでしょうか。~
m_hwnd = ::CreateWindow( lpCApp->getClassName(), lpCApp...
WS_VISIBLE | WS_CHILD, CW_USEDEFAULT, CW_USEDEFAULT, C...
hwndParent, NULL, lpCApp->getInstance(), ( LPVOID )thi...
ウィンドウタイトルはとりあえずクラス名と同じにしておくと...
位置とサイズが全部CW_USEDEFAULTになっていますが、ウィンド...
(高さだけは、後で書くWM_TODAYCUSTOM_QUERYREFRESHCACHEメッ...
あとは、パラメータとしてウィンドウ管理クラスのポインタを...
ウィンドウの管理クラスポインタをグローバルにすると、上位...
デフォルトのウィンドウメッセージは、<windowsx.h>をinclude...
。~
stdafx.hの、windows.hのincludeの後にでも追加しておくとい...
あらかじめ、windowsx.h内の定義に従って、WM_CREATEとWM_DES...
BOOL Today_OnCreate( HWND hwnd, LPCREATESTRUCT lpCreateS...
void Today_OnDestroy( HWND hwnd ); // WM_DESTROY処理
ウィンドウプロシージャの記述を、以下のように。~
LRESULT CALLBACK WndProc( HWND hwnd, UINT uiMsg, WPARAM ...
{
switch( uiMsg ){
HANDLE_MSG( hwnd, WM_CREATE, Today_OnCreate );
HANDLE_MSG( hwnd, WM_DESTROY, Today_OnDestroy );
}
return ::DefWindowProc( hwnd, uiMsg, wParam, lParam );
}
実際の処理は、これでいいかな……?~
BOOL Today_OnCreate( HWND hwnd, LPCREATESTRUCT lpCreateS...
{
LPCTodayWnd lpCTodayWnd = ( LPCTodayWnd )lpCreateStruct...
if( NULL == lpCTodayWnd ){
return FALSE;
}
if( !::SetWindowLong( hwnd, GWL_USERDATA, ( LONG )lpCTo...
return FALSE;
}
return TRUE;
}
void Today_OnDestroy( HWND hwnd )
{
LPCTodayWnd lpCTodayWnd = NULL; // Todayウィンドウクラス
lpCTodayWnd = ( LPCTodayWnd )::GetWindowLong( hwnd, GWL...
if( NULL != lpCTodayWnd ){
::SetWindowLong( hwnd, GWL_USERDATA, NULL );
delete lpCTodayWnd;
lpCTodayWnd = NULL;
}
}
さて、作ったウィンドウを表示させるには、あと一つやらなけ...
上でちょっと書きましたが、このアイテムを表示する高さを、W...
WM_TODAYCUSTOM_QUERYREFRESHCACHE
wParam = (WPARAM) lptli;
lParam = (LPARAM) res;
このメッセージは、WPARAMとして、TODAYLISTITEM構造体のポイ...
InitializeCustomItemの時に出てきたやつですね。~
このメンバの中に、cypというものがあり、これはアイテムのピ...
この値の初期値は0ですので、0であればアイテムの高さを変え...
初期値でない場合にも、アイテムの高さを変更する必要があれ...
高さを変更しない場合には、FALSEを返せばいいようです。~
あと、WindowsMobileSDKのTodayプラグインサンプルを見ると、...
これについては、情報が少なく、どういう意図で行われている...
では実際のソース。~
まず、WM_TODAYCUSTOM_QUERYREFRESHCACHEメッセージをハンド...
このあたりのメッセージは、windowsx.hでは定義されていない...
/* BOOL Cls_OnTCQueryRefreshCache(HWND hwnd, TODAYLISTIT...
#define HANDLE_WM_TODAYCUSTOM_QUERYREFRESHCACHE(hwnd, wP...
((fn)((hwnd), (TODAYLISTITEM*)(wParam)))
#define FORWARD_WM_TODAYCUSTOM_QUERYREFRESHCACHE(hwnd, l...
(BOOL)(DWORD)(fn)((hwnd), WM_TODAYCUSTOM_QUERYREFRESHCA...
ソースの方にプロトタイプも追加して……。~
BOOL Today_OnTCQueryRefreshCache( HWND hwnd, TODAYLISTIT...
ウィンドウプロシージャにメッセージのハンドリングを追加し...
LRESULT CALLBACK WndProc( HWND hwnd, UINT uiMsg, WPARAM ...
{
switch( uiMsg ){
HANDLE_MSG( hwnd, WM_CREATE, Today_OnCreate );
HANDLE_MSG( hwnd, WM_DESTROY, Today_OnDestroy );
HANDLE_MSG( hwnd, WM_TODAYCUSTOM_QUERYREFRESHCACHE, To...
}
return ::DefWindowProc( hwnd, uiMsg, wParam, lParam );
}
実際の処理は以下のように。~
BOOL Today_OnTCQueryRefreshCache( HWND hwnd, TODAYLISTIT...
{
if(( NULL == lptli ) || ( WAIT_TIMEOUT == ::WaitForSing...
return FALSE;
}
if( 0 == lptli->cyp ){
lptli->cyp = 40;
return TRUE;
}
return FALSE;
}
今回は暫定的に、アイテムの高さを40ピクセルに指定していま...
ここまでのソースは、配置の説明の後につけておきます。~
** 配置 [#wecf9d0f]
さて、作ったソフトは、実行する前にインストールの必要があ...
なのでまず、インストール用のCABファイルを作成しましょう。~
一度インストールしてしまった後は、基本的にはdllを差し替え...
というわけで、ソリューションに新規プロジェクトを追加しま...
#ref(newprj.png,left,nowrap,新規プロジェクト)
「セットアップと配置」から、「スマートデバイスCABプロジェ...
#ref(newprjcab.png,left,nowrap,スマートデバイスCABプロジ...
プロジェクトを選択した状態で、プロパティウィンドウを開き...
#ref(cabproperty.png,left,nowrap,CABプロジェクトプロパティ)
プロジェクトの右クリックメニューからのプロパティも開いて...
Debug構成だけじゃなく、Release構成も、変更が必要であれば...
#ref(cabproperty2.png,left,nowrap,CABプロジェクトプロパテ...
#ref(cabproperty3.png,left,nowrap,CABプロジェクトプロパテ...
そして、作成したDLLを、CABに含めるように設定します。~
プロジェクトの右クリックメニューから、「追加」の「プロジ...
#ref(addprj.png,left,nowrap,プロジェクト出力追加)
DLL出力プロジェクトの、プライマリ出力を選択します。~
#ref(primary.png,left,nowrap,プライマリ出力)
これで、出力されたDLLがCABに含まれます。~
プライマリ出力は、「アプリケーションフォルダ」内に配置さ...
他に、「プログラムファイルフォルダ」というのがファイルシ...
他に、マクロ文字列は以下のような場所を指しているようです...
%CE1% \Program Files
%CE2% \Windows
%CE4% \Windows\StartUp
%CE5% \My Documents
%CE8% \Program Files\Games
%CE11% \Windows\Start Menu\Programs
%CE14% \Windows\Start Menu\Programs\Games
%CE15% \Windows\Fonts
%CE17% \Windows\Start Menu
そうそう、このままではスマートデバイスCABプロジェクトのビ...
こちらも、Debug構成だけじゃなく、Release構成も忘れずに。~
#ref(commgr.png,left,nowrap,構成マネージャ)
#ref(commgr2.png,left,nowrap,構成マネージャ)
最後に、インストール時に登録するレジストリの設定をしまし...
プロジェクトから、レジストリを開きます。~
#ref(prjreg.png,left,nowrap,レジストリ)
HKEY_LOCAL_MACHINE以下にキーを追加していき、「HKEY_LOCAL_...
#ref(prjreg2.png,left,nowrap,レジストリ)
そしてこの中に、以下の値を設定する必要があります。~
|Type|DWORD|このアイテムのタイプを指定します|
|Enabled|DWORD|このアイテムの有効/無効を指定します|
|Options|DWORD|このアイテムが設定ダイアログを持つかどうか...
|DLL|文字列|DLLが格納されている位置を指定します|
|Selectability|DWORD|このアイテムの選択方式を指定します|
Typeは通常、4(カスタムプラグイン)を指定しておけばよいです...
0はオーナー情報、1は予定、2はメール、3は仕事を表すようで...
Enabledは、インストール直後に表示させたくなければ0にして...
ユーザーが設定からチェックを入れれば表示されるようになり...
Optionsは、設定ダイアログを持つ場合は1にする必要がありま...
今回はまだ、CustomItemOptionsDlgProcの中身を実装していな...
DLLは、そのまんま、DLLのパスを指定します。~
今回の例では、「%InstallDir%\todaytest.dll」を指定すれば...
Selectabilityは、そのアイテムを選択できるかどうか、選択で...
このあたりの動作はまだ決めていないので、今回は0を指定して...
#ref(prjreg3.png,left,nowrap,レジストリ)
というわけで、ここまでできたらビルドしてみましょう。~
CABファイルが作成されているはずです。~
出来ていたら、ActiveSync経由で実機の適当な場所に置き、実...
#ref(install.png,left,nowrap,インストール)
インストールが終了したら、ActiveSyncのエクスプローラから...
実機のエクスプローラだと、デフォではdllが表示されない上に...
確認できたら、レジストリにも正しく登録されているか、リモ...
#ref(install2.png,left,nowrap,インストール)
ここまでできたら、実際にプラグインを動かせますが、毎回ソ...
なので、インストール先のdllを、VCから直接書き換えられるよ...
DLLのプロジェクトのプロパティを開き、構成プロパティの「配...
そして、配置デバイスを「Windows Mobile 6 Professional Dev...
#ref(deploy.png,left,nowrap,配置デバイス)
プログラムをビルド後、メニューからソリューションの配置(プ...
(おそらく、使用中だとダメだと思うので、書き換え時はToday...
#ref(deploy2.png,left,nowrap,ソリューション/プロジェクト...
以上で、配置については終了です。~
ここまでのソリューション、プロジェクトとソースは、こんな...
ウィンドウクラスの時のソースとはちょっと変わってるところ...
#ref(ウィンドウ表示ソース.zip,left,nowrap,ウィンドウ表示...
これを実際に動かしてみると、表示は下図のようになります。~
#ref(sample.png,left,nowrap,サンプル表示)
Optionsを無効にしているので、設定ボタンもちゃんと無効にな...
Today画面で黒く表示されている部分が、今回作成したアイテム...
黒いのは、ウィンドウクラスの設定時に、GetStockObject( BLA...
WM_ERASEBKGNDでクリアされた背景が表示されている状態です。~
今後は、このメッセージを処理して、壁紙を透かして表示する...
** デバッグ [#dfa29a6a]
基本的には、上記の配置を使って、以下のような順番でデバッ...
プラグイン無効状態→配置→プロセス(shell32.exe)にアタッチ→...
まず、ActiveSyncでPCと実機を繋ぎ、プラグインは無効状態に...
ソースをビルドして前述の手順で配置したら、デバッグまたは...
#ref(attach.png,left,nowrap,プロセスにアタッチ)
トランスポートをスマートデバイスにして、修飾子の参照から...
エミュレータ上でデバッグする場合は、そのエミュレータを選...
すると、接続が行われ、現在動いているプロセスの一覧が表示...
#ref(attach2.png,left,nowrap,プロセスにアタッチ)
すると、デバッガが起動しますので、DLL_PROCESS_ATTACHの処...
この時点では、まだshell32.exeが自分のDLLをロードしていな...
この状態で、実機のTodayの設定を開いてアイテムタブを押すと...
そのままステップ実行等が可能ですので、リソースのロード、...
一通りアタッチの処理をデバッグしたら、再度実行します。~
自分のアイテムを有効にして、OKを押してみましょう。~
ここからは私の環境だけかもしれませんが、ブレークポイント...
ブレークポイントのリストを見ると、ブレークポイント自体は...
原因はよくわかっていませんが、shell32.exeがDLLをロードす...
動作が安定してからブレークポイントを置くと、ちゃんと捕ま...
しかしこのままでは、起動時のInitializeCustomItemのデバッ...
というわけで、苦肉の策。~
起動直後のデバッグをしたい場合は、InitializeCustomItemの...
HWND APIENTRY InitializeCustomItem( TODAYLISTITEM *ptli,...
{
LPCTodayWnd lpCTodayWnd = NULL; // Todayウィンドウクラス
::Sleep( 10000 );
if( FALSE == ptli->fEnabled || NULL == g_lpCApp ){
return NULL;
}
上の例では10000msで10秒Sleepさせています。~
Sleepの次の行にブレークポイントを置き、ブレークポイントが...
10秒あれば、その間に安定すると思いますので、置き直せばち...
ウィンドウメッセージは、CreateWindow内でのWM_CREATE発行が...
というわけで、一通り作って動作、デバッグまでの流れを書い...
ひとまず一旦ここで区切って、次回以降、作り込み部分を書い...
ページ名: