ou create an “owner-draw” ListBox or ComboBox when you want to bypass the control’s automatic item display in order to do something special, such as display an image for each item or display a list in which the items aren’t all the same size. The .NET framework makes it simple to create these custom item lists. In this article, you’ll see how to populate list and combobox controls with items you draw yourself.
The only thing you need to do to create an owner-drawn list or combo box is to set the DrawMode property to either OwnerDrawFixed, or OwnerDrawVariable. The DrawMode property has three possible settings: Normal (the default), in which the system handles displaying the items automatically; OwnerDrawFixed, which you should use when you want to draw the items yourself, but they’re all the same height and width; and OwnerDrawVariable, which you use to draw items that vary in height or width. When you select the OwnerDrawFixed setting, you must implement a DrawItem method, which the ListBox calls whenever it needs to draw an item. When you select the OwnerDrawVariable setting, you must implement both the DrawItem and a MeasureItem method. The MeasureItem method lets you set the size of the item to be drawn. When you select the Normal setting, the system does not fire either the MeasureItem or the DrawItem methods.
There are a couple of restrictions. You can’t create variable-height items for multicolumn ListBoxes, and CheckedListBoxes don’t support either of the owner-drawn DrawMode settings.
Example 1: Listing Files and Folders
Suppose you want to list the files and directories in a folder along with the associated system icons appropriate to the type of file. There are several steps required to accomplish the task:
- Validate the requested directory path
- Retrieve the files and subfolders from a directory
- Iterate through them, retrieving their types and names
- Find the appropriate icon for each file type
- Draw the items for the ListBox containing the appropriate icon and text
![]() |
|
| Figure 1: The ListFilesAndFolders form contains an owner-draw ListBox that displays folder and file names, along with their system-associated icons. |
Figure 1 depicts a Web form with the finished ListBox control that displays all the files in a specified directory along with their corresponding system icons. To use the example, enter a directory path in the first text field. The form ensures that the entered path is valid, and then follows the steps listed above to fill a ListBox shown in a separate dialog. The user can double-click an item in the list, or select an item and click OK. The constructor for the dialog form (ListFilesAndFolders) requires a path string.
The first step in the application’s logic is to validate the path string the user enters into the main form. The System.IO.DirectoryInfo class has an Exists method that returns True if the directory exists:
Dim di As DirectoryInfo di = New DirectoryInfo(Me.txtPath.Text) If Not di.Exists Then txtPath.ForeColor = System.Drawing.Color.Red Beep() End If
The code turns the TextBox text red and plays a warning sound if the entered path is invalid; otherwise, it creates a new instance of the ListFilesAndFolders form, passing the validated path string to its constructor.
Dim frmFiles As New _ ListFilesAndFolders(Me.txtPath.Text)
The ListFilesAndFolders form contains a ListBox, an OK button, and a Cancel button.
The ListFilesAndFolders form constructor calls a FillList method that retrieves the files and folders in the specified path and fills a ListBox control with the icons and names, suspending the control’s display until the method completes.
Sub FillList(ByVal aPath As String) Dim fsi As FileSystemInfo lstFiles.BeginUpdate() lstFiles.Items.Clear() files = New DirectoryInfo(aPath).GetFileSystemInfos For Each fsi In files lstFiles.Items.Add(fsi) Next lstFiles.EndUpdate() End Sub
The DirectoryInfo.GetFileSystemInfos method returns an array of FileSystemInfo objects. The code iterates through the returned array and adds each item to the ListBox’s Items collection.
The act of adding the items to the ListBox doesn’t cause the ListBox to draw them; instead, the ListBox fires a DrawItem event whenever the ListBox needs to display an item. In this case, you want to draw an icon and the name of a FileSystemInfo object that represents a file or folder. Because this is an owner-draw control, you need to create the DrawItem method to create the item display.
Private Sub lstFiles_DrawItem( _ ByVal sender As Object, _ ByVal e As System.Windows.Forms.DrawItemEventArgs) _ Handles lstFiles.DrawItem ' the system sometimes calls this method with ' an index of -1. If that happens, exit. If e.Index < 0 Then e.DrawBackground() e.DrawFocusRectangle() Exit Sub End If ' create a brush Dim aBrush As Brush = System.Drawing.Brushes.Black ' get a reference to the item to be drawn Dim fsi As FileSystemInfo = _ CType(lstFiles.Items(e.Index), FileSystemInfo) ' create an icon object Dim anIcon As Icon ' use a generic string format to draw the filename Dim sFormat As StringFormat = _ StringFormat.GenericTypographic ' get the height of each item Dim itemHeight As Integer = lstFiles.ItemHeight ' call these methods to get items to highlight ' properly e.DrawBackground() e.DrawFocusRectangle() ' retrieve the appropriate icon for this file type anIcon = IconExtractor.GetSmallIcon(fsi) ' draw the icon If Not anIcon Is Nothing Then e.Graphics.DrawIcon(anIcon, 3, _ e.Bounds.Top + ((itemHeight - _ Me.ImageList1.Images(0).Height) 2)) anIcon.Dispose() End If ' if the item is selected, ' change the text color to white If (e.State And _ Windows.Forms.DrawItemState.Selected) = _ Windows.Forms.DrawItemState.Selected Then aBrush = System.Drawing.Brushes.White End If sFormat.LineAlignment = StringAlignment.Center e.Graphics.DrawString(fsi.Name, lstFiles.Font, _ aBrush, 22, e.Bounds.Top + _ (e.Bounds.Height 2), sFormat) End Sub
In the DrawItem method, the code calls a shared GetSmallIcon method exposed by the IconExtractor class (see Listing 1), which, when passed a FileSystemInfo object, calls the Win32 SHGetFileInfo API to extract the icon for the file type represented by that object. The IconExtractor class exposes two public shared methods, GetLargeIcon and GetSmallIcon, both of which simply call a private GetIcon method that returns the large (32 x 32) and small (16 x 16) icon versions, respectively.
Public Shared Function GetSmallIcon( _ ByVal fsi As FileSystemInfo) As Icon Return IconExtractor.GetIcon _ (fsi, SHGFI_SMALLICON) End Function Public Shared Function GetLargeIcon( _ ByVal fsi As FileSystemInfo) As Icon Return IconExtractor.GetIcon _ (fsi, SHGFI_LARGEICON) End Function Private Shared Function GetIcon( _ ByVal fsi As FileSystemInfo, _ ByVal anIconSize As Integer) As Icon Dim aSHFileInfo As New SHFILEINFO() Dim cbFileInfo As Integer = _ Marshal.SizeOf(aSHFileInfo) Dim uflags As Integer = SHGFI_ICON Or _ SHGFI_USEFILEATTRIBUTES Or anIconSize Try SHGetFileInfo(fsi.FullName, fsi.Attributes, _ aSHFileInfo, cbFileInfo, uflags) Return Icon.FromHandle(aSHFileInfo.hIcon) Catch ex As Exception Return Nothing End Try End Function
The GetSmallIcon and GetLargeIcon methods both accept a FileSystemInfo object. Internally, the GetIcon method uses the FileSystemInfo object to pass the file name and file attributes to the SHGetFileInfo API call. After drawing the icon, the DrawItem event handler calls the Graphics.DrawString method to place the file name on the image next to the icon. The ListBox calls the DrawItem method repeatedly, for each item in its Items collection.
The DrawItemEventArgs argument to the DrawItem event handler exposes an Index property whose value is the index of the item to be drawn. Watch out! The system raises the DrawItem event with an index value of -1 when the Items collection is empty. When that happens you should call the DrawItemEventArgs.DrawBackground() and DrawFocusRectangle() methods and then exit. The purpose of raising the event is to let the control draw a focus rectangle so that users can tell it has the focus, even when there are no items present. The code traps for that condition, calls the two methods, and then exits the handler immediately.
Users can select an item and close the ListFilesAndFolders form either by selecting an item and then clicking the OK button, or by double-clicking an item. Either way, the form sets a public property called SelectedItem, sets another public property called Cancel and then closes. The main form then displays the filename of the selected item in the Result field.
Example 2: Drawing Items with Variable Width and Height
Here's another example. The items you create don't all have to be the same width and height. To create an owner-drawn list or combo box with variable item heights and widths, set the DrawMode property to OwnerDrawVariable. Then, implement a method that handles the MeasureItem event, which accepts a sender (Object), and a System.Windows.Forms.MeasureItemEventArgs argument. The sample form frmColorListBox displays all the known system colors and their names in a combo box. The items themselves vary between 20 and 40 pixels in height. It's contrived and ugly (see Figure 2), but serves to illustrate the point.
![]() |
Charlie has over a decade of experience in website administration and technology management. As the site admin, he oversees all technical aspects of running a high-traffic online platform, ensuring optimal performance, security, and user experience. Related PostsAbout Our Editorial ProcessAt DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere. See our full editorial policy. ![]() White House Presses Military on AI
Kirstie Sands
August 3, 2026
3:02 PM
![]() Open Source Risk Management Beyond Vulnerability Scanning
Priya Nandakumar
August 3, 2026
2:35 PM
![]() Global Crypto Rules Tighten As Enforcement Rises
Sumit Kumar
August 3, 2026
2:09 PM
![]() Exclusion Claims Stir Tensions On Island
Rashan Dixon
August 3, 2026
1:42 PM
![]() ASE Lifts Capex to $10.5 Billion
Steve Gickling
August 3, 2026
12:41 PM
![]() Ceuta Border Sees Sudden Migrant Surge
Sumit Kumar
August 3, 2026
12:30 PM
![]() Kimi K3 Is the Largest Open-Source AI Model Ever. Here’s What It Means for Your Business.
Rashan Dixon
August 3, 2026
10:53 AM
![]() Europe Races To Fortify Infrastructure
Steve Gickling
August 3, 2026
8:28 AM
![]() What AI Coding Agents Can and Can’t Do for Your Dev Team
Rashan Dixon
August 3, 2026
8:00 AM
![]() How AI Agents in Finance Are Quietly Reshaping the Industry
Rashan Dixon
August 2, 2026
8:00 AM
Pocket Cameras Need Zoom More Than Hype
Joe Rothwell
August 1, 2026
10:48 AM
![]() An AI Model Escaped Its Sandbox and Hacked Hugging Face: A Wake-Up Call for AI Agent Security
Rashan Dixon
August 1, 2026
8:00 AM
![]() How to Use AI Agents in Your Everyday Workflow in 2026
Rashan Dixon
August 1, 2026
8:00 AM
![]() Study Links Soccer Finals To Fan Stress
Rashan Dixon
July 31, 2026
3:26 PM
![]() MyDecisive Exits Stealth With $12 Million
Sumit Kumar
July 31, 2026
3:18 PM
![]() How Seedance 2.0 Is Solving AI Video’s Character Consistency Problem in 2026
Marcus Whitfield
July 31, 2026
3:03 PM
![]() Halliday G2 Glasses Summarize Meetings
Steve Gickling
July 31, 2026
2:17 PM
![]() Sony Accuses Udio Of Copying Music
Sumit Kumar
July 31, 2026
1:37 PM
![]() Fauci Faces Senate Questions On Covid Origins
Steve Gickling
July 31, 2026
12:41 PM
![]() GPT-5.6 vs. Grok 4.5: Which New AI Model Should Your Team Actually Use?
Rashan Dixon
July 31, 2026
10:20 AM
![]() Apple Vision Pro VP Reportedly Joins OpenAI
Deanna Ritchie
July 31, 2026
9:16 AM
![]() AI Agents Use Cases That Are Actually Paying Off in 2026
Rashan Dixon
July 31, 2026
8:00 AM
![]() Pocket Launches $129 Phone-Mounted Recorder
Kirstie Sands
July 30, 2026
4:27 PM
![]() What Is Agentic AI? The Business Leader’s Guide to Software That Acts on Its Own
Rashan Dixon
July 30, 2026
4:17 PM
![]() Five Days Of Testimony In Teen Case
Steve Gickling
July 30, 2026
3:09 PM
|

























