|
thank João Martins
this.menuItem2.OwnerDraw = true;
this.menuItem2.Shortcut = System.Windows.Forms.Shortcut.CtrlE;
this.menuItem2.Text = "MenuItem 2(&E)";
But Ctrl+E not Show
help me!
thank you!
-- modified at 1:11 Thursday 9th February, 2006
|
|
|
|
|
how can i change the MainMenu height?
|
|
|
|
|
Using e.Bounds.Height to create the Rectangle in OnDrawSpecial
will get ride of the 'horrible' white line (Hardcoding these things allways brings problems).
private void OnDrawSpecial(object sender, System.Windows.Forms.DrawItemEventArgs e)
{
Rectangle rc = new Rectangle(e.Bounds.X,e.Bounds.Y,this.ClientRectangle.Right-(e.Bounds.X-this.ClientRectangle.X-4),e.Bounds.Height);
LinearGradientBrush gbrush = new LinearGradientBrush(rc,grad1,grad2,LinearGradientMode.Vertical);
e.Graphics.FillRectangle(gbrush,rc);
}
}
Also, as pointed out, Hardcoding the Font is very bad :
- Font aFont = customItem.GetMainMenu().GetForm().Font;
Also Hardcoding the String Position is also not a good idea:
// Cast the sender to MenuItem so you can access text property.
MenuItem customItem = (MenuItem) sender;
Font aFont = customItem.GetMainMenu().GetForm().Font;
SizeF sz_String = e.Graphics.MeasureString(customItem.Text,aFont);
int i_Shift = (e.Bounds.Height-(int)sz_String.Height)/2;
// Create a Brush and a Font to draw the MenuItem
System.Drawing.Brush aBrush = System.Drawing.Brushes.Black;
StringFormat sf = new StringFormat();
sf.Alignment = StringAlignment.Center;
rc.Y+=i_Shift;
e.Graphics.DrawString(customItem.Text,aFont,aBrush,rc,sf);
rc.Y-=i_Shift;
Otherwise : exactly what I was looking for, Thanks.
Mark Johnson, Berlin Germany
mj10777@mj10777.de
|
|
|
|
|
This code doesn't work!
The line is still there. I tried to replace system color, but it causes change of menus in all other apps, so this method is extremely messy.
Does anybody know, how to kindly replace the line?
|
|
|
|
|
I think the code will work with Windows 'Classic' theme set (Display Properties->Themes), but not with Windows XP themes.
The only way I've found to remove the white line is to draw over it by using nonclient painting routines, i.e. overriding WndProc() on the main form then using Win32 code to catch the WM_NCPAINT / WM_NCACTIVATE messages, then calling a procedure to draw a line that matches the background color when I catch them. Lots o' fun.
|
|
|
|
|
Hii there.
Your article was really helpfull, but Im having a problem now.. when I maximize or when I restore my program from the system tray (by double clicking on it) the whole menu is not colored, only the area of the menu items.
is there anyway I can fix this?
Thanks
Arfeen
|
|
|
|
|
To tell you the truth I have no idea.
I tottaly stopped programming more than 6 months ago.
It's all very blury for me now, even C++ witch was my favorite.
Maybe someone else can help you out.
Sorry
Best regards.
Há gajos pá, que falam, falam, falam, falam, falam, falam e não dizem nada e eu fico chateado, com certeza que fico chateado...ah.
|
|
|
|
|
Dim area As Rectangle = New Rectangle(e.Bounds.X, e.Bounds.Y, (Me.ClientRectangle.Right _
- (e.Bounds.X _
- (Me.ClientRectangle.X + 3))), 19)
On OnDrawExtra Replace the code of example with this
Hope it helps
|
|
|
|
|
You are providing good information to the newbies, however, you should mention that hardcoding the Font is not a good idea.
Especially within the OnMeasureItem, because you can't get in from the method itself. The DrawItemEventArgs has a Font property, but the MeasureItemEventArgs doesn't.
Without the font, it's pretty hard to measure an item.
|
|
|
|
|
Thanks for a great article. Have you come up with a solution to "that 'horrible' white line under the menu" ?
Does anyone know how/where the standard main menu background is actually drawn ? It's not a window so you can't mess with the non-client area which would be the usual way.
Thanks
Jon
|
|
|
|
|
To solve your problem, you should use SetSysColors. First, you need to save the color change it in your program and use it. At exit you should restore it. Also you can use with GetProfileString.
Anyway... the code is (only to put the color, to get the color search GetSysColors)
// Importing the function:
[DllImport("user32.dll")]
static extern bool SetSysColors(int cElements, int [] lpaElements, uint [] lpaRgbValues);
//set color.
System.Drawing.Color NewColor = System.Drawing.SystemColors.Control;
//4 represents the value of COLOR_MENU. For another changes, search on the net please.
int[] elements = {4};
//Creating an array because the function wants this.
uint[] acolors = {(uint)System.Drawing.ColorTranslator.ToWin32(NewColor)};
//applying the modifications
SetSysColors(elements.Length, elements, colors);
WARNING: YOU SHOULD RESTORE THE ORIGINAL COLOR. IF NOT, WINDOWS WILL USE IT AFTER THE PROGRAM IS CLOSED.
Radu Cosoveanu
Project Manager
ELink Telecom,
Your OutSourcing Company
|
|
|
|
|
Hi,
I am trying to convert the code in this document: http://www.codeproject.com/cs/miscctrl/custommenu.asp[^] into VB.net instead of C#. I have got most of it done but I am missing the final step, or at least I hope it is the final step. In the article all the menuitems have the following two events added:
this.menuItem3.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.OnDrawItemSec);
this.menuItem3.MeasureItem += new System.Windows.Forms.MeasureItemEventHandler(this.OnMeasureItemSec);
When I look at the source article used for this article, the author writes about going to the eventtab on each menuitem. I am guessing this is typically C# as I cannot find it in VB.net. So can anyone please tell me how to do this?
Thanks
David J
Think, try, think, think, try, think, think, think, try, ASK, think, try, advance on step and start over...
|
|
|
|
|
Hi,
VB .NET uses a different approach concerning events. You don't assign an event to be handled by a function yourself. Take a look at the last thing that appears at the end of the header of every function that is called when an event occurs. Double click your main form for example and you will be given a Form_Load(...) Handles Form1.Load. This is the only thing that tells the compiler to execute this function when the form loads. Try removing it and you'll see it for yourself, it won't be called. As a result, you should create your function and write after the header Handles AnyControl.AnyEvent
As you would have to write the parameter list for yourself, you could just select from the combo box on the top left of the code editor window and select the control to which you want to create an event handler. Then, on the combo box on the right you should select the event to be handled. That's it!
Hope this helps,
brazilianDudi
|
|
|
|
|
Thanks Dudi,
I was thinking in that direction, but I was thrown off by the way C# was doing it. This makes it all clear. One other question, if for instance you would have to use the same handler for a lot of similar controls, is it then possible to create one generic one preventing you having to write
DRAW_ITEM(...) Handles ITEM1.Draw
DRAW_ITEM(...) Handles ITEM2.Draw
DRAW_ITEM(...) Handles ITEM3.Draw
Etc etc
as these would point all to the same sub
Thanks
DJ
Think, try, think, think, try, think, think, think, try, ASK, think, try, advance on step and start over...
|
|
|
|
|
Hey,
You can easily do that by typing the various events separated by a comma.
The example above would become:
DRAWITEM(...) Handles Item1.Draw, Item2.Draw, Item3.Draw and so on.
You could also write each of the events to be handled in a different line to make the code more readable, for example:
<br />
DRAWITEM(...)Handles Item1.Draw, _<br />
Item2.Draw, _<br />
Item3.Draw ' and so on<br />
To make it look better, IMHO, you should put an offset (of spaces) to make the second, third .... lines match the position of the first Handles.
The "_" character in the end of each line is just a little something to tell the compiler that the instruction continues on the next line, as in VB there would be no way of writing multi-line statements because it doesn't use anything like the ; in C(++) or C#.
brazilianDudi
|
|
|
|
|
Hi,
Your suggestions have helped a lot, just one or two things left.....
For now do you know how you would translate the following?
MenuItem customItem = (MenuItem) sender;
I got as far as:
Dim CustomItem as MenuItem = sender
This seems to work but I am not sure if this is correct
Thanks
Think, try, think, think, try, think, think, think, try, ASK, think, try, advance on step and start over...
|
|
|
|
|
Check out this article
VB cuting edge menu
It is a more advanced customizable Menu with a sample code in VisualBasic.
I've already made the conversion to C# but I haven't had the time to write the article. I think it's what you've been looking for.
Há gajos pá, que falam, falam, falam, falam, falam, falam e não dizem nada e eu fico chateado, com certeza que fico chateado...ah.
|
|
|
|
|
I mixed the two articles in one. I used the cuting edge menu to draw the inner items of the menu and i extended its capabilities by adapting the code in this article (Customizable MainMenu on C#) to draw the top level items and the menu bar.
Also, if still having problems converting things from C# to VB check out this: http://authors.aspalliance.com/aldotnet/examples/translate.aspx Just copy-paste
Greetings.
|
|
|
|
|
That would be:
Dim CustomItem as MenuItem = CType(Sender,MenuItem)
|
|
|
|
|
Hi,
Very good article.
I want to create a MainMenu that starts with an offset from the left top corner of the screen.
any suggestions?
|
|
|
|
|
If you want to make an offset to the right yes you can. You can create a 1º main menu item and disable it (like the extra main menu item I did to paint the remainig menu bar) but this time you have to define a measure(your offset) to this menu item.
Try this:
private void OnDrawOffset(object sender,
System.Windows.Forms.DrawItemEventArgs e)
{
Rectangle rc = new Rectangle(e.Bounds.X ,
e.Bounds.Y, e.Bounds.Width, e.Bounds.Height);
e.Graphics.FillRectangle(new SolidBrush(The menu color),rc);
}
And the measure function
private void OnMeasureOffset(object sender,
System.Windows.Forms.MeasureItemEventArgs e)
{
e.ItemWidth=(you offset to the right);
e.ItemHeight=20;
}
I haven't tried this code but I think it works fine.
|
|
|
|
|
Thanks
It's working great!
|
|
|
|
|
Add the following line to set the HotKeyPrefix property of the StringFormat object in the two places it's created.
sf.HotkeyPrefix = System.Drawing.Text.HotkeyPrefix.Show;
Eric
|
|
|
|
|
Works fine.
Thanks for the tip.
|
|
|
|
|
Talking about hotkeys... I suggest you have to override all arrow keyboard events as well in order to work from a keyboard...
|
|
|
|
|