Beispiel #1
0
        internal void DrawSingleCommand(Graphics g, DrawCommand dc, bool tracked)
        {
            Rectangle drawRect = dc.DrawRect;
            MenuCommand mc = dc.MenuCommand;

            // Copy the rectangle used for drawing cell
            Rectangle shadowRect = drawRect;

            // Expand to right and bottom to cover the area used to draw shadows
            shadowRect.Width += _shadowGap;
            shadowRect.Height += _shadowGap;

            if (!dc.Separator)
            {
                Rectangle textRect;

                // Text rectangle size depends on type of draw command we are drawing
                if (dc.Chevron)
                {
                    // Create chevron drawing rectangle
                    textRect = new Rectangle(drawRect.Left + _lengthGap, drawRect.Top + _boxExpandUpper,
                                             drawRect.Width - _lengthGap * 2, drawRect.Height - (_boxExpandUpper * 2));
                }
                else
                {
                    // Create text drawing rectangle
                    textRect = new Rectangle(drawRect.Left + _lengthGap, drawRect.Top + _lengthGap,
                                             drawRect.Width - _lengthGap * 2, drawRect.Height - _lengthGap * 2);
                }

                if (dc.Enabled)
                {
                    // Draw selection
                    if (tracked)
                    {
                        Rectangle boxRect;

                        // Create the rectangle for box around the text
                        if (_direction == Direction.Horizontal)
                        {
                            boxRect = new Rectangle(textRect.Left - _boxExpandSides,
                                                    textRect.Top - _boxExpandUpper,
                                                    textRect.Width + _boxExpandSides * 2,
                                                    textRect.Height + _boxExpandUpper);
                        }
                        else
                        {
                            if (!dc.Chevron)
                            {
                                boxRect = new Rectangle(textRect.Left,
                                                        textRect.Top - _boxExpandSides,
                                                        textRect.Width - _boxExpandSides,
                                                        textRect.Height + _boxExpandSides * 2);
                            }
                            else
                                boxRect = textRect;
                        }

                        switch(_style)
                        {
                            case VisualStyle.IDE:
                                if (_selected)
                                {
                                    // Fill the entire inside
                                    g.FillRectangle(Brushes.White, boxRect);
                                    g.FillRectangle(_controlLBrush, boxRect);

                                    Color extraColor = Color.FromArgb(64, 0, 0, 0);
                                    Color darkColor = Color.FromArgb(48, 0, 0, 0);
                                    Color lightColor = Color.FromArgb(0, 0, 0, 0);

                                    int rightLeft = boxRect.Right + 1;
                                    int rightBottom = boxRect.Bottom;

                                    if (_drawUpwards && (_direction == Direction.Horizontal))
                                    {
                                        // Draw the box around the selection area
                                        using(Pen dark = new Pen(ControlPaint.Dark(_selectedBackColor)))
                                            g.DrawRectangle(dark, boxRect);

                                        if (dc.SubMenu)
                                        {
                                            // Right shadow
                                            int rightTop = boxRect.Top;
                                            int leftLeft = boxRect.Left + _shadowGap;

                                            // Bottom shadow
                                            int top = boxRect.Bottom + 1;
                                            int left = boxRect.Left + _shadowGap;
                                            int width = boxRect.Width + 1;
                                            int height = _shadowGap;

                                            Brush rightShadow;
                                            Brush bottomLeftShadow;
                                            Brush bottomShadow;
                                            Brush bottomRightShadow;

                                            // Decide if we need to use an alpha brush
                                            if (_supportsLayered)
                                            {
                                                // Create brushes
                                                rightShadow = new LinearGradientBrush(new Point(rightLeft, 9999),
                                                                                      new Point(rightLeft + _shadowGap, 9999),
                                                                                      darkColor, lightColor);

                                                bottomLeftShadow = new LinearGradientBrush(new Point(left + _shadowGap, top - _shadowGap),
                                                                                           new Point(left, top + height),
                                                                                           extraColor, lightColor);

                                                bottomRightShadow = new LinearGradientBrush(new Point(left + width - _shadowGap - 2, top - _shadowGap - 2),
                                                                                            new Point(left + width, top + height),
                                                                                            extraColor, lightColor);

                                                bottomShadow = new LinearGradientBrush(new Point(9999, top),
                                                                                       new Point(9999, top + height),
                                                                                       darkColor, lightColor);
                                            }
                                            else
                                            {
                                                rightShadow = new SolidBrush(SystemColors.ControlDark);
                                                bottomLeftShadow = rightShadow;
                                                bottomShadow = rightShadow;
                                                bottomRightShadow = rightShadow;
                                            }

                                            // Draw each part of the shadow area
                                            g.FillRectangle(rightShadow, new Rectangle(rightLeft, rightTop, _shadowGap,  rightBottom - rightTop + 1));
                                            g.FillRectangle(bottomLeftShadow, left, top, _shadowGap, height);
                                            g.FillRectangle(bottomRightShadow, left + width - _shadowGap, top, _shadowGap, height);
                                            g.FillRectangle(bottomShadow, left + _shadowGap, top, width - _shadowGap * 2, height);

                                            // Dispose of brush objects
                                            if (_supportsLayered)
                                            {
                                                rightShadow.Dispose();
                                                bottomLeftShadow.Dispose();
                                                bottomShadow.Dispose();
                                                bottomRightShadow.Dispose();
                                            }
                                            else
                                                rightShadow.Dispose();
                                        }
                                    }
                                    else
                                    {
                                        // Draw the box around the selection area
                                        using(Pen dark = new Pen(ControlPaint.Dark(_selectedBackColor)))
                                            g.DrawRectangle(dark, boxRect);

                                        if (dc.SubMenu)
                                        {
                                            if (_direction == Direction.Horizontal)
                                            {
                                                // Remove the bottom line of the selection area
                                                g.DrawLine(Pens.White, boxRect.Left, boxRect.Bottom, boxRect.Right, boxRect.Bottom);
                                                g.DrawLine(_controlLPen, boxRect.Left, boxRect.Bottom, boxRect.Right, boxRect.Bottom);

                                                int rightTop = boxRect.Top + _shadowYOffset;

                                                Brush shadowBrush;

                                                // Decide if we need to use an alpha brush
                                                if (_supportsLayered && (_style == VisualStyle.IDE))
                                                {
                                                    using(LinearGradientBrush topBrush = new LinearGradientBrush(new Point(rightLeft - _shadowGap, rightTop + _shadowGap),
                                                                                                                 new Point(rightLeft + _shadowGap, rightTop),
                                                                                                                 extraColor, lightColor))
                                                    {
                                                        g.FillRectangle(topBrush, new Rectangle(rightLeft, rightTop, _shadowGap, _shadowGap));

                                                        rightTop += _shadowGap;
                                                    }

                                                    shadowBrush = new LinearGradientBrush(new Point(rightLeft, 9999),
                                                                                          new Point(rightLeft + _shadowGap, 9999),
                                                                                          darkColor, lightColor);
                                                }
                                                else
                                                    shadowBrush = new SolidBrush(SystemColors.ControlDark);

                                                g.FillRectangle(shadowBrush, new Rectangle(rightLeft, rightTop, _shadowGap, rightBottom - rightTop));

                                                shadowBrush.Dispose();
                                            }
                                            else
                                            {
                                                // Remove the right line of the selection area
                                                g.DrawLine(Pens.White, boxRect.Right, boxRect.Top, boxRect.Right, boxRect.Bottom);
                                                g.DrawLine(_controlLPen, boxRect.Right, boxRect.Top, boxRect.Right, boxRect.Bottom);

                                                int leftLeft = boxRect.Left + _shadowYOffset;

                                                Brush shadowBrush;

                                                // Decide if we need to use an alpha brush
                                                if (_supportsLayered && (_style == VisualStyle.IDE))
                                                {
                                                    using(LinearGradientBrush topBrush = new LinearGradientBrush(new Point(leftLeft + _shadowGap, rightBottom + 1 - _shadowGap),
                                                                                                                 new Point(leftLeft, rightBottom + 1 + _shadowGap),
                                                                                                                 extraColor, lightColor))
                                                    {
                                                        g.FillRectangle(topBrush, new Rectangle(leftLeft, rightBottom + 1, _shadowGap, _shadowGap));

                                                        leftLeft += _shadowGap;
                                                    }

                                                    shadowBrush = new LinearGradientBrush(new Point(9999, rightBottom + 1),
                                                                                          new Point(9999, rightBottom + 1 + _shadowGap),
                                                                                          darkColor, lightColor);
                                                }
                                                else
                                                    shadowBrush = new SolidBrush(SystemColors.ControlDark);

                                                g.FillRectangle(shadowBrush, new Rectangle(leftLeft, rightBottom + 1, rightBottom - leftLeft - _shadowGap, _shadowGap));

                                                shadowBrush.Dispose();
                                            }
                                        }
                                    }
                                }
                                else
                                {
                                    using (Pen selectPen = new Pen(_highlightBackDark))
                                    {
                                        // Draw the selection area in white so can alpha draw over the top
                                        g.FillRectangle(Brushes.White, boxRect);

                                        using (SolidBrush selectBrush = new SolidBrush(_highlightBackLight))
                                        {
                                            // Draw the selection area
                                            g.FillRectangle(selectBrush, boxRect);

                                            // Draw a border around the selection area
                                            g.DrawRectangle(selectPen, boxRect);
                                        }
                                    }
                                }
                                break;
                            case VisualStyle.Plain:
                                if (_plainAsBlock)
                                {
                                    using (SolidBrush selectBrush = new SolidBrush(_highlightBackDark))
                                        g.FillRectangle(selectBrush, drawRect);
                                }
                                else
                                {
                                    if (_selected)
                                    {
                                        using(Pen lighlight = new Pen(ControlPaint.LightLight(this.BackColor)),
                                                  dark = new Pen(ControlPaint.DarkDark(this.BackColor)))
                                        {
                                            g.DrawLine(dark, boxRect.Left, boxRect.Bottom, boxRect.Left, boxRect.Top);
                                            g.DrawLine(dark, boxRect.Left, boxRect.Top, boxRect.Right, boxRect.Top);
                                            g.DrawLine(lighlight, boxRect.Right, boxRect.Top, boxRect.Right, boxRect.Bottom);
                                            g.DrawLine(lighlight, boxRect.Right, boxRect.Bottom, boxRect.Left, boxRect.Bottom);
                                        }
                                    }
                                    else
                                    {
                                        using(Pen lighlight = new Pen(ControlPaint.LightLight(this.BackColor)),
                                                  dark = new Pen(ControlPaint.DarkDark(this.BackColor)))
                                        {
                                            g.DrawLine(lighlight, boxRect.Left, boxRect.Bottom, boxRect.Left, boxRect.Top);
                                            g.DrawLine(lighlight, boxRect.Left, boxRect.Top, boxRect.Right, boxRect.Top);
                                            g.DrawLine(dark, boxRect.Right, boxRect.Top, boxRect.Right, boxRect.Bottom);
                                            g.DrawLine(dark, boxRect.Right, boxRect.Bottom, boxRect.Left, boxRect.Bottom);
                                        }
                                    }
                                }
                                break;
                        }
                    }
                }

                if (dc.Chevron)
                {
                    // Draw the chevron image in the centre of the text area
                    int yPos = drawRect.Top;
                    int xPos = drawRect.X + ((drawRect.Width - _chevronLength) / 2);

                    // When selected...
                    if (_selected)
                    {
                        // ...offset down and to the right
                        xPos += 1;
                        yPos += 1;
                    }

                    g.DrawImage(_menuImages.Images[_chevronIndex], xPos, yPos);
                }
                else
                {
                    // Left align the text drawing on a single line centered vertically
                    // and process the & character to be shown as an underscore on next character
                    StringFormat format = new StringFormat();
                    format.FormatFlags = StringFormatFlags.NoClip | StringFormatFlags.NoWrap;
                    format.Alignment = StringAlignment.Center;
                    format.LineAlignment = StringAlignment.Center;
                    format.HotkeyPrefix = HotkeyPrefix.Show;

                    if (_direction == Direction.Vertical)
                        format.FormatFlags |= StringFormatFlags.DirectionVertical;

                    if (dc.Enabled && this.Enabled)
                    {
                        if (tracked && (_style == VisualStyle.Plain) && _plainAsBlock)
                        {
                            // Is the item selected as well as tracked?
                            if (_selected)
                            {
                                // Offset to show it is selected
                                textRect.X += 2;
                                textRect.Y += 2;
                            }

                            using (SolidBrush textBrush = new SolidBrush(_plainSelectedTextColor))
                                g.DrawString(mc.Text, this.Font, textBrush, textRect, format);
                        }
                        else
                        {
                            if (_selected && tracked)
                            {
                                using (SolidBrush textBrush = new SolidBrush(_selectedTextColor))
                                    g.DrawString(mc.Text, this.Font, textBrush, textRect, format);
                            }
                            else
                            {
                                if (tracked)
                                {
                                    using (SolidBrush textBrush = new SolidBrush(_highlightTextColor))
                                        g.DrawString(mc.Text, this.Font, textBrush, textRect, format);
                                }
                                else
                                {
                                    using (SolidBrush textBrush = new SolidBrush(_textColor))
                                        g.DrawString(mc.Text, this.Font, textBrush, textRect, format);
                                }
                            }
                        }
                    }
                    else
                    {
                        // Helper values used when drawing grayed text in plain style
                        Rectangle rectDownRight = textRect;
                        rectDownRight.Offset(1,1);

                        // Draw the text offset down and right
                        g.DrawString(mc.Text, this.Font, Brushes.White, rectDownRight, format);

                        // Draw then text offset up and left
                        using (SolidBrush grayBrush = new SolidBrush(SystemColors.GrayText))
                            g.DrawString(mc.Text, this.Font, grayBrush, textRect, format);
                    }
                }
            }
        }
        internal void DrawSingleCommand(Graphics g, DrawCommand dc, bool hotCommand)
        {
            Rectangle drawRect = dc.DrawRect;
            MenuCommand mc = dc.MenuCommand;

            // Remember some often used values
            int textGapLeft = _position[(int)_style, (int)PI.TextGapLeft];
            int imageGapLeft = _position[(int)_style, (int)PI.ImageGapLeft];
            int imageGapRight = _position[(int)_style, (int)PI.ImageGapRight];
            int imageLeft = drawRect.Left + imageGapLeft;

            // Calculate some common values
            int imageColWidth = imageGapLeft + _imageWidth + imageGapRight;

            int subMenuWidth = _position[(int)_style, (int)PI.SubMenuGapLeft] +
                               _position[(int)_style, (int)PI.SubMenuWidth] +
                               _position[(int)_style, (int)PI.SubMenuGapRight];

            int subMenuX = drawRect.Right -
                           _position[(int)_style, (int)PI.SubMenuGapRight] -
                           _position[(int)_style, (int)PI.SubMenuWidth];

            // Text drawing rectangle needs to know the right most position for drawing
            // to stop. This is the width of the window minus the relevant values
            int shortCutX = subMenuX -
                            _position[(int)_style, (int)PI.SubMenuGapLeft] -
                            _position[(int)_style, (int)PI.TextGapRight];

            // Is this item an expansion command?
            if (dc.Expansion)
            {
                Rectangle box = drawRect;

                // In IDE style the box is next to the image column
                if (_style == VisualStyle.IDE)
                {
                    // Reduce the box to take into account the column
                    box.X += imageColWidth;
                    box.Width -= imageColWidth;
                }

                // Find centre for drawing the image
                int xPos = box.Left + ((box.Width - _imageHeight) / 2);
                int yPos = box.Top + ((box.Height - _imageHeight) / 2);

                // Should the item look selected
                if (hotCommand)
                {
                    switch(_style)
                    {
                        case VisualStyle.IDE:
                            Rectangle selectArea = new Rectangle(drawRect.Left + 1, drawRect.Top,
                                                                 drawRect.Width - 3, drawRect.Height - 1);

                            using (Pen selectPen = new Pen(_highlightColorDark))
                            {
                                // Draw the selection area white, because we are going to use an alpha brush
                                using (SolidBrush whiteBrush = new SolidBrush(Color.White))
                                    g.FillRectangle(whiteBrush, selectArea);

                                using (SolidBrush selectBrush = new SolidBrush(_highlightColorLight))
                                {
                                    // Draw the selection area
                                    g.FillRectangle(selectBrush, selectArea);

                                    // Draw a border around the selection area
                                    g.DrawRectangle(selectPen, selectArea);
                                }
                            }
                            break;
                        case VisualStyle.Plain:
                            // Shrink the box to provide a small border
                            box.Inflate(-2, -2);

                            using (Pen lightPen = new Pen(ControlPaint.LightLight(_backColor)),
                                       darkPen = new Pen(ControlPaint.DarkDark(_backColor)))
                            {
                                g.DrawLine(lightPen, box.Right, box.Top, box.Left, box.Top);
                                g.DrawLine(lightPen, box.Left, box.Top, box.Left, box.Bottom);
                                g.DrawLine(darkPen, box.Left, box.Bottom, box.Right, box.Bottom);
                                g.DrawLine(darkPen, box.Right, box.Bottom, box.Right, box.Top);
                            }
                            break;
                    }
                }
                else
                {
                    switch(_style)
                    {
                        case VisualStyle.IDE:
                            // Fill the entire drawing area with white
                            g.FillRectangle(_controlLLBrush, new Rectangle(drawRect.Left + 1, drawRect.Top,
                                drawRect.Width - 1, drawRect.Height));

                            // Draw the image column background
                            g.FillRectangle(Brushes.White, new Rectangle(drawRect.Left, drawRect.Top,
                                                                         imageColWidth, drawRect.Height));

                            g.FillRectangle(_controlLBrush, new Rectangle(drawRect.Left, drawRect.Top,
                                                                          imageColWidth, drawRect.Height));
                            break;
                        case VisualStyle.Plain:
                            using(SolidBrush drawBrush = new SolidBrush(_backColor))
                                g.FillRectangle(drawBrush, new Rectangle(drawRect.Left, drawRect.Top,
                                                                         drawRect.Width, drawRect.Height));
                            break;
                    }

                }

                // Always draw the expansion bitmap
                g.DrawImage(_menuImages.Images[(int)ImageIndex.Expansion], xPos, yPos);
            }
            else
            {
                // Is this item a separator?
                if (dc.Separator)
                {
                    if (dc.VerticalSeparator)
                    {
                        switch(_style)
                        {
                            case VisualStyle.IDE:
                                // Draw the separator as a single line
                                using (Pen separatorPen = new Pen(ControlPaint.Dark(_backColor)))
                                    g.DrawLine(separatorPen, drawRect.Left, drawRect.Top, drawRect.Left, drawRect.Bottom);
                                break;
                            case VisualStyle.Plain:
                                ButtonBorderStyle bsInset = ButtonBorderStyle.Inset;
                                ButtonBorderStyle bsNone = ButtonBorderStyle.Inset;

                                Rectangle sepRect = new Rectangle(drawRect.Left + 1, drawRect.Top, 2, drawRect.Height);

                                // Draw the separator as two lines using Inset style
                                ControlPaint.DrawBorder(g, sepRect,
                                                        _backColor, 1, bsInset, _backColor, 0, bsNone,
                                                        _backColor, 1, bsInset, _backColor, 0, bsNone);
                                break;
                        }
                    }
                    else
                    {
                        switch(_style)
                        {
                            case VisualStyle.IDE:
                                // Draw the image column background
                                Rectangle imageCol = new Rectangle(drawRect.Left, drawRect.Top, imageColWidth, drawRect.Height);

                                g.FillRectangle(Brushes.White, imageCol);
                                g.FillRectangle(_controlLBrush, imageCol);

                                // Draw a separator
                                using (Pen separatorPen = new Pen(Color.FromArgb(75, _textColor)))
                                {
                                    // Draw the separator as a single line
                                    g.DrawLine(separatorPen,
                                               drawRect.Left + imageColWidth + textGapLeft, drawRect.Top + 2,
                                               drawRect.Right,
                                               drawRect.Top + 2);
                                }
                                break;
                            case VisualStyle.Plain:
                                if (dc.Infrequent && _highlightInfrequent)
                                {
                                    // Change background to be a lighter shade
                                    using(Brush drawBrush = new SolidBrush(ControlPaint.Light(_backColor)))
                                        g.FillRectangle(drawBrush, drawRect);
                                }

                                ButtonBorderStyle bsInset = ButtonBorderStyle.Inset;
                                ButtonBorderStyle bsNone = ButtonBorderStyle.Inset;

                                Rectangle sepRect = new Rectangle(drawRect.Left + 2, drawRect.Top + 2, drawRect.Width - 4, 2);

                                // Draw the separator as two lines using Inset style
                                ControlPaint.DrawBorder(g, sepRect,
                                                        _backColor, 0, bsNone, _backColor, 1, bsInset,
                                                        _backColor, 0, bsNone, _backColor, 1, bsInset);
                                break;
                        }
                    }
                }
                else
                {
                    int leftPos = drawRect.Left + imageColWidth + textGapLeft;

                    // Should the command be drawn selected?
                    if (hotCommand)
                    {
                        switch(_style)
                        {
                            case VisualStyle.IDE:
                                Rectangle selectArea = new Rectangle(drawRect.Left + 1, drawRect.Top, drawRect.Width - 3, drawRect.Height - 1);

                                using (Pen selectPen = new Pen(_highlightColorDark))
                                {
                                    // Draw the selection area white, because we are going to use an alpha brush
                                    using (SolidBrush whiteBrush = new SolidBrush(Color.White))
                                        g.FillRectangle(whiteBrush, selectArea);

                                    using (SolidBrush selectBrush = new SolidBrush(_highlightColorLight))
                                    {
                                        // Draw the selection area
                                        g.FillRectangle(selectBrush, selectArea);

                                        // Draw a border around the selection area
                                        g.DrawRectangle(selectPen, selectArea);
                                    }
                                }
                                break;
                            case VisualStyle.Plain:
                                using (SolidBrush selectBrush = new SolidBrush(_highlightColorDark))
                                    g.FillRectangle(selectBrush, drawRect);
                                break;
                        }
                    }
                    else
                    {
                        switch(_style)
                        {
                            case VisualStyle.IDE:
                                // Fill the entire drawing area with ControlLightLight
                                g.FillRectangle(_controlLLBrush, new Rectangle(drawRect.Left + 1, drawRect.Top, drawRect.Width - 1, drawRect.Height));

                                if (dc.Infrequent && _highlightInfrequent)
                                {
                                    // Draw the text area in a darker shade
                                    g.FillRectangle(Brushes.White, new Rectangle(leftPos, drawRect.Top, drawRect.Right - leftPos - textGapLeft, drawRect.Height));
                                    g.FillRectangle(_controlEBrush, new Rectangle(leftPos, drawRect.Top, drawRect.Right - leftPos - textGapLeft, drawRect.Height));
                                }

                                Rectangle imageCol = new Rectangle(drawRect.Left, drawRect.Top,imageColWidth, drawRect.Height);

                                // Draw the image column background
                                g.FillRectangle(Brushes.White, imageCol);
                                g.FillRectangle(_controlLBrush, imageCol);
                                break;
                            case VisualStyle.Plain:
                                if (dc.Infrequent && _highlightInfrequent)
                                {
                                    using(Brush drawBrush = new SolidBrush(ControlPaint.Light(_backColor)))
                                        g.FillRectangle(drawBrush, new Rectangle(drawRect.Left, drawRect.Top, drawRect.Width, drawRect.Height));
                                }
                                else
                                {
                                    using(Brush drawBrush = new SolidBrush(_backColor))
                                        g.FillRectangle(drawBrush, new Rectangle(drawRect.Left, drawRect.Top, drawRect.Width, drawRect.Height));
                                }

                                if (dc.TopBorder && _highlightInfrequent)
                                    using(Pen drawPen = new Pen(ControlPaint.Dark(_backColor)))
                                        g.DrawLine(drawPen, drawRect.Left, drawRect.Top, drawRect.Right, drawRect.Top);

                                if (dc.BottomBorder && _highlightInfrequent)
                                    using(Pen drawPen = new Pen(ControlPaint.LightLight(_backColor)))
                                        g.DrawLine(drawPen, drawRect.Left, drawRect.Bottom - 1, drawRect.Right, drawRect.Bottom - 1);
                                break;
                        }
                    }

                    // Calculate text drawing rectangle
                    Rectangle strRect = new Rectangle(leftPos, drawRect.Top, shortCutX - leftPos, drawRect.Height);

                    // Left align the text drawing on a single line centered vertically
                    // and process the & character to be shown as an underscore on next character
                    StringFormat format = new StringFormat();
                    format.FormatFlags = StringFormatFlags.NoClip | StringFormatFlags.NoWrap;
                    format.Alignment = StringAlignment.Near;
                    format.LineAlignment = StringAlignment.Center;
                    format.HotkeyPrefix = HotkeyPrefix.Show;

                    SolidBrush textBrush;

                    // Create brush depending on enabled state
                    if (mc.Enabled)
                    {
                        if (!hotCommand || (_style == VisualStyle.IDE))
                            textBrush = new SolidBrush(_textColor);
                        else
                            textBrush = new SolidBrush(_highlightTextColor);
                    }
                    else
                        textBrush = new SolidBrush(SystemColors.GrayText);

                    // Helper values used when drawing grayed text in plain style
                    Rectangle rectDownRight = strRect;
                    rectDownRight.Offset(1,1);

                    if (mc.Enabled || (_style == VisualStyle.IDE))
                        g.DrawString(mc.Text, _textFont, textBrush, strRect, format);
                    else
                    {
                        if (_style == VisualStyle.Plain)
                        {
                            // Draw grayed text by drawing white string offset down and right
                            using (SolidBrush whiteBrush = new SolidBrush(Color.White))
                                g.DrawString(mc.Text, _textFont, whiteBrush, rectDownRight, format);
                        }

                        // And then draw in correct color offset up and left
                        g.DrawString(mc.Text, _textFont, textBrush, strRect, format);
                    }

                    if (mc.Shortcut != Shortcut.None)
                    {
                        // Right align the shortcut drawing
                        format.Alignment = StringAlignment.Far;

                        if (mc.Enabled || (_style == VisualStyle.IDE))
                        {
                            // Draw the shortcut text
                            g.DrawString(GetShortcutText(mc.Shortcut), _textFont, textBrush, strRect, format);
                        }
                        else
                        {
                            if (_style == VisualStyle.Plain)
                            {
                                // Draw grayed text by drawing white string offset down and right
                                using (SolidBrush whiteBrush = new SolidBrush(Color.White))
                                    g.DrawString(GetShortcutText(mc.Shortcut), _textFont, whiteBrush, rectDownRight, format);
                            }

                            // And then draw in corret color offset up and left
                            g.DrawString(GetShortcutText(mc.Shortcut), _textFont, textBrush, strRect, format);
                        }
                    }

                    // The image offset from top of cell is half the space left after
                    // subtracting the height of the image from the cell height
                    int imageTop = drawRect.Top + (drawRect.Height - _imageHeight) / 2;

                    Image image = null;

                    // Should a check mark be drawn?
                    if (mc.Checked)
                    {
                        switch(_style)
                        {
                            case VisualStyle.IDE:
                                Pen boxPen;
                                Brush boxBrush;

                                if (mc.Enabled)
                                {
                                    boxPen = new Pen(_highlightColorDark);
                                    boxBrush = new SolidBrush(_highlightColorLightLight);
                                }
                                else
                                {
                                    boxPen = new Pen(SystemColors.GrayText);
                                    boxBrush = new SolidBrush(Color.FromArgb(20, SystemColors.GrayText));
                                }

                                Rectangle boxRect = new Rectangle(imageLeft - 1, imageTop - 1, _imageHeight + 2, _imageWidth + 2);

                                // Fill the checkbox area very slightly
                                g.FillRectangle(boxBrush, boxRect);

                                // Draw the box around the checkmark area
                                g.DrawRectangle(boxPen, boxRect);

                                boxPen.Dispose();
                                boxBrush.Dispose();
                                break;
                            case VisualStyle.Plain:
                                break;
                        }

                        // Grab either tick or radio button image
                        if (mc.RadioCheck)
                        {
                            if (hotCommand && (_style == VisualStyle.Plain))
                                image = _menuImages.Images[(int)ImageIndex.RadioSelected];
                            else
                                image = _menuImages.Images[(int)ImageIndex.Radio];
                        }
                        else
                        {
                            if (hotCommand && (_style == VisualStyle.Plain))
                                image = _menuImages.Images[(int)ImageIndex.CheckSelected];
                            else
                                image = _menuImages.Images[(int)ImageIndex.Check];
                        }
                    }
                    else
                    {
                        try
                        {
                            // Always use the Image property in preference to the ImageList
                            if (mc.Image != null)
                                image = mc.Image;
                            else
                            {
                                if ((mc.ImageList != null) && (mc.ImageIndex >= 0))
                                    image = mc.ImageList.Images[mc.ImageIndex];
                            }
                        }
                        catch(Exception)
                        {
                            // User supplied ImageList/ImageIndex are invalid, use an error image instead
                            image = _menuImages.Images[(int)ImageIndex.ImageError];
                        }
                    }

                    // Is there an image to be drawn?
                    if (image != null)
                    {
                        if (mc.Enabled)
                        {
                            if ((hotCommand) && (!mc.Checked) && (_style == VisualStyle.IDE))
                            {
                                // Draw a gray icon offset down and right
                                Bitmap shadowImage = new Bitmap((Bitmap) image);
                                Color shadowColor = Color.FromArgb(154, 156, 146);
                                Color transparent = Color.FromArgb(0, 0, 0, 0);

                                for(int pixelX = 0; pixelX < image.Width; pixelX++)
                                {
                                    for(int pixelY = 0; pixelY < image.Height; pixelY++)
                                    {
                                        if (shadowImage.GetPixel(pixelX, pixelY) != transparent)
                                            shadowImage.SetPixel(pixelX, pixelY, shadowColor);
                                    }
                                }

                                g.DrawImage(shadowImage, imageLeft + 1, imageTop + 1);

                                // Draw an enabled icon offset up and left
                                g.DrawImage(image, imageLeft - 1, imageTop - 1);
                            }
                            else
                            {
                                // Draw an faded enabled icon
                                // A new bitmap so we don't change the actual image
                                Bitmap fadedImage = new Bitmap(image);
                                Color transparent = Color.FromArgb(0, 0, 0, 0);

                                for(int pixelX = 0; pixelX < image.Width; pixelX++)
                                {
                                    for(int pixelY = 0; pixelY < image.Height; pixelY++)
                                    {
                                        Color pixelColor = fadedImage.GetPixel(pixelX, pixelY);
                                        if (pixelColor != transparent)
                                        {
                                            Color newPixelColor = Color.FromArgb((pixelColor.R + 76) - (((pixelColor.R + 32) / 64) * 19),
                                                                                 (pixelColor.G + 76) - (((pixelColor.G + 32) / 64) * 19),
                                                                                 (pixelColor.B + 76) - (((pixelColor.B + 32) / 64) * 19));

                                            fadedImage.SetPixel(pixelX, pixelY, newPixelColor);
                                        }
                                    }
                                }

                                g.DrawImage(fadedImage, imageLeft, imageTop);

                                // Draw an enabled icon
                                //g.DrawImage(image, imageLeft, imageTop);
                            }
                        }
                        else
                        {
                            // Draw a image disabled
                            ControlPaint.DrawImageDisabled(g, image, imageLeft, imageTop, SystemColors.HighlightText);
                        }
                    }

                    // Does the menu have a submenu defined?
                    if (dc.SubMenu)
                    {
                        // Is the item enabled?
                        if (mc.Enabled)
                        {
                            int subMenuIndex = (int)ImageIndex.SubMenu;

                            if (hotCommand && (_style == VisualStyle.Plain))
                                subMenuIndex = (int)ImageIndex.SubMenuSelected;

                            // Draw the submenu arrow
                            g.DrawImage(_menuImages.Images[subMenuIndex], subMenuX, imageTop);
                        }
                        else
                        {
                            // Draw a image disabled
                            ControlPaint.DrawImageDisabled(g, _menuImages.Images[(int)ImageIndex.SubMenu],
                                                           subMenuX, imageTop, _highlightTextColor);
                        }
                    }
                }
            }
        }
