/// <summary>
        /// Reevaluates the DockPosition and Bounds
        /// and raises the PositionOrSizeChanged event if necessary
        /// </summary>
        public void Update(IntPtr childHwnd)
        {
            var oldDockPosition = DockPosition;
            var oldBounds       = Bounds;

            if (childHwnd == IntPtr.Zero)
            {
                DockPosition = TaskbarUtils.GetTaskbarDockPosition(Handle);
                Bounds       = WindowUtils.GetWindowBounds(Handle);

                // raised by the main taskbar, check if it was moved
                if (oldDockPosition != DockPosition || oldBounds != Bounds)
                {
                    RaisePositionOrSizeChanged(IntPtr.Zero);
                }
            }
            else
            {
                if (ObservedChildBoundChanges.TryGetValue(childHwnd, out Rectangle childRect))
                {
                    // check if the child bounds have really changed
                    var screenRect = WindowUtils.GetWindowBounds(childHwnd);

                    if (!screenRect.Equals(childRect))
                    {
                        RaisePositionOrSizeChanged(childHwnd);
                    }
                }
            }
        }
        /// <summary>
        /// Show the primary taskbar's calendar flyout at the given location with the given alignment
        /// </summary>
        public static void ShowCalendarFlyOut(Rectangle alignTo, FlyoutAlignment alignment)
        {
            // get all window handles which have the same class as the
            // flyout, so that we know these are not the flyout
            var nonFlyoutHandles = WindowUtils.ListWindowsWithClass(CalendarFlyoutClassName);

            // invoke the primary taskbar's calendar flyout
            if (TaskbarUtils.InvokeCalendarFlyOut())
            {
                // wait for it to open (max. 2 seconds)
                IntPtr flyoutHwnd = IntPtr.Zero;
                int    start      = Environment.TickCount;
                while (flyoutHwnd == IntPtr.Zero && (Environment.TickCount - start <= 2000))
                {
                    flyoutHwnd = TaskbarUtils.GetCalendarFlyoutHwnd(nonFlyoutHandles);
                }

                if (flyoutHwnd != IntPtr.Zero)
                {
                    // and move it to this clock's location
                    NativeImports.RECT flyoutRect;
                    if (NativeImports.GetWindowRect(flyoutHwnd, out flyoutRect))
                    {
                        int flyoutWidth  = flyoutRect.Right - flyoutRect.Left;
                        int flyoutHeight = flyoutRect.Bottom - flyoutRect.Top;

                        switch (alignment)
                        {
                        case FlyoutAlignment.Below:
                            // place the calendar flyout below the clock
                            NativeImports.SetWindowPos(flyoutHwnd, IntPtr.Zero, alignTo.Right - flyoutWidth, alignTo.Bottom, 0, 0, NativeImports.SetWindowPosFlags.SWP_NOSIZE);
                            break;

                        case FlyoutAlignment.Above:
                            // place the calendar flyout above the clock
                            NativeImports.SetWindowPos(flyoutHwnd, IntPtr.Zero, alignTo.Right - flyoutWidth, alignTo.Top - flyoutHeight, 0, 0, NativeImports.SetWindowPosFlags.SWP_NOSIZE);
                            break;

                        case FlyoutAlignment.ToTheRight:
                            // place the calendar flyout to the right of the clock
                            NativeImports.SetWindowPos(flyoutHwnd, IntPtr.Zero, alignTo.Right, alignTo.Bottom - flyoutHeight, 0, 0, NativeImports.SetWindowPosFlags.SWP_NOSIZE);
                            break;

                        case FlyoutAlignment.ToTheLeft:
                            // place the calendar flyout to the left of the clock
                            NativeImports.SetWindowPos(flyoutHwnd, IntPtr.Zero, alignTo.Left - flyoutWidth, alignTo.Bottom - flyoutHeight, 0, 0, NativeImports.SetWindowPosFlags.SWP_NOSIZE);
                            break;
                        }
                    }
                }
            }
        }