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