方法 : オーナー描画リスト ボックスを作成します。
[このドキュメントはプレビュー版であり、後のリリースで変更されることがあります。 空白のトピックは、プレースホルダーとして挿入されています。]
作成できますが、オーナー描画リスト ボックス、.NET Compact Framework として簡単に .NET Framework と同様です。 他の図面メンバーですがリスト ボックスと、他のコントロールの機能をプログラムできますを .NET Compact Framework、DrawModeDrawItem をサポートしていません。 この例は、オーナー描画リスト ボックスを作成するカスタム コントロール クラスを提供し、フォントを選択するリスト ボックスとしてコントロールを実装します。
このサンプルには、基本クラス、OwnerDrawnListBoxFontListBox の派生元が含まれています。 OwnerDrawnListBox コア関数は次のとおりです。
項目、およびリスト ボックスを構築するビットマップを含む、垂直スクロール バー、配列提供します。
アイテムの高さのプロパティを示し、コントロールの高さの指定項目の数を描画できるかを決定します。
現在のスクロール バー、項目の高さ、およびマウス ポインターの座標値で選択した項目を決定する SelectedIndex プロパティ、用意されています。
SelectedIndexChanged イベントを提供します。
アイテムの可視性を確実にします。
不要な場合、スクロール バーを削除します。
ナビゲーション キーを押し、上向きとは、キーボード操作を提供します。
FontListBox クラスは、OwnerDrawnListBox を継承します。 実装および手法の次をとおり
適切な項目の高さを決定します。
オーバーライド OnPaint メソッドを使用して描画として強調表示されている、選択した項目に、アイテムを描画します。 ちらつきを回避するのにこのメソッドは、すべてのグラフィック機能が描画されるまで表示しません、制御します。
選択されているフォントの名前を含む、SelectedFaceName プロパティを提供します。
DrawFontList をフォームは、次の処理を行います。
FontListBox の新しいインスタンスを作成し、コントロール コレクションに追加します。
SelectedIndexChanged イベントのイベント ハンドラーを追加します。
フォントの一覧が FontListBox 作成します。
選択したフォントのサンプルを表示するラベルを提供します。
オーナー描画リスト ボックスを作成するには
プロジェクトに、OwnerDrawnListBox カスタム コントロール クラスを追加します。
' Base custom control for DrawFontList Class OwnerDrawnListBox Inherits Control PrivateConst SCROLL_WIDTH AsInteger = 20 Private itemH AsInteger = -1 Private selIndex AsInteger = -1 Private offScreenBitmap As Bitmap Private vs As VScrollBar Private itemsAList As ArrayList PublicSubNew() Me.vs = New VScrollBar Me.vs.Parent = MeMe.vs.Visible = FalseMe.vs.SmallChange = 1 AddHandlerMe.vs.ValueChanged, AddressOfMe.ScrollValueChanged Me.itemsAList = New ArrayList EndSubPublicReadOnlyProperty Items() As ArrayList GetReturnMe.itemsAList EndGetEndPropertyProtectedReadOnlyProperty OffScreen() As Bitmap GetReturnMe.offScreenBitmap EndGetEndPropertyProtectedReadOnlyProperty VScrollBar() As VScrollBar GetReturnMe.vs EndGetEndPropertyFriendEvent SelectedIndexChanged As EventHandler ProtectedOverridableSub OnSelectedIndexChanged(ByVal e As EventArgs) RaiseEvent SelectedIndexChanged(Me, e) EndSubProtectedOverridesSub OnMouseDown(ByVal e As MouseEventArgs) Me.SelectedIndex = Me.vs.Value + e.Y / Me.ItemHeight ' Invalidate the control so we can draw the item as selected.Me.Refresh() EndSub ' Get or set index of selected item.PublicProperty SelectedIndex() AsIntegerGetReturnMe.selIndex EndGetSet(ByVal Value AsInteger) Me.selIndex = Value RaiseEvent SelectedIndexChanged(Me, Nothing) EndSetEndPropertyProtectedSub ScrollValueChanged(ByVal o AsObject, ByVal e As EventArgs) Me.Refresh() EndSubProtectedOverridableProperty ItemHeight() AsIntegerGetReturnMe.itemH EndGetSet(ByVal Value AsInteger) Me.itemH = Value EndSetEndProperty ' If the requested index is before the first visible index then set the ' first item to be the requested index. If it is after the last visible ' index, then set the last visible index to be the requested index.PublicSub EnsureVisible(ByVal index AsInteger) If index < Me.vs.Value ThenMe.vs.Value = index Me.Refresh() ElseIf index >= Me.vs.Value + Me.DrawCount ThenMe.vs.Value = index - Me.DrawCount + 1 Me.Refresh() EndIfEndSub ' Need to set focus to the control when it ' is clicked so that keyboard events occur.ProtectedOverridesSub OnClick(ByVal e As EventArgs) Me.Focus() MyBase.OnClick(e) EndSub ' Selected item moves when you use the keyboard up/down keys.ProtectedOverridesSub OnKeyDown(ByVal e As KeyEventArgs) SelectCase e.KeyCode Case Keys.Down IfMe.SelectedIndex < Me.vs.Maximum ThenMe.SelectedIndex = Me.SelectedIndex + 1 EnsureVisible(Me.SelectedIndex + 1) Me.Refresh() EndIfCase Keys.Up IfMe.SelectedIndex > Me.vs.Minimum ThenMe.SelectedIndex = Me.SelectedIndex - 1 EnsureVisible(Me.SelectedIndex - 1) Me.Refresh() EndIfCase Keys.PageDown Me.SelectedIndex = Math.Min(Me.vs.Maximum, Me.SelectedIndex + Me.DrawCount) EnsureVisible(Me.SelectedIndex) Me.Refresh() Case Keys.PageUp Me.SelectedIndex = Math.Max(Me.vs.Minimum, Me.SelectedIndex - Me.DrawCount) EnsureVisible(Me.SelectedIndex) Me.Refresh() Case Keys.Home Me.SelectedIndex = 0 EnsureVisible(Me.SelectedIndex) Me.Refresh() Case Keys.EndMe.SelectedIndex = Me.itemsAList.Count - 1 EnsureVisible(Me.SelectedIndex) Me.Refresh() EndSelectMyBase.OnKeyDown(e) EndSub ' Calculate how many items we can draw given the height of the control.ProtectedReadOnlyProperty DrawCount() AsIntegerGetIfMe.vs.Value + Me.vs.LargeChange > Me.vs.Maximum ThenReturnMe.vs.Maximum - Me.vs.Value + 1 ElseReturnMe.vs.LargeChange EndIfEndGetEndPropertyProtectedOverridesSub OnResize(ByVal e As EventArgs) Dim viewableItemCount AsInteger = Me.ClientSize.Height / Me.ItemHeight Me.vs.Bounds = New Rectangle(Me.ClientSize.Width - SCROLL_WIDTH, 0, SCROLL_WIDTH, Me.ClientSize.Height) ' Determine if scrollbars are neededIfMe.itemsAList.Count > viewableItemCount ThenMe.vs.Visible = TrueMe.vs.LargeChange = viewableItemCount Me.offScreenBitmap = New Bitmap(Me.ClientSize.Width - SCROLL_WIDTH - 1, Me.ClientSize.Height - 2) ElseMe.vs.Visible = FalseMe.vs.LargeChange = Me.itemsAList.Count Me.offScreenBitmap = New Bitmap(Me.ClientSize.Width - 1, Me.ClientSize.Height - 2) EndIfMe.vs.Maximum = Me.itemsAList.Count - 1 EndSubEndClass
// Base custom control for DrawFontList class OwnerDrawnListBox : Control { constint SCROLL_WIDTH = 20; int itemHeight = -1; int selectedIndex = -1; Bitmap offScreen; VScrollBar vs; ArrayList items; public OwnerDrawnListBox() { this.vs = new VScrollBar(); this.vs.Parent = this; this.vs.Visible = false; this.vs.SmallChange = 1; this.vs.ValueChanged += new EventHandler(this.ScrollValueChanged); this.items = new ArrayList(); } public ArrayList Items { get { returnthis.items; } } protected Bitmap OffScreen { get { returnthis.offScreen; } } protected VScrollBar VScrollBar { get { returnthis.vs; } } publicevent EventHandler SelectedIndexChanged; // Raise the SelectedIndexChanged eventprotectedvirtualvoid OnSelectedIndexChanged(EventArgs e) { if(this.SelectedIndexChanged != null) this.SelectedIndexChanged(this, e); } protectedoverridevoid OnMouseDown(MouseEventArgs e) { this.SelectedIndex = this.vs.Value + (e.Y / this.ItemHeight); // Invalidate the control so we can draw the item as selected.this.Refresh(); } // Get or set index of selected item.publicint SelectedIndex { get { returnthis.selectedIndex; } set { this.selectedIndex = value; if (this.SelectedIndexChanged != null) this.SelectedIndexChanged(this, EventArgs.Empty); } } protectedvoid ScrollValueChanged(object o, EventArgs e) { this.Refresh(); } protectedvirtualint ItemHeight { get { returnthis.itemHeight; } set { this.itemHeight = value; } } // If the requested index is before the first visible index then set the// first item to be the requested index. If it is after the last visible// index, then set the last visible index to be the requested index.publicvoid EnsureVisible(int index) { if(index < this.vs.Value) { this.vs.Value = index; this.Refresh(); } elseif(index >= this.vs.Value + this.DrawCount) { this.vs.Value = index - this.DrawCount + 1; this.Refresh(); } } // Need to set focus to the control when it// is clicked so that keyboard events occur.protectedoverridevoid OnClick(EventArgs e) { this.Focus(); base.OnClick(e); } // Selected item moves when you use the keyboard up/down keys.protectedoverridevoid OnKeyDown(KeyEventArgs e) { switch(e.KeyCode) { case Keys.Down: if(this.SelectedIndex < this.vs.Maximum) { EnsureVisible(++this.SelectedIndex); this.Refresh(); } break; case Keys.Up: if(this.SelectedIndex > this.vs.Minimum) { EnsureVisible(--this.SelectedIndex); this.Refresh(); } break; case Keys.PageDown: this.SelectedIndex = Math.Min(this.vs.Maximum, this.SelectedIndex + this.DrawCount); EnsureVisible(this.SelectedIndex); this.Refresh(); break; case Keys.PageUp: this.SelectedIndex = Math.Max(this.vs.Minimum, this.SelectedIndex - this.DrawCount); EnsureVisible(this.SelectedIndex); this.Refresh(); break; case Keys.Home: this.SelectedIndex = 0; EnsureVisible(this.SelectedIndex); this.Refresh(); break; case Keys.End: this.SelectedIndex = this.items.Count - 1; EnsureVisible(this.SelectedIndex); this.Refresh(); break; } base.OnKeyDown(e); } // Calculate how many items we can draw given the height of the control.protectedint DrawCount { get { if(this.vs.Value + this.vs.LargeChange > this.vs.Maximum) returnthis.vs.Maximum - this.vs.Value + 1; elsereturnthis.vs.LargeChange; } } protectedoverridevoid OnResize(EventArgs e) { int viewableItemCount = this.ClientSize.Height / this.ItemHeight; this.vs.Bounds = new Rectangle(this.ClientSize.Width - SCROLL_WIDTH, 0, SCROLL_WIDTH, this.ClientSize.Height); // Determine if scrollbars are neededif(this.items.Count > viewableItemCount) { this.vs.Visible = true; this.vs.LargeChange = viewableItemCount; this.offScreen = new Bitmap(this.ClientSize.Width - SCROLL_WIDTH - 1, this.ClientSize.Height - 2); } else { this.vs.Visible = false; this.vs.LargeChange = this.items.Count; this.offScreen = new Bitmap(this.ClientSize.Width - 1, this.ClientSize.Height - 2); } this.vs.Maximum = this.items.Count - 1; } }
プロジェクトに、FontListBox クラス (これは OwnerDrawnListBox の実装) を追加します。
' Derive an implementation of the ' OwnerDrawnListBox class Class FontListBox Inherits OwnerDrawnListBox PrivateConst FONT_SIZE AsInteger = 10 PrivateConst DRAW_OFFSET AsInteger = 5 PublicSubNew() ' Determine what the item height should be ' by adding 30% padding after measuring ' the letter A with the selected font.Dim g As Graphics = Me.CreateGraphics() Me.ItemHeight = Fix(g.MeasureString("A", Me.Font).Height * 1.3) g.Dispose() EndSub ' Return the name of the selected font.PublicReadOnlyProperty SelectedFaceName() AsStringGetReturnCStr(Me.Items(Me.SelectedIndex)) EndGetEndProperty ' Determine what the text color should be ' for the selected item drawn as highlightedFunction CalcTextColor(ByVal backgroundColor As Color) As Color If backgroundColor.Equals(Color.Empty) ThenReturn Color.Black EndIfDim sum AsInteger = backgroundColor.R + backgroundColor.G + backgroundColor.B If sum > 256 ThenReturn Color.Black ElseReturn Color.White EndIfEndFunctionProtectedOverridesSub OnPaint(ByVal e As PaintEventArgs) Dim font As Font Dim fontColor As Color ' The base class contains a bitmap, offScreen, for constructing ' the control and is rendered when all items are populated. ' This technique prevents flicker.Dim gOffScreen As Graphics = Graphics.FromImage(Me.OffScreen) gOffScreen.FillRectangle(New SolidBrush(Me.BackColor), Me.ClientRectangle) Dim itemTop AsInteger = 0 ' Draw the fonts in the list.Dim n AsIntegerFor n = Me.VScrollBar.Value To (Me.VScrollBar.Value + DrawCount) - 1 ' If the font name contains "dings" it needs to be displayed ' in the list box with a readable font with the default font.IfCStr(Me.Items(n)).ToLower().IndexOf("dings") <> -1 Then font = New Font(Me.Font.Name, FONT_SIZE, FontStyle.Regular) Else font = New Font(CStr(Me.Items(n)), FONT_SIZE, FontStyle.Regular) EndIf ' Draw the selected item to appear highlightedIf n = Me.SelectedIndex Then gOffScreen.FillRectangle(New SolidBrush(SystemColors.Highlight), 1, itemTop + 1, Me.ClientSize.Width - IIf(Me.VScrollBar.Visible, Me.VScrollBar.Width, 2), Me.ItemHeight) ' If the scroll bar is visible, subtract the scrollbar width ' otherwise subtract 2 for the width of the rectangle fontColor = CalcTextColor(SystemColors.Highlight) Else fontColor = Me.ForeColor EndIf ' Draw the item gOffScreen.DrawString(CStr(Me.Items(n)), font, New SolidBrush(fontColor), DRAW_OFFSET, itemTop) itemTop += Me.ItemHeight Next n ' Draw the list box e.Graphics.DrawImage(Me.OffScreen, 1, 1) gOffScreen.Dispose() EndSub ' Draws the external border around the control.ProtectedOverridesSub OnPaintBackground(ByVal e As PaintEventArgs) e.Graphics.DrawRectangle(New Pen(Color.Black), 0, 0, Me.ClientSize.Width - 1, Me.ClientSize.Height - 1) EndSubEndClass
// Derive an implementation of the // OwnerDrawnListBox class class FontListBox : OwnerDrawnListBox { constint FONT_SIZE = 10; constint DRAW_OFFSET = 5; public FontListBox() { // Determine what the item height should be// by adding 30% padding after measuring// the letter A with the selected font. Graphics g = this.CreateGraphics(); this.ItemHeight = (int)(g.MeasureString("A", this.Font).Height * 1.3); g.Dispose(); } // Return the name of the selected font.publicstring SelectedFaceName { get { return (string)this.Items[this.SelectedIndex]; } } // Determine what the text color should be// for the selected item drawn as highlighted Color CalcTextColor(Color backgroundColor) { if(backgroundColor.Equals(Color.Empty)) return Color.Black; int sum = backgroundColor.R + backgroundColor.G + backgroundColor.B; if(sum > 256) return Color.Black; elsereturn Color.White; } protectedoverridevoid OnPaint(PaintEventArgs e) { Font font; Color fontColor; // The base class contains a bitmap, offScreen, for constructing// the control and is rendered when all items are populated.// This technique prevents flicker. Graphics gOffScreen = Graphics.FromImage(this.OffScreen); gOffScreen.FillRectangle(new SolidBrush(this.BackColor), this.ClientRectangle); int itemTop = 0; // Draw the fonts in the list.for(int n = this.VScrollBar.Value; n < this.VScrollBar.Value + DrawCount; n++) { // If the font name contains "dings" it needs to be displayed // in the list box with a readable font with the default font.if(((string)this.Items[n]).ToLower().IndexOf("dings") != -1) font = new Font(this.Font.Name, FONT_SIZE, FontStyle.Regular); else font = new Font((string)this.Items[n], FONT_SIZE, FontStyle.Regular); // Draw the selected item to appear highlightedif(n == this.SelectedIndex) { gOffScreen.FillRectangle(new SolidBrush(SystemColors.Highlight), 1, itemTop + 1, // If the scroll bar is visible, subtract the scrollbar width// otherwise subtract 2 for the width of the rectanglethis.ClientSize.Width - (this.VScrollBar.Visible ? this.VScrollBar.Width : 2), this.ItemHeight); fontColor = CalcTextColor(SystemColors.Highlight); } else fontColor = this.ForeColor; // Draw the item gOffScreen.DrawString((string)this.Items[n], font, new SolidBrush(fontColor), DRAW_OFFSET, itemTop); itemTop += this.ItemHeight; } // Draw the list box e.Graphics.DrawImage(this.OffScreen, 1, 1); gOffScreen.Dispose(); } // Draws the external border around the control.protectedoverridevoid OnPaintBackground(PaintEventArgs e) { e.Graphics.DrawRectangle(new Pen(Color.Black), 0, 0, this.ClientSize.Width - 1, this.ClientSize.Height - 1); } }
フォームで、2 つの Label コントロール追加し、 descLabel および sampleLabel; 名前を付けます後者の場合が表示、フォントの使用例 FontListBox から選択されます。
FontListBox フォームのインスタンスを作成します。
フォームに対する Load イベントのコンストラクターに次のコードを追加します。
' Create a new instance of FontListBox. myListBox.Parent = Me ' Configure the event handler for the SelectedIndexChanged event. AddHandler myListBox.SelectedIndexChanged, AddressOfMe.SelectedIndexChanged ' Draw the bounds of the FontListBox. myListBox.Bounds = New Rectangle(5, 5, 150, 100) ' Add fonts to list, repeat the list 4 times' so that the scroll bar can be demonstrated.Dim n AsIntegerFor n = 0 To 3 myListBox.Items.Add("Bookdings") myListBox.Items.Add("Courier New") myListBox.Items.Add("Frutiger Linotype") myListBox.Items.Add("Tahoma") Next n ' Labels to show the selected font from the list box. Assumes' instances of these labels have been declared for the form. descLabel.Parent = Me descLabel.Text = "Font Sample:" descLabel.Bounds = New Rectangle(10, myListBox.Bottom + 20, Me.ClientSize.Width - 10, 30) ' Assumes an instance sampleLabel is declared for the form. sampleLabel.Parent = Me sampleLabel.Bounds = New Rectangle(10, descLabel.Bottom, Me.ClientSize.Width - 10, 30) sampleLabel.Text = "AaBbCc 123"
// Create a new instance of FontListBox. box = new FontListBox(); box.Parent = this; // Configure the event handler for the SelectedIndexChanged event. box.SelectedIndexChanged += new EventHandler(this.SelectedIndexChanged); // Draw the bounds of the FontListBox. box.Bounds = new Rectangle(5, 5, 150, 100); // Add fonts to list, repeat the list 4 times// so that the scroll bar can be demonstrated.for(int n = 0; n < 4; n++) { box.Items.Add("Bookdings"); box.Items.Add("Courier New"); box.Items.Add("Frutiger Linotype"); box.Items.Add("Tahoma"); } // Labels to show the selected font and a sample. Label desc = new Label(); desc.Parent = this; desc.Text = "Font Sample:"; desc.Bounds = new Rectangle(10, box.Bottom + 20, this.ClientSize.Width - 10, 30); sample = new Label(); sample.Parent = this; sample.Bounds = new Rectangle(10, desc.Bottom, this.ClientSize.Width - 10, 30); sample.Text = "AaBbCc 123";
コード SelectedChangedEventFontListBox コントロールで選択されているフォントを表示する、 sampleLabel コントロールのイベントを追加します。
' Event handler for SelectedIndexChanged to ' display a sample of the selected font. ' Assumes that an instace of myListBox has been declared for the form. Friend Sub SelectedIndexChanged(ByVal o AsObject, ByVal e As EventArgs) sampleLabel.Font = New Font(myListBox.SelectedFaceName, 12, FontStyle.Regular) EndSub
// Event handler for SelectedIndexChanged to // display a sample of the selected font. private void SelectedIndexChanged(object o, EventArgs e) { sample.Font = new Font(box.SelectedFaceName, 12, FontStyle.Regular); }
コードのコンパイル方法
この例では、次の名前空間への参照が必要です。