主婦と.NETと犬のぶろぐ

奥様 と プログラム と お犬様 の 楽しい日常

目次

Blog 利用状況

ニュース

書庫

日記カテゴリ

ComboBox(System.Windows.Forms.ComboBox)

ComboBox は比較的よく使うコントロールなので、エントリも短時間で済むだろうと思っていたのですが...
こんな面白いもの(拡張 ComboBox の作成)を見つけたので、
VB のコードに変換してみたり、使ってみたりと、なんじゃかんじゃやっていたら予想より時間がかかってしまいました。

拡張 ComboBox のサンプルコードを見てみると、デザイナ上で Items にどわーっとリストを記述しています。
なので、HandleCreated 時にリスト幅の計算をやったりする処理が走って問題ないとおもうんですが、
実際に業務で使う場合は、動的にリストを生成する方が多いと思います。

なので、私も DB から動的な値とってきて DataSource にセットして、DisplayMemberChanged 時にとりあえずやっていますが、
ほかに適切なイベントがあるやもしれません。
ひょっとしたら、UpdateDropDownWidth を外部に公開したほうが良いと思う方もいるやもしれません。

あと、どぼん!さんのページでこのようなものを見つけました。
ComboBoxが上下矢印キーで項目を変更できないようにする
そういう要望は結構あるんでしょか...

■参考文献
ComboBox クラス
AutoCompleteStringCollection クラス
ComboBoxが上下矢印キーで項目を変更できないようにする
拡張 ComboBox の作成

■実行画像
ComboBox5 ドロップダウン時
ComboBox ComboBox5 ドロップダウン時

BetterComboBox ドロップダウン時
ComboBox BetterComboBox ドロップダウン時

Imports System.Runtime.InteropServices 'Better ComboBox の為

