Using OwnerDraw For Good-Looking Controls
Using OwnerDraw For Good-Looking Controls
Using OwnerDraw For Good-Looking Controls
Using OwnerDraw For Good-Looking Controls
Using OwnerDraw For Good-Looking Controls
Using OwnerDraw For Good-Looking Controls Using OwnerDraw For Good-Looking Controls Using OwnerDraw For Good-Looking Controls Using OwnerDraw For Good-Looking Controls Using OwnerDraw For Good-Looking Controls Using OwnerDraw For Good-Looking Controls Using OwnerDraw For Good-Looking Controls Using OwnerDraw For Good-Looking Controls
Using OwnerDraw For Good-Looking Controls Using OwnerDraw For Good-Looking Controls
Using OwnerDraw For Good-Looking Controls
Go Back  Xtreme Visual Basic Talk > > > > Using OwnerDraw For Good-Looking Controls


Reply
 
Thread Tools Display Modes
  #1  
Old 07-24-2005, 09:09 AM
Iceplug's Avatar
IceplugUsing OwnerDraw For Good-Looking Controls Iceplug is offline
MetaCenturion

Retired Moderator
* Guru *
 
Join Date: Aug 2001
Location: Iowa, USA
Posts: 16,583
Thumbs up Using OwnerDraw For Good-Looking Controls


OwnerDrawing allows you to draw the graphics of a particular control yourself. This opens up a lot of opportunities for expressing your artistic mind. Are you tired of that boring old menu-colored menu? Spice it up with a bright new yellow color or a hot new blue. Want to add a little something to that listbox? OwnerDraw it?

First, we're going to look at OwnerDraw on Menu controls.

First, add a MainMenu component to your form, and change its name to something besides MainMenu1.
Now add one menu header to it... let's call it FileMenu and set the caption to be File (no '&' yet).
Next, let's set the OwnerDraw property for FileMenu to True.
When you run your program now, you won't see the menu, because it is up to you to draw it.

Beginning OwnerDraw
To do OwnerDraw for this menu, we go to the events for this FileMenu.
The first event to use is the MeasureItem event.
The MeasureItemEventArgs has only 4 properties - we're only going to look at one of them for now... that's the .ItemWidth. (ItemHeight is fixed, nothing will happen)
We will set this value to the width that the want our menu canvas to be, and after this event is complete, the menu will be created to this size.

After we've set those, it's time to move on to the DrawItem event. This is, of course, where you'll be doing your drawing.
The DrawItemEventArgs are more robust (slightly).

You can add e.DrawBackground to get just a simple menu interfacing - white when not selected and the selected color when selected.

After our background is drawn, we can draw the menu text with .DrawString; the graphics object is available at e.Graphics.
The string can be taken from either FileMenu.Text, or you can DirectCast the sender into a Menu... but for our case, it should be "File".
The Font is included with the DrawItemEventArgs: e.Font.
Brushes.Black is typical of the brush that would be used to draw text.
The X and Y property should be e.Bounds.X and e.Bounds.Y. You can add some value to it, but without e.Bounds, you'd be drawing on the icon in the titlebar.
These are just defaults. You can set them to whatever you want to do: you can use Wingdings with a Red Brush and draw the string in uppercase if you want.
Code:
Private Sub FileMenu_MeasureItem(ByVal sender As Object, ByVal e As System.Windows.Forms.MeasureItemEventArgs) Handles FileMenu.MeasureItem e.ItemWidth = 56 End Sub Private Sub FileMenu_DrawItem(ByVal sender As Object, ByVal e As System.Windows.Forms.DrawItemEventArgs) Handles FileMenu.DrawItem e.DrawBackground() e.Graphics.DrawString(FileMenu.Text, e.Font, Brushes.Black, e.Bounds.X, e.Bounds.Y) End Sub

Expanding your Drawing Ability and State Checking
Now, you have drawn your own menu. But, you can do more, of course.
Instead of doing e.DrawBackground, you can easily draw your own background rectangle:

e.Graphics.FillRectangle(Brushes.LightBlue, e.Bounds)
For a lightblue menu.
e.Graphics.FillRectangle(SystemBrushes.Menu, e.Bounds)
For a menu-colored menu.

When you run your project however, you will notice that your menu won't highlight. This is because e.DrawBackground() properly checked the e.State, but at the moment, we aren't checking the state.

