Example #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;

      // Draw background color over cell and shadow area to the right
      using(SolidBrush back = new SolidBrush(SystemColors.Control))
        g.FillRectangle(back, shadowRect);

      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(SystemBrushes.ControlLight, boxRect);
                
                  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(SystemColors.ControlDark))
                      g.DrawRectangle(dark, boxRect.Left, boxRect.Top - _shadowGap, 
                        boxRect.Width, boxRect.Height + _shadowGap);

                    // Remove the top line of the selection area
                    using(Pen dark = new Pen(SystemColors.ControlLight))
                      g.DrawLine(dark, boxRect.Left + 1, boxRect.Top, boxRect.Right - 2, boxRect.Top);

                    int rightTop = boxRect.Top;
                    int leftLeft = boxRect.Left + _shadowGap;

                    SolidBrush shadowBrush;

                    // Decide if we need to use an alpha brush
                    if (_supportsLayered && (_style == VisualStyle.IDE))
                      shadowBrush = new SolidBrush(Color.FromArgb(64, 0, 0, 0));
                    else
                      shadowBrush = new SolidBrush(SystemColors.ControlDark);

                    g.FillRectangle(shadowBrush, new Rectangle(rightLeft, rightTop + _shadowGap - 1, _shadowGap, rightBottom - rightTop - _shadowGap*2));

                    shadowBrush.Dispose();
                  }
                  else
                  {
                    // Draw the box around the selection area
                    using(Pen dark = new Pen(SystemColors.ControlDark))
                      g.DrawRectangle(dark, boxRect);

                    if (_direction == Direction.Horizontal)
                    {
                      // Remove the bottom line of the selection area
                      using(Pen dark = new Pen(SystemColors.ControlLight))
                        g.DrawLine(dark, boxRect.Left, boxRect.Bottom, boxRect.Right, boxRect.Bottom);

                      int rightTop = boxRect.Top + _shadowYOffset;

                      SolidBrush shadowBrush;

                      // Decide if we need to use an alpha brush
                      if (_supportsLayered && (_style == VisualStyle.IDE))
                        shadowBrush = new SolidBrush(Color.FromArgb(64, 0, 0, 0));
                      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
                      using(Pen dark = new Pen(SystemColors.ControlLight))
                        g.DrawLine(dark, boxRect.Right, boxRect.Top, boxRect.Right, boxRect.Bottom);

                      int leftLeft = boxRect.Left + _shadowYOffset;

                      SolidBrush shadowBrush;

                      // Decide if we need to use an alpha brush
                      if (_supportsLayered && (_style == VisualStyle.IDE))
                        shadowBrush = new SolidBrush(Color.FromArgb(64, 0, 0, 0));
                      else
                        shadowBrush = new SolidBrush(SystemColors.ControlDark);

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

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

                  using (SolidBrush selectBrush = new SolidBrush(Color.FromArgb(70, ColorUtil.VSNetBorderColor)))
                  {
                    // Draw the selection area
                    g.FillRectangle(selectBrush, boxRect);

                    // Draw a border around the selection area
                    g.DrawRectangle( ColorUtil.VSNetBorderPen, boxRect );
                  }
                }
                break;

              case VisualStyle.Plain:
                if (_plainAsBlock)
                {
                  g.FillRectangle( ColorUtil.VSNetBorderBrush, drawRect );
                }
                else
                {
                  Pen lighlight = SystemPens.ControlLightLight;
                  Pen dark = SystemPens.ControlDark;

                  if (_selected)
                  {
                    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
                  {
                    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)
          {
            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;
              }

              g.DrawString(mc.Text, this.Font, SystemBrushes.HighlightText, textRect, format);
            }
            else
              using (SolidBrush textBrush = new SolidBrush(SystemColors.MenuText))
                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 then text offset down and right
            g.DrawString(mc.Text, this.Font, SystemBrushes.HighlightText, rectDownRight, format);

            // Draw then text offset up and left
            g.DrawString(mc.Text, this.Font, SystemBrushes.FromSystemColor(SystemColors.GrayText), 
              textRect, format);
          }
        }
      }
    }
