Context menu manipulation
Hi,
I want to control the location of the context menu linked with a button in
VB.Net. The requirement is to be able to show the menu on clicking the button,
with x and y location as follows:
x: either at the left edge or the right edge of the button,
y: either starting at the botton edge of the button (for down context menu)
OR ending at the upper edge of the button (for up context menu).
Your suggestions for this would be highly appreciated
Thanks
Re: Context menu manipulation
If I understand your question correctly:
You need to create a rectangle that defines the area where the
the context menu is active(or can be shown). Defining this rectangle will
be your challenge, but the rectangle will give you X and Y points that you
are valid points that can respond to MouseEvents.
Then code some MouseEvents(Button1_MouseHover, Button1_MouseEnter, Button1_MouseDown)
that handle the event. If the Mouse is within your rectangle, the context
menu is active (you could use the Show Method).
The following comes from the .NET OnLine Help, but it gives some useful
hints about how to attack your problem. It overrides the base class event
OnMouseMove.
Protected Overrides Sub OnMouseMove(ByVal e As MouseEventArgs)
SetDragValue(New Point(e.X, e.Y))
End Sub
Private Sub SetDragValue(ByVal mouseLocation As Point)
Dim client As Rectangle = ClientRectangle
If (client.Contains(mouseLocation)) Then
If (client.Y <= mouseLocation.Y And mouseLocation.Y <= client.Y
+ client.Height) Then
If (mouseLocation.X <= client.X And mouseLocation.X >
client.X - LeftRightBorder) Then
Dim newDragValue As Integer = Min
If (newDragValue <> dragValue) Then
Dim old As Integer = dragValue
dragValue = newDragValue
OptimizedInvalidate(old, dragValue)
End If
ElseIf (mouseLocation.X >= client.X + client.Width And
mouseLocation.X < client.X + client.Width + LeftRightBorder) Then
Dim newDragValue As Integer = Max
If (newDragValue <> dragValue) Then
Dim old As Integer = dragValue
dragValue = newDragValue
OptimizedInvalidate(old, dragValue)
End If
End If
Else
If (dragValue <> Value) Then
Dim old As Integer = dragValue
dragValue = Value
OptimizedInvalidate(old, dragValue)
End If
End If
End If
End Sub
Re: Context menu manipulation
Thanks a lot for your reply but this is not what I am trying to do. I am actually
creating a MS Money style menubutton user control, a context menu would be
assigned to it and properties would be exposed like "MenuAlignment" which
would be left/right and "MenuDirection" which could be Up/Down. Now based
on what the user chooses, when this button is clicked run time then I have
to show the context menu based on the properties specified. Now I am using
the "Show" method of context menu but the problem is that with it just the
top left corner of the context menu is configured. So if someone chooses
alignment as left and direction as top then the show method would be passed
the point as 0,0 which would start the context menu from the top left edge
of the button and would thus overlap the button. Instead I need a way to
either draw the whole menu dynamically or somehow manipulate the location
of the menu so that the bottom edge of the menu lies on the top edge of the
button.
This could be confusing but imagine a simple clickable button which has a
image pointing up or down at left or right side and when you click on that
button the context menu shows up.
Please help.
"PWilmarth" <pwilmarth80231@msn.com> wrote:
>
>If I understand your question correctly:
>
>
>You need to create a rectangle that defines the area where the
>the context menu is active(or can be shown). Defining this rectangle will
>be your challenge, but the rectangle will give you X and Y points that you
>are valid points that can respond to MouseEvents.
>
>Then code some MouseEvents(Button1_MouseHover, Button1_MouseEnter, Button1_MouseDown)
>that handle the event. If the Mouse is within your rectangle, the context
>menu is active (you could use the Show Method).
>
>The following comes from the .NET OnLine Help, but it gives some useful
>hints about how to attack your problem. It overrides the base class event
>OnMouseMove.
>
> Protected Overrides Sub OnMouseMove(ByVal e As MouseEventArgs)
> SetDragValue(New Point(e.X, e.Y))
> End Sub
>
>Private Sub SetDragValue(ByVal mouseLocation As Point)
>
> Dim client As Rectangle = ClientRectangle
>
> If (client.Contains(mouseLocation)) Then
>
> If (client.Y <= mouseLocation.Y And mouseLocation.Y <=
client.Y
>+ client.Height) Then
> If (mouseLocation.X <= client.X And mouseLocation.X
>
>client.X - LeftRightBorder) Then
> Dim newDragValue As Integer = Min
> If (newDragValue <> dragValue) Then
> Dim old As Integer = dragValue
> dragValue = newDragValue
> OptimizedInvalidate(old, dragValue)
> End If
>
> ElseIf (mouseLocation.X >= client.X + client.Width And
>mouseLocation.X < client.X + client.Width + LeftRightBorder) Then
> Dim newDragValue As Integer = Max
> If (newDragValue <> dragValue) Then
> Dim old As Integer = dragValue
> dragValue = newDragValue
> OptimizedInvalidate(old, dragValue)
> End If
> End If
>
> Else
> If (dragValue <> Value) Then
> Dim old As Integer = dragValue
> dragValue = Value
> OptimizedInvalidate(old, dragValue)
> End If
>
> End If
>
> End If
>
> End Sub
>
>
>
>
>
>
>
>
Re: Context menu manipulation
It sounds like you need to pass a negative number to the show method. The
ideal solution would be based on the height of the context menu and you can
access this property, but I'm not sure that the number passed back to you
is in pixels. It is definitely an integer (when I played around with this,
I got 19 for the context menu. You can access this number like this piece
of code:
myMenuHeight= System.Windows.Forms.SystemInformation.MenuHeight.ToString
Now I'm not sure if this is the height for each menu item in your context
menu or the total height(I suspect it is the menu height for each menu item).
You are correct that point = (0,0) will align the top left corner of the
context menu to the top left corner of the button. If you want to align the
bottom of the context menu to the top of the button, you need to subtract
the context menu height from 0 (this is the most accurate method for positioning
the context menu) to create a new Y. You could try something like this:
dim X as integer = 0
dim Y as integer = 0
dim m_Point as Point = new Point(X, Y - System.Windows.Forms.SystemInformation.MenuHeight)
ContextMenu.Show(Button, m_Point)
This will move the context menu up, but once again, you may need to make
some adjustments by multiplying the MenuHeight by the number of menu items
(I had only one Menu Item in my list.
When I multiplied the MenuHeight by 1.25, I got a pretty good alignment with
the bottom of the context menu and the top of the button.
I haven't been able to ascertain anyway to determine the context menu width,
but you can also create a negative number based on the button width if you
need to move the context menu to the left of the button.
Let me know if this approximates the solution you are looking for. This was
definitely an interesting problem to think through. If you find another solution
(or better solution) let me know.
PW
>
>Thanks a lot for your reply but this is not what I am trying to do. I am
actually
>creating a MS Money style menubutton user control, a context menu would
be
>assigned to it and properties would be exposed like "MenuAlignment" which
>would be left/right and "MenuDirection" which could be Up/Down. Now based
>on what the user chooses, when this button is clicked run time then I have
>to show the context menu based on the properties specified. Now I am using
>the "Show" method of context menu but the problem is that with it just the
>top left corner of the context menu is configured. So if someone chooses
>alignment as left and direction as top then the show method would be passed
>the point as 0,0 which would start the context menu from the top left edge
>of the button and would thus overlap the button. Instead I need a way to
>either draw the whole menu dynamically or somehow manipulate the location
>of the menu so that the bottom edge of the menu lies on the top edge of
the
>button.
>
>This could be confusing but imagine a simple clickable button which has
a
>image pointing up or down at left or right side and when you click on that
>button the context menu shows up.
>
>Please help.
>
>
>"PWilmarth" <pwilmarth80231@msn.com> wrote:
>>
>>If I understand your question correctly:
>>
>>
>>You need to create a rectangle that defines the area where the
>>the context menu is active(or can be shown). Defining this rectangle will
>>be your challenge, but the rectangle will give you X and Y points that
you
>>are valid points that can respond to MouseEvents.
>>
>>Then code some MouseEvents(Button1_MouseHover, Button1_MouseEnter, Button1_MouseDown)
>>that handle the event. If the Mouse is within your rectangle, the context
>>menu is active (you could use the Show Method).
>>
>>The following comes from the .NET OnLine Help, but it gives some useful
>>hints about how to attack your problem. It overrides the base class event
>>OnMouseMove.
>>
>> Protected Overrides Sub OnMouseMove(ByVal e As MouseEventArgs)
>> SetDragValue(New Point(e.X, e.Y))
>> End Sub
>>
>>Private Sub SetDragValue(ByVal mouseLocation As Point)
>>
>> Dim client As Rectangle = ClientRectangle
>>
>> If (client.Contains(mouseLocation)) Then
>>
>> If (client.Y <= mouseLocation.Y And mouseLocation.Y <=
>client.Y
>>+ client.Height) Then
>> If (mouseLocation.X <= client.X And mouseLocation.X
>>
>>client.X - LeftRightBorder) Then
>> Dim newDragValue As Integer = Min
>> If (newDragValue <> dragValue) Then
>> Dim old As Integer = dragValue
>> dragValue = newDragValue
>> OptimizedInvalidate(old, dragValue)
>> End If
>>
>> ElseIf (mouseLocation.X >= client.X + client.Width
And
>>mouseLocation.X < client.X + client.Width + LeftRightBorder) Then
>> Dim newDragValue As Integer = Max
>> If (newDragValue <> dragValue) Then
>> Dim old As Integer = dragValue
>> dragValue = newDragValue
>> OptimizedInvalidate(old, dragValue)
>> End If
>> End If
>>
>> Else
>> If (dragValue <> Value) Then
>> Dim old As Integer = dragValue
>> dragValue = Value
>> OptimizedInvalidate(old, dragValue)
>> End If
>>
>> End If
>>
>> End If
>>
>> End Sub
>>
>>
>>
>>
>>
>>
>>
>>
>
Re: Context menu manipulation
I tried this with 3 menu items.
You do need to multiply the number of menu items in your longest column by
the menuHeight and then make some adjustments so the bottom of the context
menu aligns better visually. I found that adding 0.25 or 0.3 (I'm calling
this "the adjustment factor") to the product makes the context menu line
up pretty nicely.
Re: Context menu manipulation
Hi,
Thank you so much for your effort, I was thinking on the same line, I tried
yesterday with VB5 and came to this formula to get the height on the menu:
(17 * aMenu.MenuItems.Count) + 4.5. After reading your post today I tried
using (System.Windows.Forms.SystemInformation.MenuHeight * aMenu.MenuItems.Count)in
this .net project but this is not getting accurate, I even tried adding .25/.3
etc. as adjustment factors but they do not seem to work, can you write what
exact formula you used. Also this and my above formula falls apart when there
are separators in the menu... any ideas about how to handle that.
Thank you so much, I really appreciate your help.
"PWilmarth" <pwilmarth80231@msn.com> wrote:
>
>I tried this with 3 menu items.
>
>You do need to multiply the number of menu items in your longest column
by
>the menuHeight and then make some adjustments so the bottom of the context
>menu aligns better visually. I found that adding 0.25 or 0.3 (I'm calling
>this "the adjustment factor") to the product makes the context menu line
>up pretty nicely.
Re: Context menu manipulation
Dim X As Integer = 0
Dim Y As Integer = -1 * (3 * System.Windows.Forms.SystemInformation.MenuHeight
+ 0.3)
Dim newPoint As Point = New Point(X, Y)
ContextMenu.Show(Button1, newPoint)
is the piece of code I use for 3 menu items.
However, I used your method, and it does adjust the context menu pretty well,
but I don't know how precise you want to be in the location of your context
menu. I found that you need to adjust the context menu by 7 or 8 for each
separator in you list (Don't count the separotors as menu Items, they are
smaller than one MenuItem). I have some thoughts about why this may be
and I think it has to do with the height of the border lines for the context
menu, plus some additional space between the last item in the menu and the
border (border height returns as 1).
PW
"nnch97" <vb.@127.0.0.1> wrote:
>
>Hi,
>
>Thank you so much for your effort, I was thinking on the same line, I tried
>yesterday with VB5 and came to this formula to get the height on the menu:
>(17 * aMenu.MenuItems.Count) + 4.5. After reading your post today I tried
>using (System.Windows.Forms.SystemInformation.MenuHeight * aMenu.MenuItems.Count)in
>this .net project but this is not getting accurate, I even tried adding
.25/.3
>etc. as adjustment factors but they do not seem to work, can you write what
>exact formula you used. Also this and my above formula falls apart when
there
>are separators in the menu... any ideas about how to handle that.
>
>Thank you so much, I really appreciate your help.
>
>"PWilmarth" <pwilmarth80231@msn.com> wrote:
>>
>>I tried this with 3 menu items.
>>
>>You do need to multiply the number of menu items in your longest column
>by
>>the menuHeight and then make some adjustments so the bottom of the context
>>menu aligns better visually. I found that adding 0.25 or 0.3 (I'm calling
>>this "the adjustment factor") to the product makes the context menu line
>>up pretty nicely.
>
Re: Context menu manipulation
Dim X As Integer = 0
Dim Y As Integer = -1 * (Number of Menu Items * System.Windows.Forms.SystemInformation.MenuHeight
+ 7.5 * Number of Separators)
Dim m_Point as Point = New Point(X, Y)
ContextMenu.Show(button, m_Point)
Is the precise code I used, but once again, I don't know how precise you
need to be in locating the bottom of your context menu.
PW
Re: Context menu manipulation
Ok, Thank you so much for your help.
"PWilmarth" <pwilmarth80231@msn.com> wrote:
>
> Dim X As Integer = 0
> Dim Y As Integer = -1 * (Number of Menu Items * System.Windows.Forms.SystemInformation.MenuHeight
>+ 7.5 * Number of Separators)
>Dim m_Point as Point = New Point(X, Y)
>ContextMenu.Show(button, m_Point)
>
>Is the precise code I used, but once again, I don't know how precise you
>need to be in locating the bottom of your context menu.
>
>PW