A menu object goes more often through two basic states:
State.None and State.Selected
Depending on the value of the state that is in e.State(), we should draw an appropriate background for it.
To check if the menu is selected through the e.State (flag) enumeration, we do any flag checking method available.
For example:
If (e.State And DrawItemState.Selected) = DrawItemState.Selected Then
will check if it is selected.

In this If block, we draw the background for when the menu is selected. In the Else part, we can draw the background for when the menu is not selected.
Code:
'Check if the menu is selected. If (e.State And DrawItemState.Selected) = DrawItemState.Selected Then 'If menu selected, we draw a yellowgreen highlighting e.Graphics.FillRectangle(Brushes.YellowGreen, e.Bounds) Else 'Not selected, we draw this light blue. e.Graphics.FillRectangle(Brushes.LightBlue, e.Bounds) End If

OwnerDraw on Submenus
Now, let's add a few submenus to the FileMenu menuheader... say,
New, Open, Save, and Close.
Set all of their name properties to something and set all of their OwnerDraw properties to True. I am using FileNew, FileOpen, FileSave, and FileClose.

To save the time of making DrawItem and MeasureItem event handlers for all of these, you can just create a DrawItem and MeasureItem for one control, and then set them to handle the others, as shown below.
Code:
Private Sub FileNew_DrawItem(ByVal sender As Object, ByVal e As System.Windows.Forms.DrawItemEventArgs) Handles FileNew.DrawItem, _ FileOpen.DrawItem, FileSave.DrawItem, FileClose.DrawItem 'draw item. End Sub Private Sub FileNew_MeasureItem(ByVal sender As Object, ByVal e As System.Windows.Forms.MeasureItemEventArgs) Handles FileNew.MeasureItem, _ FileOpen.MeasureItem, FileSave.MeasureItem, FileClose.MeasureItem 'measure item. End Sub
In the MeasureItem, we'll set the width for all of these menu items.
In addition, we can now set .ItemHeight, since these are not menu headers.
Code:
Private Sub FileNew_MeasureItem(ByVal sender As Object, ByVal e As System.Windows.Forms.MeasureItemEventArgs) Handles FileNew.MeasureItem, _ FileOpen.MeasureItem, FileSave.MeasureItem, FileClose.MeasureItem e.ItemWidth = 72 e.ItemHeight = 24 End Sub
Then, in DrawItem we do our drawing.
We should first DirectCast the sender into a Menu object:
Dim M As MenuItem = DirectCast(sender, MenuItem)