Public Class ComboBoxTest
Private Sub ComboBoxTest_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load '' DataSource を指定する Dim dt As DataTable = New DataTable dt.Columns.Add("ID", GetType(Integer)) dt.Columns.Add("NAME", GetType(String)) dt.Rows.Add(New Object() {1, "ふじこ"}) dt.Rows.Add(New Object() {2, "エデン"}) dt.Rows.Add(New Object() {3, "オット"}) Me.ComboBox1.DataSource = dt Me.ComboBox1.DisplayMember = dt.Columns(1).ColumnName Me.ComboBox1.ValueMember = dt.Columns(0).ColumnName ' 未選択状態にする Me.ComboBox1.SelectedIndex = -1
'' Items を追加する ' ユーザーの編集を拒否する Me.ComboBox2.DropDownStyle = ComboBoxStyle.DropDownList Me.ComboBox2.Items.Clear() Me.ComboBox2.Items.Add("わんくま") Me.ComboBox2.Items.Add("wankuma") Me.ComboBox2.Items.Add("ワンクマ") ' wankuma を選択状態にする Me.ComboBox2.SelectedItem = "wankuma"
'' オートコンプリートを設定する(FileSystem) Me.ComboBox4.AutoCompleteMode = AutoCompleteMode.Suggest Me.ComboBox4.AutoCompleteSource = Windows.Forms.AutoCompleteSource.FileSystem
'' オートコンプリートを設定する(カスタムソース) Me.ComboBox4.Items.Clear() Me.ComboBox4.Items.Add("shiba") Me.ComboBox4.Items.Add("dachshund") Me.ComboBox4.Items.Add("otto")
Me.ComboBox4.AutoCompleteMode = AutoCompleteMode.Suggest Me.ComboBox4.AutoCompleteSource = Windows.Forms.AutoCompleteSource.CustomSource Dim autoCompleteSource As AutoCompleteStringCollection = New AutoCompleteStringCollection autoCompleteSource.Add("shiba") autoCompleteSource.Add("dachshund") autoCompleteSource.Add("otto") Me.ComboBox4.AutoCompleteCustomSource = autoCompleteSource
'' BetterComboBox 比較用 Const CONNECTION_STRING As String = "Data Source=(local);Initial Catalog=NorthWind;Integrated Security=SSPI;" Dim source As DataTable = New DataTable Dim connection As SqlClient.SqlConnection = New SqlClient.SqlConnection(CONNECTION_STRING) Try connection.Open() Dim da As SqlClient.SqlDataAdapter = New SqlClient.SqlDataAdapter da.SelectCommand = New SqlClient.SqlCommand da.SelectCommand.Connection = connection da.SelectCommand.CommandText = "SELECT Address FROM Customers" da.Fill(source) Finally If Not connection Is Nothing Then connection.Close() connection.Dispose() End If End Try
' 普通の ComboBox Me.ComboBox5.Items.Clear() Me.ComboBox5.DataSource = source Me.ComboBox5.DisplayMember = "Address"
' BetterComboBox 使用 Dim bComboBox As BetterComboBox = New BetterComboBox Me.Controls.Add(bComboBox) bComboBox.Location = New Point(12, 140) bComboBox.DataSource = source bComboBox.DisplayMember = "Address" End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click '' ComboBox4 の AutoCompleteCustomSource に 値を追加する。 Me.ComboBox4.Items.Add(Me.ComboBox4.Text) Me.ComboBox4.AutoCompleteCustomSource.Add(Me.ComboBox4.Text) End Sub End Class
''' <summary> ''' BetterComboBox ''' </summary> ''' <remarks> ''' http://www.microsoft.com/japan/msdn/net/winforms/bettercombobox.aspx ''' </remarks> Public Class BetterComboBox Inherits ComboBox
#Region "SetWindowPos" <DllImport("user32.dll", CharSet:=CharSet.Auto)> _ Private Shared Function SetWindowPos( _ ByVal hWnd As IntPtr, _ ByVal hWndInsertAfter As IntPtr, _ ByVal x As Integer, _ ByVal y As Integer, _ ByVal cx As Integer, _ ByVal cy As Integer, _ ByVal uFlags As Integer) _ As Boolean End Function
' サイズ変更なし Private Const SWP_NOSIZE As Integer = &H1 ' リストが描画されようとしている時の親コンテナへのメッセージ Private Const WM_CTLCOLORLISTBOX As Integer = &H134 #End Region
'//UpdateDropDownWidth でチェックする既定の幅を格納します Private initialDropDownWidth As Integer = 0
Private components As System.ComponentModel.IContainer = Nothing
Protected Overrides Sub Dispose(ByVal disposing As Boolean) If disposing AndAlso Not Me.components Is Nothing Then Me.components.Dispose() End If MyBase.Dispose(disposing) End Sub
Private Sub InitializeComponent() Me.Name = "BetterComboBox" End Sub
Public Sub New() Me.InitializeComponent() Me.initialDropDownWidth = Me.DropDownWidth 'AddHandler Me.HandleCreated, New EventHandler(AddressOf Me.BetterComboBox_HandleCreated) AddHandler Me.DisplayMemberChanged, New EventHandler(AddressOf Me.BetterComboBox_HandleCreated) End Sub
Public Sub BetterComboBox_HandleCreated(ByVal sender As Object, ByVal e As System.EventArgs) Me.UpdateDropDownWidth() End Sub
Private Sub UpdateDropDownWidth() '//GDI+ 描画面を作成して、文字列の幅を測定します Dim ds As System.Drawing.Graphics = Me.CreateGraphics() '//最大幅の項目の値を保持する Float 変数 Dim maxWidth As Single = 0 '//各項目を反復処理して '//DisplayMember 文字列の最大幅を測定します For Each item As Object In Me.Items maxWidth = Math.Max(maxWidth, ds.MeasureString(item.ToString(), Me.Font).Width) Next '//空白文字用のバッファを '//テキストに追加します maxWidth += 30 '//maxWidth を四捨五入して int にキャストします Dim newWidth As Integer = Convert.ToInt32(Decimal.Round(Convert.ToDecimal(maxWidth), 0)) '//幅が画面よりも大きい場合には '//画面内に収まるようにします If newWidth > Screen.GetWorkingArea(Me).Width Then newWidth = Screen.GetWorkingArea(Me).Width End If '//新しく計算した幅よりも小さい場合にのみ '//既定の幅を変更します If newWidth > initialDropDownWidth Then Me.DropDownWidth = newWidth End If '//描画面をクリーンアップします ds.Dispose() End Sub
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message) If m.Msg = WM_CTLCOLORLISTBOX Then '//画面内に収まるようにします Dim left As Integer = Me.PointToScreen(New Point(0, 0)).X '//ドロップダウンが画面の右端からはみ出す場合のみ、以下の処理を実行します If Me.DropDownWidth > Screen.PrimaryScreen.WorkingArea.Width - left Then '//ComboBox の現在の位置とサイズを取得します Dim comboRect As Rectangle = Me.RectangleToScreen(Me.ClientRectangle)
Dim dropHeight As Integer = 0 Dim topOfDropDown As Integer = 0 Dim leftOfDropDown As Integer = 0
'//ドロップ リストの高さを計算します Dim i As Integer = 0 While (i < Me.Items.Count AndAlso i < Me.MaxDropDownItems) dropHeight += Me.ItemHeight i += 1 End While
'//ドロップ リストが画面の下端からはみ出す場合には '//ドロップダウンの上位置を設定します If dropHeight > Screen.PrimaryScreen.WorkingArea.Height - _ Me.PointToScreen(New Point(0, 0)).Y Then topOfDropDown = comboRect.Top - dropHeight - 2 Else topOfDropDown = comboRect.Bottom End If
'//移動先の左位置を計算します leftOfDropDown = comboRect.Left - (Me.DropDownWidth - _ (Screen.PrimaryScreen.WorkingArea.Width - left)) '//ドロップダウンの配置とサイズを決定します '//SWP_NOSIZE フラグを使用する場合、cx および cy パラメータは無視されます SetWindowPos(m.LParam, _ IntPtr.Zero, _ leftOfDropDown, _ topOfDropDown, _ 0, _ 0, _ SWP_NOSIZE) End If End If MyBase.WndProc(m) End Sub End Class

投稿日時 : 2006年12月14日 12:27

Feedback

# re: ComboBox(System.Windows.Forms.ComboBox) 2006/12/14 14:41 επιστημη

ふじこ,エデンとオットが同列!(爆

そかそか、'愛するもの'のテーブルなのねん♪

# re: ComboBox(System.Windows.Forms.ComboBox) 2006/12/14 16:58 なおこ(・∀・)

>> えぴさん
> 愛するもの
ということにしておきましょう...

# 本当はわたしの可愛いペット達。

# カルティエ 腕輪 2016/11/19 5:12 ctkxqswpmfj@docomo.ne.jp

スーパーコピーブランド通販店(*^-^*)
スーパーコピーブランドメンズレディースファッション時計バッグ財布を海外通販!
スーパーコピーブランド激安ショッピングサイトです。
送料無料(日本全国)!
サポート体制も万全です。
スタイルが豊富で。
最新作も随時入荷いたしております。
ご安心購入くださいませ。
カルティエ 腕輪 http://www.newkakaku.com/pb1.htm

タイトル  
名前  
Url
コメント