ContextMenuStripをタスクバー上に表示する

投稿者: shuichi, タグ: ,,,, 投稿日時: 2006/10/28 04:38

.NET Framework 2.0では.NET Framework 1.xのContextMenuの代わりにContextMenuStripというコントロールが追加されました。このContextMenuStripは多機能で便利ですが、タスクバー上に表示させようとするとうまく表示できません(タスクバーに重ならないように表示される)。SHAppBarMessageでデスクトップツールバーを作成したときなどは困るんじゃないかと。ということでContextMenuStripをタスクバー上に表示させるためにいろいろと調べてみました。

最初に注目したのはNotifyIcon。NotifyIconにContextMenuStripを設定すると正常にタスクバー上に表示されます。MSIL逆アセンブラでNotifyIconを覗いてみると、ContextMenuStripのShowInTaskbarというプライベートメソッドを呼び出していることが分かります。とりあえず、

contextMenuStrip.GetType().InvokeMember(
    "ShowInTaskbar",
    System.Reflection.BindingFlags.NonPublic |
    System.Reflection.BindingFlags.InvokeMethod |
    System.Reflection.BindingFlags.Instance,
    null,
    contextMenuStrip,
    new Object[] { Cursor.Position.X, Cursor.Position.Y } );

とすることでcontextMenuStripをタスクバー上に表示させることができました。

ただし、この方法では何故かメニューが常にマウスポインタの右上に表示されるようです。いまいちスッキリしないのでShowInTaskbarメソッドの中をさらに覗いてみると、ToolStripDropDownにWorkingAreaConstrainedプロパティが存在するらしい。強制的に作業領域に表示させるという意味なので、

contextMenuStrip.GetType().InvokeMember(
    "WorkingAreaConstrained",
    System.Reflection.BindingFlags.NonPublic |
    System.Reflection.BindingFlags.SetProperty |
    System.Reflection.BindingFlags.Instance,
    null,
    contextMenuStrip,
    new Object[] { false } );
contextMenuStrip.Show( Cursor.Position );

としてみるとうまく表示させることができました。ただし、メニューが表示されるとWorkingAreaConstrainedがtrueに設定されるようなので、表示させる前に毎回WorkingAreaConstrainedをfalseに設定しないと駄目なようです。

これらの方法は本来アクセスできないメソッドやプロパティに強引にアクセスしているわけで、実際はこのような方法は好ましくありません。とりあえずこのような方法もあるというだけです。

iアプリのストップウォッチ

投稿者: shuichi, タグ: ,,, 投稿日時: 2006/10/11 22:18

iアプリのストップウォッチを作ってみました。自分の携帯電話に(アラームはあるけど)ストップウォッチがなかったので。iアプリのストップウォッチは探せば無料のものがいくらでも見つかりますが、iアプリプログラミングの練習として作成しました。今のところSH902iで動作確認しました。恐らくFOMA 90xシリーズで動作可能です。

http://sks.s101.xrea.com/i/stopwatch/ に携帯電話でアクセスして、DOWNLOADからダウンロードしてください。このURLのQRコードも載せておきます。

Stopwatch QRコード

ストップウォッチをエミュレータ上で動作させた場合の動作画面と設定画面は以下のような感じです。1/100秒単位まで表示していますが実際どの程度の精度なのかは分かりません。設定画面では画面の更新間隔、文字サイズ、動作モードを設定することができます。

Stopwatch
Stopwatch 設定

操作方法は動作モードによって異なります。スプリットタイムモードおよびラップタイムモードにおける操作方法は以下のとおりです。

スタート、ストップ
決定ボタン
リセット
ストップ状態のときに左ボタン
スプリット、ラップ
スタート状態のときに左ボタン
スプリット、ラップモード切替
右ボタン
スプリット、ラップタイムのスクロール
上下ボタン

マルチタイムモードにおける操作方法は以下のとおりです。マルチタイムモードでは5つのストップウォッチをそれぞれ操作することができます。

スタート、ストップ
決定ボタン、2、5、8、0
リセット
左ボタン、1、4、7、*
全てスタート
上ボタン
全てストップ
下ボタン

ストップウォッチの動作中に電話がかかってきた場合iアプリはサスペンド状態に移行しますが、通話を終えてiアプリに復帰したときストップウォッチは通話前と変わらず動作しているはずです(通話中の時間もカウントしています)。ただし、通話中はスタートやストップ、リセットなどの操作は行うことができません。これを回避するには携帯電話を公共モードに設定すれば可能ですが、そういう場合は素直にちゃんとしたストップウォッチを。

DoCoMoが配布しているiアプリ開発ツールにはEclipse用のプラグインも同梱されていましたので比較的楽にソースコードを書くことができました。ただ、iアプリのサイズを考慮せずに書いたためサイズは約7 kBで、この程度のものとしてはちょっと大きめだと思います。