Example #2
0
    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);
        
        switch( style)
        {
          case VisualStyle.IDE:
            g.FillRectangle(SystemBrushes.ControlLightLight, box);
            break;
          case VisualStyle.Plain:
            g.FillRectangle(SystemBrushes.Control, box);
            break;
        }

        // 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);

              // Draw the selection area white, because we are going to use an alpha brush
              g.FillRectangle( Brushes.White, selectArea );

              using (SolidBrush selectBrush = new SolidBrush(Color.FromArgb(70,ColorUtil.VSNetBorderColor)))
              {
                // Draw the selection area
                g.FillRectangle(selectBrush, selectArea);

                // Draw a border around the selection area
                g.DrawRectangle( ColorUtil.VSNetBorderPen, selectArea );
              }
              break;

            case VisualStyle.Plain:
              // Shrink the box to provide a small border
              box.Inflate(-2, -2);

              // Grab common values
              Color baseColor = SystemColors.Control;

              using (Pen lightPen = new Pen(SystemColors.ControlLightLight),
                       darkPen = new Pen(SystemColors.ControlDarkDark))
              {
                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( SystemBrushes.ControlLightLight, 
                new Rectangle(drawRect.Left + 1, drawRect.Top,
                drawRect.Width - 1, drawRect.Height));

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

              // Draw the image column background
              g.FillRectangle(SystemBrushes.Control, imageCol);
              break;
            case VisualStyle.Plain:
              g.FillRectangle(SystemBrushes.Control, 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(SystemColors.ControlDark))
                  g.DrawLine(separatorPen, drawRect.Left, drawRect.Top, drawRect.Left, drawRect.Bottom);
                break;
              case VisualStyle.Plain:
                Color baseColor = SystemColors.Control;
                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, 
                  baseColor, 1, bsInset, baseColor, 0, bsNone,
                  baseColor, 1, bsInset, baseColor, 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( ColorUtil.VSNetBackgroundBrush, drawRect);
                g.FillRectangle( ColorUtil.VSNetControlBrush, imageCol);
                             
                // Draw a separator
                using (Pen separatorPen = new Pen(Color.FromArgb(75, SystemColors.MenuText)))
                {
                  // Draw the separator as a single line
                  g.DrawLine(separatorPen, drawRect.Left + imageColWidth + textGapLeft, drawRect.Top + 1,
                    drawRect.Right-4, drawRect.Top + 1); 
                       
                }
                break;
              case VisualStyle.Plain:
                Color baseColor = SystemColors.Control;
                ButtonBorderStyle bsInset = ButtonBorderStyle.Inset;
                ButtonBorderStyle bsNone = ButtonBorderStyle.Inset;
              
                Rectangle sepRect = new Rectangle(drawRect.Left + 2, drawRect.Top + 1, 
                  drawRect.Width - 4, 2);
              
                // Draw the separator as two lines using Inset style
                ControlPaint.DrawBorder(g, sepRect, 
                  baseColor, 0, bsNone, baseColor, 1, bsInset,
                  baseColor, 0, bsNone, baseColor, 1, bsInset);
                break;
            }
          }
        }
        else
        {
          // Should the command be drawn selected?
          if (hotCommand && mc.ComboBox == null )
          {
            switch( style)
            {
              case VisualStyle.IDE:
                Rectangle selectArea = new Rectangle(drawRect.Left + 1, drawRect.Top,
                  drawRect.Width - 3, drawRect.Height - 1);

                // Draw the selection area white, because we are going to use an alpha brush
                g.FillRectangle(Brushes.White, selectArea);

                using (SolidBrush selectBrush = new SolidBrush(Color.FromArgb(70, ColorUtil.VSNetBorderColor)))
                {
                  // Draw the selection area
                  g.FillRectangle(selectBrush, selectArea);

                  // Draw a border around the selection area
                  g.DrawRectangle( ColorUtil.VSNetBorderPen, selectArea);
                }
                break;

              case VisualStyle.Plain:
                g.FillRectangle( ColorUtil.VSNetBorderBrush, drawRect);
                break;
            }
          }
          else
          {
            switch( style)
            {
              case VisualStyle.IDE:
                // Fill the entire drawing area with white
                g.FillRectangle( ColorUtil.VSNetBackgroundBrush, 
                  new Rectangle(drawRect.Left + 1, drawRect.Top, drawRect.Width - 1, drawRect.Height));

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

                // Draw the image column background
                g.FillRectangle( ColorUtil.VSNetControlBrush, imageCol );

                // If this is a combobox item, make sure to position the combobox a couple
                // of pixel after the icon area 
                if ( mc.ComboBox != null )
                {
                  // Combobox will paint itself
                  mc.ComboBox.Left = drawRect.Left+imageColWidth + 2;
                  mc.ComboBox.Top = drawRect.Top + (drawRect.Height - mc.ComboBox.Height)/2;
        
                }

                break;
              case VisualStyle.Plain:
                g.FillRectangle(SystemBrushes.Control, new Rectangle(drawRect.Left, drawRect.Top,
                  drawRect.Width, drawRect.Height));
                break;
            }
          }

          int leftPos = drawRect.Left + imageColWidth + textGapLeft;

          // 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(SystemColors.MenuText);
            else
              textBrush = new SolidBrush(SystemColors.HighlightText);
          }
          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
          {
            // Draw grayed text by drawing white string offset down and right
            g.DrawString(mc.Text, textFont, SystemBrushes.HighlightText, rectDownRight, format);

            // And then draw in corret 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
            {
              // Draw grayed text by drawing white string offset down and right
              g.DrawString(GetShortcutText(mc.Shortcut), textFont, 
                SystemBrushes.HighlightText, 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;

                if (mc.Enabled)
                  boxPen = ColorUtil.VSNetBorderPen;
                else
                  boxPen = SystemPens.GrayText;

                // Draw the box around the checkmark area
                g.DrawRectangle(boxPen, new Rectangle(imageLeft - 1, imageTop - 1, 
                  imageHeight + 2, imageWidth + 2));

                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
            {
              // Is there an image available to be drawn?
              if ((mc.ImageList != null) && (mc.ImageIndex >= 0))
                image = mc.ImageList.Images[mc.ImageIndex];
              else if ( mc.Image != null)
                image = mc.Image;
            }
            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 disabled icon offset down and right
                ControlPaint.DrawImageDisabled(g, image, imageLeft + 1, imageTop + 1, 
                  SystemColors.HighlightText);

                // Draw an enabled icon offset up and left
                g.DrawImage(image, imageLeft - 1, imageTop - 1);
              }
              else
              {
                // 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, SystemColors.HighlightText);
            }
          }
        }
      }
    }
