Is there a way to create an animation when a ContextMenuStrip is opened, like in the this image?
this animation is for WhatsApp right click.I have no idea how to do this.
You can use the AnimateWindow function with ToolStrips, which includes the ContextMenuStrip class, since these all have handles.
For example, you can reproduce the animation shown in the OP handling the MouseDown event of a Control:
Private Sub SomeControl_MouseDown(sender As Object, e As MouseEventArgs) Handles SomeControl.MouseDown
If e.Button = MouseButtons.Right Then
Dim ctrl = DirectCast(sender, Control)
Dim cms = ContextMenuStrip1
cms.Location = MousePosition
AnimateWindow(cms.Handle, 250, AW_VER_POSITIVE Or AW_HOR_POSITIVE)
cms.Show(ctrl, ctrl.PointToClient(MousePosition))
End If
End Sub
This implies that you have to handle the MouseDown event of each Control that needs an animated ContextMenuStrip. If it's just one, it may be acceptable. Or a bunch o Controls that can share the same MouseDown event.
But you cannot apply the animation to all Controls in a Form, setting the ContextMenuStrip to the Form class, for example.
It's probably better to build a Custom Control, inheriting ContextMenuStrip.
You can then add some Properties that allow to configure the ContextMenuStrip behavior, adding some animations that are supported.
I'm adding a few:
OpenDownwards
: as in the OP's sample imageOpenUpwards
: the oppositeExpand
: expand the menu from its centerSlide (self-explanatory):
SlideToRight
, SlideToLeft
SlideDownwards
, SlideUpwards
New Public Properties:
AnimationTime
: the speed of the animation, in millisecondsAnimationType
: the type of animation. ComboBox selectorAnimateInDesigner
: animate the ContextMenuStrip in the Form Designer. Makes it easier to configure it, since the animation is shown at design-time.True
to turn it on. You may want to turn it back off after the control is configured.Imports System.ComponentModel
Imports System.Runtime.InteropServices
Imports System.Windows.Forms
<DesignerCategory("code")>
Public Class ContextMenuStripAnimated
Inherits ContextMenuStrip
' Don't remove
Public Sub New()
End Sub
Public Sub New(container As IContainer)
Me.New()
If container Is Nothing Then
Throw New ArgumentNullException("container is null")
End If
container.Add(Me)
End Sub
Protected Overrides Sub OnOpening(e As CancelEventArgs)
If Not DesignMode OrElse AnimateInDesigner Then
Dim result = AnimateWindow(Handle, AnimationTime, AnimationType)
End If
MyBase.OnOpening(e)
End Sub
<DefaultValue(False)>
Public Property AnimateInDesigner As Boolean = False
<DefaultValue(AnimationMode.OpenDownwards)>
Public Property AnimationType As AnimationMode = AnimationMode.OpenDownwards
<DefaultValue(250)>
Public Property AnimationTime As UInteger = 250
<Flags()>
Public Enum AnimationMode As UInteger
CloseCentered = AW_CENTER Or AW_HIDE
CloseDownwards = AW_VER_POSITIVE Or AW_HOR_POSITIVE Or AW_HIDE
CloseUpwards = AW_VER_NEGATIVE Or AW_HOR_NEGATIVE Or AW_HIDE
OpenCentered = AW_CENTER
OpenDownwards = AW_HOR_POSITIVE Or AW_VER_POSITIVE
OpenUpwards = AW_HOR_NEGATIVE Or AW_VER_NEGATIVE
SlideToRight = AW_SLIDE Or AW_HOR_POSITIVE
SlideToLeft = AW_SLIDE Or AW_HOR_NEGATIVE
SlideDownwards = AW_SLIDE Or AW_VER_POSITIVE
SlideUpwards = AW_SLIDE Or AW_VER_NEGATIVE
Hide = AW_HIDE
End Enum
#Region "NativeMethods"
Private Const AW_HOR_POSITIVE As UInteger = &H1
Private Const AW_HOR_NEGATIVE As UInteger = &H2
Private Const AW_VER_POSITIVE As UInteger = &H4
Private Const AW_VER_NEGATIVE As UInteger = &H8
Private Const AW_CENTER As UInteger = &H10
Private Const AW_HIDE As UInteger = &H10000
Private Const AW_ACTIVATE As UInteger = &H20000
Private Const AW_SLIDE As UInteger = &H40000
Private Const AW_BLEND As UInteger = &H80000
<DllImport("user32.dll", SetLastError:=true)>
Private Shared Function AnimateWindow(hwnd As IntPtr, time As UInteger, flags As AnimationMode) As Boolean
End Function
#End Region
End Class
To add this new Control to the ToolBox:
ContextMenuStripAnimated
Imports
directivesC# version, just in case:
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Windows.Forms;
[DesignerCategory("code")]
public class ContextMenuStripAnimated : ContextMenuStrip
{
public ContextMenuStripAnimated() { }
public ContextMenuStripAnimated(IContainer container) : this()
{
if (container == null) {
throw new ArgumentNullException("container is null");
}
container.Add(this);
}
protected override void OnOpening(CancelEventArgs e)
{
if (!DesignMode || AnimateInDesigner) {
var result = AnimateWindow(Handle, AnimationTime, AnimationType);
}
base.OnOpening(e);
}
[DefaultValue(false)]
public bool AnimateInDesigner { get; set; } = false;
[DefaultValue(250)]
public uint AnimationTime { get; set; } = 250;
[DefaultValue(AnimationMode.OpenDownwards)]
public AnimationMode AnimationType { get; set; } = AnimationMode.OpenDownwards;
[Flags]
public enum AnimationMode : uint
{
CloseCentered = AW_CENTER | AW_HIDE
CloseDownwards = AW_VER_POSITIVE | AW_HOR_POSITIVE | AW_HIDE
CloseUpwards = AW_VER_NEGATIVE | AW_HOR_NEGATIVE | AW_HIDE
OpenCentered = AW_CENTER
OpenDownwards = AW_HOR_POSITIVE | AW_VER_POSITIVE
OpenUpwards = AW_HOR_NEGATIVE | AW_VER_NEGATIVE
SlideToRight = AW_SLIDE | AW_HOR_POSITIVE
SlideToLeft = AW_SLIDE | AW_HOR_NEGATIVE
SlideDownwards = AW_SLIDE | AW_VER_POSITIVE
SlideUpwards = AW_SLIDE | AW_VER_NEGATIVE
Hide = AW_HIDE
}
private const uint AW_HOR_POSITIVE = 0x1;
private const uint AW_HOR_NEGATIVE = 0x2;
private const uint AW_VER_POSITIVE = 0x4;
private const uint AW_VER_NEGATIVE = 0x8;
private const uint AW_CENTER = 0x10;
private const uint AW_HIDE = 0x10000;
private const uint AW_ACTIVATE = 0x20000;
private const uint AW_SLIDE = 0x40000;
private const uint AW_BLEND = 0x80000;
[DllImport("user32.dll", SetLastError = true)]
private static extern bool AnimateWindow(IntPtr hwnd, uint time, AnimationMode flags);
}