「拡張 ComboBox の作成」
http://msdn.microsoft.com/ja-jp/library/ms996411.aspx

これを読んで、いいなあ、と思って、ComboBox に組み込んだのですが、落とし穴がありました。

マルチモニタ環境で、プライマリスクリーン以外の場所で、ドロップダウンリストを表示すると、プライマリスクリーンに表示されます。

私はシングル環境しか持ってないので、どうやってテストするかなーと思ってたのですが、Oracle VM VirtualBox で環境が作れるようです。

早速インストールして実行。

bettercombo.jpg

なるほど、こんな感じなのかー。

というわけで修正。

Screen.PrimaryScreen.WorkingArea を参照している箇所は、Screen.GetWorkingArea(this) に変更し、ドロップダウンリストの位置を変更している箇所のロジックを少々書き換えます。

 private void AdjustDropDown(ref Message m)
 {    
     // 現在の WorkArea を取得
     Rectangle workArea = Screen.GetWorkingArea(this);
 
     // ComboBox の現在の位置とサイズを取得
     Rectangle comboRect = this.RectangleToScreen(this.ClientRectangle);
 
     // DropDownList の左上のスクリーン座標を取得
     Point dropDownPoint = new Point(comboRect.Left, comboRect.Bottom);
     Point newDropDownPoint = dropDownPoint;
 
     //ドロップダウンが画面の右端からはみ出す場合
     if (dropDownPoint.X + this.DropDownWidth > workArea.Right)
     {
         //移動先の左位置を計算
         newDropDownPoint.X = workArea.Right - this.DropDownWidth;
     }
 
     // ドロップダウンリストの高さを計算
     int dropHeight = 0;
     for (int i = 0; (i < this.Items.Count && i < this.MaxDropDownItems); i++)
     {
         dropHeight += this.ItemHeight;
     }
 
     // ドロップダウンが画面の下端からはみ出す場合
     if (dropDownPoint.Y + dropHeight > workArea.Bottom)
     {
         newDropDownPoint.Y = comboRect.Top - dropHeight - 2;
     }
 
     // 必要があれば移動する
     if (dropDownPoint != newDropDownPoint)
     {
         NativeMethods.SetWindowPos(
                         new HandleRef(this, m.LParam),
                         NativeMethods.NullRef,
                         newDropDownPoint.X,
                         newDropDownPoint.Y,
                         0,
                         0,
                         NativeMethods.SWP_NOSIZE);
     }
 }

API の宣言については、NativeMethods クラスに持っていき、ウィンドウハンドルでなく、HandleRef に変えています。




トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   最終更新のRSS
Last-modified: 2013-08-04 (日) 19:30:42 (1473d)