Then, our drawing is exactly the same as it is in the first part.
The value of e.Bounds properly moves everything so that it does not fall into the place of one of the other menus. The only change that you might make is to draw M.Text in the .DrawString call (that's why the DirectCast is up there).
Code:
Private Sub FileNew_DrawItem(ByVal sender As Object, ByVal e As System.Windows.Forms.DrawItemEventArgs) Handles FileNew.DrawItem, _ FileOpen.DrawItem, FileSave.DrawItem, FileClose.DrawItem Dim M As MenuItem = DirectCast(sender, MenuItem) If (e.State And DrawItemState.Selected) = DrawItemState.Selected Then e.Graphics.FillRectangle(Brushes.LightCoral, e.Bounds) Else e.Graphics.FillRectangle(Brushes.LawnGreen, e.Bounds) End If e.Graphics.DrawString(M.Text, e.Font, Brushes.Brown, e.Bounds.X, e.Bounds.Y) End Sub
You'll even get to see your drawing fade out.

Notice that you are always using a Graphics object to do your drawing, so whatever you can draw with Graphics can be drawn on a menu... that includes Images (picture of a disk for Save, perhaps?), LinearGradientBrushes and PathGradientBrushes on your menus to give you that new office look, TextureBrushes so that your menu can have a background, and much more...

Attached are some menus that I've created.
Attached Files
File Type: zip Overdose.zip (27.4 KB, 185 views)
__________________

Iceplug, USN
Quadrill 1 Quadrill 2 (full) Quadrill 3 JumpCross .NET Website is ALIVE! - DL Platform Tour for VB.NET! Posting Guidelines Hint: Specify your location in your user cp profile if you want compassion!
Reply With Quote
  #2  
Old 10-13-2005, 06:41 AM
Iceplug's Avatar
IceplugUsing OwnerDraw For Good-Looking Controls Iceplug is offline
MetaCenturion

Retired Moderator
* Guru *
 
Join Date: Aug 2001
Location: Iowa, USA
Posts: 16,583
Smile OwnerDraw on Listboxes

OwnerDraw for listboxes is fairly similar to OwnerDraw for menus.

You use MeasureItem to get the size, and then DrawItem to draw the new element within the listbox.

A difference with the listbox however is that, to set the OwnerDraw properties of the listbox, you have to set the DrawMode of the listbox, in contrast to the OwnerDraw property of the menu component.

The DrawMode property of the listbox supports two OwnerDraw modes: OwnerDrawFixed and OwnerDrawVariable

OwnerDrawFixed

OwnerDrawFixed means that you cannot specify the size of the item within the listbox... this means that you don't even have to bother with the MeasureItem event and you can go directly to DrawItem. The items are all regular-size.

So, in the DrawItem, you draw the listbox items:
Code:
Private Sub LB_DrawItem(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DrawItemEventArgs) Handles LB.DrawItem e.DrawBackground() If e.Index >= 0 Then e.Graphics.DrawString(LB.Items(e.Index).ToString(), LB.Font, Brushes.Black, e.Bounds.X, e.Bounds.Y) End If End Sub
You will need the If e.Index >= 0 Then line if you are planning to remove things from the listbox.

Again, it's a graphics object, so you can draw whatever you need.

If (e.State And DrawItemState.Selected) = DrawItemState.Selected Then
to check this listbox item's state.

e.DrawBackground() draws the regular background for regular listboxes.

You can make your own by checking the state property.
Code:
If (e.State And DrawItemState.Selected) = DrawItemState.Selected Then e.Graphics.FillRectangle(Brush2, e.Bounds) Else e.Graphics.FillRectangle(Brush1, e.Bounds) End If

OwnerDrawVariable
This one lets you set the height of the entry within the listbox. So, you must handle the MeasureItem event for Listboxes that have a DrawMode of OwnerDrawVariable.

The drawings are made the same way:
Code:
If (e.State And DrawItemState.Selected) = DrawItemState.Selected Then e.Graphics.FillRectangle(Brush2, e.Bounds) Else e.Graphics.FillRectangle(Brush1, e.Bounds) End If

And that's it.

Check out the attachment below - I have a listbox with a background image on it and a listbox that lists the fonts drawn in their own font, just like in MS Word (except with a listbox instead of a combobox).
Attached Files
File Type: zip Overdos2.zip (35.4 KB, 135 views)
__________________

Iceplug, USN
Quadrill 1 Quadrill 2 (full) Quadrill 3 JumpCross .NET Website is ALIVE! - DL Platform Tour for VB.NET! Posting Guidelines Hint: Specify your location in your user cp profile if you want compassion!
Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

Advertisement:





Free Publications
The ASP.NET 2.0 Anthology
101 Essential Tips, Tricks & Hacks - Free 156 Page Preview. Learn the most practical features and best approaches for ASP.NET.
subscribe
Programmers Heaven C# School Book -Free 338 Page eBook
The Programmers Heaven C# School book covers the .NET framework and the C# language.
subscribe
Build Your Own ASP.NET 3.5 Web Site Using C# & VB, 3rd Edition - Free 219 Page Preview!
This comprehensive step-by-step guide will help get your database-driven ASP.NET web site up and running in no time..
subscribe
Using OwnerDraw For Good-Looking Controls
Using OwnerDraw For Good-Looking Controls
Using OwnerDraw For Good-Looking Controls Using OwnerDraw For Good-Looking Controls
Using OwnerDraw For Good-Looking Controls
Using OwnerDraw For Good-Looking Controls
Using OwnerDraw For Good-Looking Controls Using OwnerDraw For Good-Looking Controls Using OwnerDraw For Good-Looking Controls Using OwnerDraw For Good-Looking Controls Using OwnerDraw For Good-Looking Controls Using OwnerDraw For Good-Looking Controls Using OwnerDraw For Good-Looking Controls
Using OwnerDraw For Good-Looking Controls
Using OwnerDraw For Good-Looking Controls
 
Using OwnerDraw For Good-Looking Controls
Using OwnerDraw For Good-Looking Controls
 
-->