- In the extension bar, click the AdBlock Plus icon
- Click the large blue toggle for this website
- Click refresh
- In the extension bar, click the AdBlock icon
- Under "Pause on this site" click "Always"
- In the extension bar, click on the Adguard icon
- Click on the large green toggle for this website
- In the extension bar, click on the Ad Remover icon
- Click "Disable on This Website"
- In the extension bar, click on the orange lion icon
- Click the toggle on the top right, shifting from "Up" to "Down"
- In the extension bar, click on the Ghostery icon
- Click the "Anti-Tracking" shield so it says "Off"
- Click the "Ad-Blocking" stop sign so it says "Off"
- Refresh the page
- In the extension bar, click on the uBlock Origin icon
- Click on the big, blue power button
- Refresh the page
- In the extension bar, click on the uBlock icon
- Click on the big, blue power button
- Refresh the page
- In the extension bar, click on the UltraBlock icon
- Check the "Disable UltraBlock" checkbox
- Please disable your Ad Blocker
- Disable any DNS blocking tools such as AdGuardDNS or NextDNS
- Disable any privacy or tracking protection extensions such as Firefox Enhanced Tracking Protection or DuckDuckGo Privacy.
If the prompt is still appearing, please disable any tools or services you are using that block internet ads (e.g. DNS Servers, tracking protection or privacy extensions).
Question
anog
Some of you have asked me how to create your own OwnerDrawn menus.
Since finding info on how to create my own menus was very hard, and I had tried everywhere (maybe i'm just dumb or unlucky..) and found nearly nothing, here is my tutorial. I hope you enjoy it!
This tutorial is NOT complete, so don't complain about it... I expect to complete it today or tomorrow, but decided to post what I already have so you can learn something, search the web or MSDN for it and maybe, who knows, you won't need the rest of the tutorial at all!
Request: Please DO post any errors you have found or any suggestions you have. If you can explain something better than me, please send me a PM with it and I will add it to this post and give you credit for it.
Also, if you want to, post screenshots of your own menus!
So.. here we go!
Understanding how Inheritance works
The first thing you need to understand is how Inheritance works in .Net.
Imagine this. You buy a brand new car. It has everything you need, so you use it as it is. But time goes by and you find you need somethings the car as it is can't give you, maybe you need a radio and a GPS or you feel you need to completely change the looks of the car.
To do this, you have two options:
Which option do you think is the best? With the first you have to recreate most of what you already have and which is want you want. The car you have already has seats, wheels, direction, engine, etc. So why recreate all that?
With the second options, however, this is solved. You use want you want from the car, and create ONLY what the car does not give you.
This is what inheritance is all about. You take something with basic functionality and you take it from there, adding or changing things as you please.
Indeed, when you create a new windows form, the first lines of code are
Public Class Form1 Inherits System.Windows.Forms.Form
The first line says you are creating a new class called Form1, and the second line says that class inherits from System.Windows.Forms.Form. That is to say, the basic funcionality of the form is already there (like the title bar and the minimize, maximize and close buttons and the area where you place your controls) and you just have to build upon it.
The same happens when you create your own menuitem. The basic funcionality, like controling the mouseovers and click and etc are alredy in the Mouseitem class. If you inherit it, you won't have to do it all through Windows APIs and your work is greatly simplified.
I could have easily skipped this and you would not lose much, but I preferred to add it so you can understand better how the whole thing works.
So, the first step to create your own menus is a very simple one: Create a new class and inherit from the MenuItem class.
So, create a Windows Forms project in Visual Basic. Add a new class to it. Finally inherit from the MenuItem class! Simple, isn't it?
You can also create a separate project so you can create a .Net Component and use those menus in different projects, but i'll cover that later on.
So far, your code should be something like
Public Class Menu1 Inherits System.Windows.Forms.MenuItem
Beeing, of course, Menu1 the name you want to give your own menus.
The basics of Ownerdrawn menus I - OnMeasureItem
Now that your class is created, you need to understand the basics of the Ownerdrawn menus.
One thing can easily see when using any application it that different menus have almost always different heights and different widths. That is to say, a menu with three items has a smaller witdh than a menu with 10 items, and that "this is my very long menu caption" and "file" would produce menus with very different widths.
So, before drawing your menu you have to measure it so that Windows can create the canvas where you will draw.
The measure is done overridding OnMeasureItem.
So, place the following code on your class.
Protected Overrides Sub OnMeasureItem(ByVal e As System.Windows.Forms.MeasureItemEventArgs) End Sub
(This is the same as chosing "(Overrides)" from the left drop down list and then chosing "OnMeasureItem" from the right drop down list)
As you can see, that sub has one parameter, e. It is through e that the measurement will be made. e has two properties, ItemHeight and ItemWidth, and it is by setting their values that the blank are where you draw will be created. It sums the Height of all the items and uses the width of the longest item.
However, these values will depend of several things, like how you wish to draw your menus (if you wish to add an icon you have to leave space for it, for instance) or the font you use.
I, for one, think it is best to create a Font variable in the class where you set the font you want to use. That way, you only have to change the code on one single place if you wish to change the font later on, and you can even create a property so you can change the code from VS.net IDE or at run time.
To create this variable, just type (outside of any "sub", of course...)
myFont being the name of the variable. And don't forget to set the font...
Now you need to check the lenght and width of the text using that font. If a font has size 8, it is smaller than a size 20 font.
So, a possibility for this would be
The MeasureString method returns the width and heigth of the rectangle containg a specific string, using a specific font. The last line checks if the MenuItem beeing measured has any child menuitems, and if so it adds 10 pixels to its width so there is space for the arrow to be drawn. If you go to the "File" menu in Windows Explorer, you will see that the "New" item has an arrow and that if you hover it, a new menu will appear. This is what I am referring to.
The basics of Ownerdrawn menus II - OnDrawItem
Now that you have the items measured, you need to draw them, which is done overriding the OnDrawItem sub.
So you should add a new sub, as shown below.
Protected Overrides Sub OnDrawItem(ByVal e As System.Windows.Forms.DrawItemEventArgs) End Sub
The drawing is handled one menu item at a time. So, if you have four menu items, for instance, "New", "Open", "Save" and "Close", this method will be called for each and every one of those items as each item has its own rectangle.
Remember the "e" object used in the OnMeasureItem? It will be used here as well, but for a different purpose. Here you use it to retreave the bounds of the item's rectangle and to draw to that rectangle using the "e"'s graphics object.
A simple way to draw the item's text to the rectangle would be
MyBrush is a new global variable I created. It is advisable to create brushes,pens, etc as global variables instead of creating new objects inside the sub.
Are you ready to test your menus? Here we go!
The basics of Ownerdrawn menus III - Using them on a form
Create a new form and add a new menus to it. Now go to code view and change all references to Windows.Forms.Windows.MenuItem to (your name here).
So if your class is named "MyMenu", you would have
Run your project. Open the menu and... nothing happens!
So what have you done wrong? Absolutely nothing.
You simply have to set the menu's "Ownerdraw" property to true. While this can be done in the IDE one menuitem at a time, there is a more efficient and quick way.
You simply use the "New" sub to set the menu item to Ownerdraw = true and to set a default font (or else the Myfont object is set to nothing and your program will crash).
If you run your program now, the menus will work. However, there are two problems.
These are very easy to fix, and that's what we will do now
(to be continued)
Andr? Nogueira
Edited by anogLink to comment
https://www.neowin.net/forum/topic/194617-vbnet-ownerdrawn-menus-tutorial/Share on other sites
6 answers to this question
Recommended Posts