Example #3
0
    internal void OperateSubMenu(DrawCommand dc, bool selectFirst, bool trackRemove)
    {
      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 - 1));
        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 + _lengthGap + 1));
        else
          aboveScreenPos = PointToScreen(new Point(dc.DrawRect.Right - _breadthGap, drawRect.Bottom + _lengthGap));
      }
      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();

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

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

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

        bool addCommands = false;

        // 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
        _popupMenu.TrackPopup(screenPos, 
          aboveScreenPos,
          _direction,
          mcc, 
          borderGap,
          selectFirst,
          this,
          ref returnDir);
      }
      else
      {
        // Generate event so that caller has chance to modify MenuCommand contents
        OnPopupStart(dc.MenuCommand);

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

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

      // Remove unwanted object
      _popupMenu = null;

      // Was arrow key used to dismiss the submenu?
      if (returnDir != 0)
      {
        // Using keyboard movements means we should have the focus
        if (!_manualFocus)
        {
          _manualFocus = true;

          GrabTheFocus();
        }

        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
      {
        // 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
          _selected = false;
          _drawUpwards = false;

          // Should we stop tracking this item
          if (trackRemove)
          {
            ReturnTheFocus();

            // Unselect the current item
            _trackItem = SwitchTrackingItem(_trackItem, -1);
          }
          else
          {
            // Repaint the item
            DrawCommand(_trackItem, true);
          }
        }
        else
        {
          // Do not change _selected status
          _dismissTransfer = false;
        }
      }
    }
Example #4
0
    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;

      // Get hold of the DC for the desktop
      IntPtr hDC = WindowsAPI.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 this is a combobox, then add the combobox dimension
            if ( command.ComboBox != null )
            {
              cellWidth += command.ComboBox.Width;
            }
          }

          // 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;
          }
  
          // 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);

          // 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!
      WindowsAPI.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);
    }