Beispiel #3
0
        internal void OperateSubMenu(DrawCommand dc, bool selectFirst, bool trackRemove)
        {
            if (this.IsDisposed)
                return;

            if (dc == null)
                return;

            Rectangle drawRect = dc.DrawRect;

            // Find screen positions for popup menu
            Point screenPos;

            if (_style == VisualStyle.IDE)
            {
                if (_direction == Direction.Horizontal)
                    screenPos = PointToScreen(new Point(dc.DrawRect.Left + 1, drawRect.Bottom - _lengthGap - 2));
                else
                    screenPos = PointToScreen(new Point(dc.DrawRect.Right - _breadthGap, drawRect.Top + _boxExpandSides - 1));
            }
            else
            {
                if (_direction == Direction.Horizontal)
                    screenPos = PointToScreen(new Point(dc.DrawRect.Left + 1, drawRect.Bottom));
                else
                    screenPos = PointToScreen(new Point(dc.DrawRect.Right, drawRect.Top));
            }

            Point aboveScreenPos;

            if (_style == VisualStyle.IDE)
            {
                if (_direction == Direction.Horizontal)
                    aboveScreenPos = PointToScreen(new Point(dc.DrawRect.Left + 1, drawRect.Top + _breadthGap + _lengthGap - 1));
                else
                    aboveScreenPos = PointToScreen(new Point(dc.DrawRect.Right - _breadthGap, drawRect.Bottom + _lengthGap + 1));
            }
            else
            {
                if (_direction == Direction.Horizontal)
                    aboveScreenPos = PointToScreen(new Point(dc.DrawRect.Left + 1, drawRect.Top));
                else
                    aboveScreenPos = PointToScreen(new Point(dc.DrawRect.Right, drawRect.Bottom));
            }

            int borderGap;

            // Calculate the missing gap in the PopupMenu border
            if (_direction == Direction.Horizontal)
                borderGap = dc.DrawRect.Width - _subMenuBorderAdjust;
            else
                borderGap = dc.DrawRect.Height - _subMenuBorderAdjust;

            _popupMenu = new PopupMenu();
            if (_popupMenu == null)
                return;

            // Define the correct visual style based on ours
            _popupMenu.Style = this.Style;

            // Key direction when keys cause dismissal
            int returnDir = 0;

            // Command selected by the PopupMenu
            MenuCommand returnCommand = null;

            // Should the PopupMenu tell the collection to remember expansion state
            _popupMenu.RememberExpansion = _rememberExpansion;

            // Propogate our highlight setting
            _popupMenu.HighlightInfrequent = _highlightInfrequent;

            // Might need to define custom colors
            if (!_defaultSelectedBackColor)
                _popupMenu.BackColor = _selectedBackColor;

            if (!_defaultSelectedTextColor)
                _popupMenu.TextColor = _selectedTextColor;

            if (!_defaultHighlightTextColor)
                _popupMenu.HighlightTextColor = _highlightTextColor;

            if (!_defaultHighlightBackColor)
                _popupMenu.HighlightColor = _highlightBackColor;

            if (!_defaultFont)
                _popupMenu.Font = base.Font;

            // Pass on the animation values
            _popupMenu.Animate = _animate;
            _popupMenu.AnimateStyle = _animateStyle;
            _popupMenu.AnimateTime = _animateTime;

            if (dc.Chevron)
            {
                MenuCommandCollection mcc = new MenuCommandCollection();

                bool addCommands = false;

                if (_menuCommands != null)
                {
                    // Generate a collection of menu commands for those not visible
                    foreach(MenuCommand command in _menuCommands)
                    {
                        if (!addCommands && (command == _chevronStartCommand))
                            addCommands = true;

                        if (addCommands)
                            mcc.Add(command);
                    }
                }

                // Track the popup using provided menu item collection
                returnCommand = _popupMenu.TrackPopup(screenPos,
                                                      aboveScreenPos,
                                                      _direction,
                                                      mcc,
                                                      borderGap,
                                                      selectFirst,
                                                      this,
                                                      _animateFirst,
                                                      ref returnDir);
            }
            else
            {
                // Generate event so that caller has chance to modify MenuCommand contents
                dc.MenuCommand.OnPopupStart();

                // Honour the collections request for showing infrequent items
                _popupMenu.ShowInfrequent = dc.MenuCommand.MenuCommands.ShowInfrequent;

                // Track the popup using provided menu item collection
                returnCommand = _popupMenu.TrackPopup(screenPos,
                                                      aboveScreenPos,
                                                      _direction,
                                                      dc.MenuCommand.MenuCommands,
                                                      borderGap,
                                                      selectFirst,
                                                      this,
                                                      _animateFirst,
                                                      ref returnDir);
            }

            // No more animation till simulation ends
            _animateFirst = false;

            // If we are supposed to expand all items at the same time
            if (_expandAllTogether)
            {
                // Is anything we have shown now in the expanded state
                if (AnythingExpanded(_menuCommands))
                {
                    // Set everything to expanded
                    SetAllCommandsExpansion(_menuCommands, true);
                }
            }

            // Was arrow key not used to dismiss the submenu?
            if (returnDir == 0)
            {
                // The submenu may have eaten the mouse leave event
                _mouseOver = false;

                // Only if the submenu was dismissed at the request of the submenu
                // should the selection mode be cancelled, otherwise keep selection mode
                if (!_dismissTransfer)
                {
                    // This item is no longer selected
                    Deselect();
                    _drawUpwards = false;

                    if (!this.IsDisposed)
                    {
                        // Should we stop tracking this item
                        if (trackRemove)
                        {
                            // Unselect the current item
                            _trackItem = SwitchTrackingItem(_trackItem, -1);
                        }
                        else
                        {
                            if (_trackItem != -1)
                            {
                                // Repaint the item
                                DrawCommand(_trackItem, true);
                            }
                        }
                    }
                }
                else
                {
                    // Do not change _selected status
                    _dismissTransfer = false;
                }
            }

            if (!dc.Chevron)
            {
                // Generate event so that caller has chance to modify MenuCommand contents
                dc.MenuCommand.OnPopupEnd();
            }

            // Spin the message loop so the messages dealing with destroying
            // the PopupMenu window are processed and cause it to disappear from
            // view before events are generated
            Application.DoEvents();

            // Remove unwanted object
            _popupMenu = null;

            // Was arrow key used to dismiss the submenu?
            if (returnDir != 0)
            {
                if (returnDir < 0)
                {
                    // Shift selection left one
                    ProcessMoveLeft(true);
                }
                else
                {
                    // Shift selection right one
                    ProcessMoveRight(true);
                }

                // A WM_MOUSEMOVE is generated when we open up the new submenu for
                // display, ignore this as it causes the selection to move
                _ignoreMouseMove = true;
            }
            else
            {
                // Was a MenuCommand returned?
                if (returnCommand != null)
                {
                    // Remove

                    // Are we simulating having the focus?
                    if (_manualFocus)
                    {
                        // Always return focus to original when a selection is made
                        SimulateReturnFocus();
                    }

                    // Pulse the selected event for the command
                     returnCommand.OnClick(EventArgs.Empty);
                }
            }
        }
        protected Size GenerateDrawPositions()
        {
            // Create a collection of drawing objects
            _drawCommands = new ArrayList();

            // Calculate the minimum cell width and height
            int cellMinHeight = _position[(int)_style, (int)PI.ImageGapTop] +
                                _imageHeight +
                                _position[(int)_style, (int)PI.ImageGapBottom];

            int cellMinWidth = _position[(int)_style, (int)PI.ImageGapLeft] +
                               _imageWidth +
                               _position[(int)_style, (int)PI.ImageGapRight] +
                               _position[(int)_style, (int)PI.TextGapLeft] +
                               _position[(int)_style, (int)PI.TextGapRight] +
                               _position[(int)_style, (int)PI.SubMenuGapLeft] +
                               _position[(int)_style, (int)PI.SubMenuWidth] +
                               _position[(int)_style, (int)PI.SubMenuGapRight];

            // Find cell height needed to draw text
            int textHeight = _textFont.Height;

            // If height needs to be more to handle image then use image height
            if (textHeight < cellMinHeight)
                textHeight = cellMinHeight;

            // Make sure no column in the menu is taller than the screen
            int screenHeight = SystemInformation.WorkingArea.Height;

            // Define the starting positions for calculating cells
            int xStart = _position[(int)_style, (int)PI.BorderLeft];
            int yStart =_position[(int)_style, (int)PI.BorderTop];
            int yPosition = yStart;

            // Largest cell for column defaults to minimum cell width
            int xColumnMaxWidth = cellMinWidth;

            int xPreviousColumnWidths = 0;
            int xMaximumColumnHeight = 0;

            // Track the row/col of each cell
            int row = 0;
            int col = 0;

            // Are there any infrequent items
            bool infrequent = false;
            bool previousInfrequent = false;

            // Get hold of the DC for the desktop
            IntPtr hDC = User32.GetDC(IntPtr.Zero);

            // Contains the collection of items in the current column
            ArrayList columnItems = new ArrayList();

            using(Graphics g = Graphics.FromHdc(hDC))
            {
                // Handle any extra text drawing
                if (_menuCommands.ExtraText.Length > 0)
                {
                    // Calculate the column width needed to show this text
                    SizeF dimension = g.MeasureString(_menuCommands.ExtraText, _menuCommands.ExtraFont);

                    // Always add 1 to ensure that rounding is up and not down
                    int extraHeight = (int)dimension.Height + 1;

                    // Find the total required as the text requirement plus style specific spacers
                    _extraSize = extraHeight +
                                 _position[(int)_style, (int)PI.ExtraRightGap] +
                                 _position[(int)_style, (int)PI.ExtraWidthGap] * 2;

                    // Push first column of items across from the extra text
                    xStart += _extraSize;

                    // Add this extra width to the total width of the window
                    xPreviousColumnWidths = _extraSize;
                }

                foreach(MenuCommand command in _menuCommands)
                {
                    // Give the command a chance to update its state
                    command.OnUpdate(EventArgs.Empty);

                    // Ignore items that are marked as hidden
                    if (!command.Visible)
                        continue;

                    // If this command has menu items (and so it a submenu item) then check
                    // if any of the submenu items are visible. If none are visible then there
                    // is no point in showing this submenu item
                    if ((command.MenuCommands.Count > 0) && (!command.MenuCommands.VisibleItems()))
                        continue;

                    // Ignore infrequent items unless flag set to show them
                    if (command.Infrequent && !_showInfrequent)
                    {
                        infrequent = true;
                        continue;
                    }

                    int cellWidth = 0;
                    int cellHeight = 0;

                    // Shift across to the next column?
                    if (command.Break)
                    {
                        // Move row/col tracking to the next column
                        row = 0;
                        col++;

                        // Apply cell width to the current column entries
                        ApplySizeToColumnList(columnItems, xColumnMaxWidth);

                        // Move cell position across to start of separator position
                        xStart += xColumnMaxWidth;

                        // Get width of the separator area
                        int xSeparator = _position[(int)_style, (int)PI.SeparatorWidth];

                        DrawCommand dcSep = new DrawCommand(new Rectangle(xStart, 0, xSeparator, 0), false);

                        // Add to list of items for drawing
                        _drawCommands.Add(dcSep);

                        // Move over the separator
                        xStart += xSeparator;

                        // Reset cell position to top of column
                        yPosition = yStart;

                        // Accumulate total width of previous columns
                        xPreviousColumnWidths += xColumnMaxWidth + xSeparator;

                        // Largest cell for column defaults to minimum cell width
                        xColumnMaxWidth  = cellMinWidth;
                    }

                    // Is this a horizontal separator?
                    if (command.Text == "-")
                    {
                        cellWidth = cellMinWidth;
                        cellHeight = _position[(int)_style, (int)PI.SeparatorHeight];
                    }
                    else
                    {
                        // Use precalculated height
                        cellHeight = textHeight;

                        // Calculate the text width portion of the cell
                        SizeF dimension = g.MeasureString(command.Text, _textFont);

                        // Always add 1 to ensure that rounding is up and not down
                        cellWidth = cellMinWidth + (int)dimension.Width + 1;

                        // Does the menu command have a shortcut defined?
                        if (command.Shortcut != Shortcut.None)
                        {
                            // Find the width of the shortcut text
                            dimension = g.MeasureString(GetShortcutText(command.Shortcut), _textFont);

                            // Add to the width of the cell
                            cellWidth += _position[(int)_style, (int)PI.ShortcutGap] + (int)dimension.Width + 1;
                        }
                    }

                    // If the new cell expands past the end of the screen...
                    if ((yPosition + cellHeight) >= screenHeight)
                    {
                        // .. then need to insert a column break

                        // Move row/col tracking to the next column
                        row = 0;
                        col++;

                        // Apply cell width to the current column entries
                        ApplySizeToColumnList(columnItems, xColumnMaxWidth);

                        // Move cell position across to start of separator position
                        xStart += xColumnMaxWidth;

                        // Get width of the separator area
                        int xSeparator = _position[(int)_style, (int)PI.SeparatorWidth];

                        DrawCommand dcSep = new DrawCommand(new Rectangle(xStart, yStart, xSeparator, 0), false);

                        // Add to list of items for drawing
                        _drawCommands.Add(dcSep);

                        // Move over the separator
                        xStart += xSeparator;

                        // Reset cell position to top of column
                        yPosition = yStart;

                        // Accumulate total width of previous columns
                        xPreviousColumnWidths += xColumnMaxWidth + xSeparator;

                        // Largest cell for column defaults to minimum cell width
                        xColumnMaxWidth  = cellMinWidth;

                        // Show this be drawn in the infrequent colors
                        dcSep.Infrequent = previousInfrequent;
                    }

                    // Create a new position rectangle (the width will be reset later once the
                    // width of the column has been determined but the other values are correct)
                    Rectangle cellRect = new Rectangle(xStart, yPosition, cellWidth, cellHeight);

                    // Create a drawing object
                    DrawCommand dc = new DrawCommand(command, cellRect, row, col);

                    // Is the infrequent state different from previous commands?
                    if (previousInfrequent != command.Infrequent)
                    {
                        // If was not infrequent but now is
                        if (command.Infrequent)
                        {
                            // Then draw this infrequent item with a top border
                            dc.TopBorder = true;
                        }
                        else
                        {
                            if (_drawCommands.Count > 0)
                            {
                                // Find the previous command (excluding separators) and make it as needed a border
                                for(int index = _drawCommands.Count - 1; index>=0; index--)
                                {
                                    if (!( _drawCommands[index] as DrawCommand).Separator)
                                    {
                                        (_drawCommands[index] as DrawCommand).BottomBorder = true;
                                        break;
                                    }
                                }
                            }
                        }
                    }

                    // Remember the state of previous command only if not a separator
                    if (!dc.Separator)
                        previousInfrequent = command.Infrequent;

                    // Add to list of items for drawing
                    _drawCommands.Add(dc);

                    // Add to list of items in this column
                    columnItems.Add(dc);

                    // Remember the biggest cell width in this column
                    if (cellWidth > xColumnMaxWidth)
                        xColumnMaxWidth = cellWidth;

                    // Move down to start of next cell in column
                    yPosition += cellHeight;

                    // Remember the tallest column in the menu
                    if (yPosition > xMaximumColumnHeight)
                        xMaximumColumnHeight = yPosition;

                    row++;
                }

                // Check if we need to add an infrequent expansion item
                if (infrequent)
                {
                    // Create a minimum size cell
                    Rectangle cellRect = new Rectangle(xStart, yPosition, cellMinWidth, cellMinHeight);

                    // Create a draw command to represent the drawing of the expansion item
                    DrawCommand dc = new DrawCommand(cellRect, true);

                    // Must be last item
                    _drawCommands.Add(dc);

                    // Add to list of items in this column
                    columnItems.Add(dc);

                    yPosition += cellMinHeight;

                    // Remember the tallest column in the menu
                    if (yPosition > xMaximumColumnHeight)
                        xMaximumColumnHeight = yPosition;
                }

                // Apply cell width to the current column entries
                ApplySizeToColumnList(columnItems, xColumnMaxWidth);
            }

            // Must remember to release the HDC resource!
            User32.ReleaseDC(IntPtr.Zero, hDC);

            // Find width/height of window
            int windowWidth = _position[(int)_style, (int)PI.BorderLeft] +
                              xPreviousColumnWidths +
                              xColumnMaxWidth +
                              _position[(int)_style, (int)PI.BorderRight];

            int windowHeight = _position[(int)_style, (int)PI.BorderTop] +
                               xMaximumColumnHeight +
                               _position[(int)_style, (int)PI.BorderBottom];

            // Define the height of the vertical separators
            ApplyVerticalSeparators(xMaximumColumnHeight);

            // Style specific modification of window size
            int xAdd = _position[(int)_style, (int)PI.ShadowHeight];
            int yAdd = _position[(int)_style, (int)PI.ShadowWidth];

            if (_style == VisualStyle.Plain)
            {
                xAdd += SystemInformation.Border3DSize.Width * 2;
                yAdd += SystemInformation.Border3DSize.Height * 2;
            }

            return new Size(windowWidth + xAdd, windowHeight + yAdd);
        }