経緯
検索結果(単一行)の表示用に使えそうなオーナードロー部分を作った。
※今回のソースコードに検索機能はないです。
画面キャプチャ
ソースコード
参考サイト1のサンプルをベースに作成。
参考サイト1のサンプルではListViewItem
のTag
が内部フラグ管理に使われていたので、別のメンバを充てて、Tagを使えるようにした。
usingSystem;usingSystem.Collections.Generic;usingSystem.Drawing;usingSystem.Drawing.Drawing2D;usingSystem.Globalization;usingSystem.Windows.Forms;classSampleUsage:Form{CustomComponent.ListViewOwnerDrawlsv;SampleUsage(){ClientSize=newSize(500,500);lsv=newCustomComponent.ListViewOwnerDraw();lsv.Dock=DockStyle.Fill;lsv.GridLines=true;lsv.View=View.Details;lsv.FullRowSelect=true;lsv.Columns.Add("Path",100,HorizontalAlignment.Left);lsv.Columns.Add("Name",80,HorizontalAlignment.Left);lsv.Columns.Add("LineNo",50,HorizontalAlignment.Center);lsv.Columns.Add("Text",250,HorizontalAlignment.Left);CustomComponent.ListViewItemOwnerDrawlistViewItem1=newCustomComponent.ListViewItemOwnerDraw(newstring[]{@"c:\src","sample.c","10","#define THIS_IS_SAMPLE ((unsigned short)5)"});CustomComponent.ListViewItemOwnerDrawlistViewItem2=newCustomComponent.ListViewItemOwnerDraw(newstring[]{@"c:\src\doc","sample.txt","5","change THIS_IS_SAMPLE value to ..."});CustomComponent.ListViewItemOwnerDrawlistViewItem3=newCustomComponent.ListViewItemOwnerDraw(newstring[]{@"c:\src\tmp","dummy.txt","20","THIS_IS_SAMPLE THIS_ISNOT_SAMPLE THIS_IS_SAMPLE hoge"});lsv.Items.AddRange(newCustomComponent.ListViewItemOwnerDraw[]{listViewItem1,listViewItem2,listViewItem3});lsv.SetWord("THIS_IS_SAMPLE");lsv.SetSubIndex(3);Controls.Add(lsv);}[STAThread]staticvoidMain(){Application.Run(newSampleUsage());}}namespaceCustomComponent{publicclassListViewItemOwnerDraw:ListViewItem{publicbool_InvalidationFlag;void_init(){}publicListViewItemOwnerDraw(String[]a1,Stringa2,Colora3,Colora4,Fonta5):base(a1,a2,a3,a4,a5){_init();}publicListViewItemOwnerDraw(String[]a1,Int32a2,Colora3,Colora4,Fonta5):base(a1,a2,a3,a4,a5){_init();}publicListViewItemOwnerDraw(ListViewItem.ListViewSubItem[]a1,Stringa2):base(a1,a2){_init();}publicListViewItemOwnerDraw(String[]a1,Stringa2):base(a1,a2){_init();}publicListViewItemOwnerDraw(String[]a1,Int32a2):base(a1,a2){_init();}publicListViewItemOwnerDraw(Stringa1,Stringa2):base(a1,a2){_init();}publicListViewItemOwnerDraw(Stringa1,Int32a2):base(a1,a2){_init();}publicListViewItemOwnerDraw(String[]a1):base(a1){_init();}publicListViewItemOwnerDraw(Stringa1):base(a1){_init();}publicListViewItemOwnerDraw(ListViewItem.ListViewSubItem[]a1,Int32a2):base(a1,a2){_init();}}publicclassListViewOwnerDraw:ListView{string_word;int_subIndex;publicvoidSetWord(stringword){_word=word;}publicvoidSetSubIndex(intsubIndex){_subIndex=subIndex;}publicListViewOwnerDraw(){this.View=View.Details;this.OwnerDraw=true;this.DrawItem+=this_DrawItem;this.DrawSubItem+=this_DrawSubItem;this.DrawColumnHeader+=this_DrawColumnHeader;this.MouseUp+=this_MouseUp;this.MouseMove+=this_MouseMove;this.ColumnWidthChanged+=this_ColumnWidthChanged;this.Invalidated+=this_Invalidated;}// Selects and focuses an item when it is clicked anywhere along its width.// The click must normally be on the parent item text.privatevoidthis_MouseUp(objectsender,MouseEventArgse){ListViewItemclickedItem=this.GetItemAt(5,e.Y);if(clickedItem!=null){clickedItem.Selected=true;clickedItem.Focused=true;}}staticvoidMyDrawFocusRectangle(DrawListViewItemEventArgse){Rectanglerect=e.Bounds;intw=rect.Width-1;inth=rect.Height-2;if(w<0){w=0;}if(h<0){h=0;}rect=newRectangle(rect.X,rect.Y,w,h);Penpen=newPen(Color.Black,1.0f);pen.DashStyle=DashStyle.Dot;e.Graphics.DrawRectangle(pen,rect);}voidMyFillMatchedRect(DrawListViewSubItemEventArgse,Fontfnt,StringFormatsf){varcr=CalcCharRanges(e);sf.SetMeasurableCharacterRanges(cr);Region[]regions=e.Graphics.MeasureCharacterRanges(e.SubItem.Text,fnt,e.Bounds,sf);foreach(Regionsrinregions){RectangleFrect=sr.GetBounds(e.Graphics);rect.Y++;rect.Height-=3;e.Graphics.FillRectangle(Brushes.Yellow,rect);}}// Draws the backgrounds for entire ListView items.privatevoidthis_DrawItem(objectsender,DrawListViewItemEventArgse){if((e.State&ListViewItemStates.Selected)!=0){// Draw the background and focus rectangle for a selected item.//e.DrawBackground();e.Graphics.FillRectangle(Brushes.LightBlue,e.Bounds);//e.DrawFocusRectangle();MyDrawFocusRectangle(e);}else{e.DrawBackground();}// Draw the item text for views other than the Details view.// if (this.View != View.Details) { e.DrawText(); }}// Draws subitem text and applies content-based formatting.privatevoidthis_DrawSubItem(objectsender,DrawListViewSubItemEventArgse){TextFormatFlagsflags=TextFormatFlags.Left;using(StringFormatsf=newStringFormat()){switch(e.Header.TextAlign){caseHorizontalAlignment.Center:sf.Alignment=StringAlignment.Center;flags=TextFormatFlags.HorizontalCenter;break;caseHorizontalAlignment.Right:sf.Alignment=StringAlignment.Far;flags=TextFormatFlags.Right;break;}if(e.ColumnIndex==_subIndex){MyFillMatchedRect(e,this.Font,sf);}elseif((e.ItemState&ListViewItemStates.Selected)==0){e.DrawBackground();}if(e.ColumnIndex==_subIndex){e.Graphics.DrawString(e.SubItem.Text,this.Font,Brushes.Black,e.Bounds,sf);}else{e.DrawText(flags);}}}CharacterRange[]CalcCharRanges(DrawListViewSubItemEventArgse){varret=newList<CharacterRange>();if(_word!=null&&_word.Length>=1){strings=e.SubItem.Text;for(inti=0;i<s.Length;i+=_word.Length){i=s.IndexOf(_word,i);if(i<0){break;}ret.Add(newCharacterRange(i,_word.Length));}}returnret.ToArray();}// Draws column headers.privatevoidthis_DrawColumnHeader(objectsender,DrawListViewColumnHeaderEventArgse){using(StringFormatsf=newStringFormat()){switch(e.Header.TextAlign){caseHorizontalAlignment.Center:sf.Alignment=StringAlignment.Center;break;caseHorizontalAlignment.Right:sf.Alignment=StringAlignment.Far;break;}e.DrawBackground();e.Graphics.DrawString(e.Header.Text,this.Font,Brushes.Black,e.Bounds,sf);}return;}// Forces each row to repaint itself the first time the mouse moves over // it, compensating for an extra DrawItem event sent by the wrapped // Win32 control. This issue occurs each time the ListView is invalidated.privatevoidthis_MouseMove(objectsender,MouseEventArgse){ListViewItemOwnerDrawitem=this.GetItemAt(e.X,e.Y)asListViewItemOwnerDraw;if(item!=null&&!item._InvalidationFlag){this.Invalidate(item.Bounds);item._InvalidationFlag=true;}}// Resets the item tags. voidthis_Invalidated(objectsender,InvalidateEventArgse){foreach(ListViewItemitemTmpinthis.Items){ListViewItemOwnerDrawitem=itemTmpasListViewItemOwnerDraw;if(item==null)return;item._InvalidationFlag=false;}}voidthis_ColumnWidthChanged(objectsender,ColumnWidthChangedEventArgse){this.Invalidate();// to repaint}}}