Code:
/ DotNET / DotNET / 8.0 / untmp / whidbey / REDBITS / ndp / fx / src / WinForms / Managed / System / WinForms / ToolStripDropDownMenu.cs / 1 / ToolStripDropDownMenu.cs
namespace System.Windows.Forms { using System; using System.Collections; using System.ComponentModel; using System.ComponentModel.Design.Serialization; using System.Diagnostics; using System.Drawing; using System.Globalization; using System.Windows.Forms.Layout; using System.Reflection; using System.Runtime.InteropServices; using System.Security; using System.Security.Permissions; using System.Windows.Forms.Internal; using System.Collections.Specialized; using System.Diagnostics.CodeAnalysis; ///[Designer("System.Windows.Forms.Design.ToolStripDropDownDesigner, " + AssemblyRef.SystemDesign)] [ComVisible(true)] [ClassInterface(ClassInterfaceType.AutoDispatch)] public class ToolStripDropDownMenu : ToolStripDropDown { private static Padding ImagePadding = new Padding(2); private static Padding TextPadding = new Padding(8,1,9,1); private static Padding CheckPadding = new Padding(5,2,2,2); private static Padding ArrowPadding = new Padding(0,0,8,0); // This is totally a UI Fudge - if we have an image or check margin with // no image or checks in it use this - which is consistent with office // and an image margin with a 16x16 icon in it. private static int DefaultImageMarginWidth = 25; // 24+1px border private static int DefaultImageAndCheckMarginWidth = 47; // 46+1px border private Size maxItemSize = Size.Empty; private Rectangle checkRectangle = Rectangle.Empty; private Rectangle imageRectangle = Rectangle.Empty; private Rectangle arrowRectangle = Rectangle.Empty; private Rectangle textRectangle = Rectangle.Empty; private Rectangle imageMarginBounds = Rectangle.Empty; private int paddingToTrim = 0; private int tabWidth = -1; private ToolStripScrollButton upScrollButton = null; private ToolStripScrollButton downScrollButton = null; private int scrollAmount = 0; private int indexOfFirstDisplayedItem = -1; private BitVector32 state = new BitVector32(); private static readonly int stateShowImageMargin = BitVector32.CreateMask(); private static readonly int stateShowCheckMargin = BitVector32.CreateMask(stateShowImageMargin); private static readonly int stateMaxItemSizeValid = BitVector32.CreateMask(stateShowCheckMargin); private static readonly Size defaultImageSize = new Size(16,16); /// /// /// Summary of ToolStripDropDown. /// public ToolStripDropDownMenu(){ } ////// Constructor to autogenerate /// internal ToolStripDropDownMenu(ToolStripItem ownerItem, bool isAutoGenerated) : base(ownerItem,isAutoGenerated) { } internal override bool AllItemsVisible { get { return !RequiresScrollButtons; } set { RequiresScrollButtons = !value; } } internal Rectangle ArrowRectangle { get { return arrowRectangle; } } internal Rectangle CheckRectangle { get { return checkRectangle; } } ///protected override Padding DefaultPadding { get { RightToLeft rightToLeft = RightToLeft; int textPadding = (rightToLeft == RightToLeft.Yes) ? TextPadding.Right : TextPadding.Left; int padding = (ShowCheckMargin || ShowImageMargin) ? textPadding + ImageMargin.Width : textPadding; // scooch in all the items by the margin. if (rightToLeft == RightToLeft.Yes) { return new Padding(1,2,padding,2); } return new Padding(padding,2,1,2); } } /// public override Rectangle DisplayRectangle { get { Rectangle rect = base.DisplayRectangle; if (GetToolStripState(STATE_SCROLLBUTTONS)) { rect.Y += UpScrollButton.Height + UpScrollButton.Margin.Vertical; rect.Height -= UpScrollButton.Height + UpScrollButton.Margin.Vertical + DownScrollButton.Height + DownScrollButton.Margin.Vertical; // Because we're going to draw the scroll buttons on top of the padding, we need to add it back in here. rect = LayoutUtils.InflateRect(rect, new Padding(0, this.Padding.Top, 0, this.Padding.Bottom)); } return rect; } } private ToolStripScrollButton DownScrollButton { get { if (downScrollButton == null) { downScrollButton = new ToolStripScrollButton(false); downScrollButton.ParentInternal = this; } return downScrollButton; } } /// /// the rectangle representing /// internal Rectangle ImageRectangle { get { return imageRectangle; } } internal int PaddingToTrim { get { return paddingToTrim; } set { if (paddingToTrim != value) { paddingToTrim = value; AdjustSize(); } } } ////// the rectangle representing the color stripe in the menu - this will appear as AffectedBounds /// in the ToolStripRenderEventArgs /// internal Rectangle ImageMargin { get { imageMarginBounds.Height =this.Height; return imageMarginBounds; } } ///public override LayoutEngine LayoutEngine { get { return ToolStripDropDownLayoutEngine.LayoutInstance; } } [ DefaultValue(ToolStripLayoutStyle.Flow) ] public new ToolStripLayoutStyle LayoutStyle { get { return base.LayoutStyle; } set { base.LayoutStyle = value; } } /// protected internal override Size MaxItemSize { get { if (!state[stateMaxItemSizeValid]) { CalculateInternalLayoutMetrics(); } return maxItemSize; } } /// [ DefaultValue(true), SRDescription(SR.ToolStripDropDownMenuShowImageMarginDescr), SRCategory(SR.CatAppearance) ] public bool ShowImageMargin { get { return state[stateShowImageMargin]; } set { if (value != state[stateShowImageMargin]) { state[stateShowImageMargin] = value; LayoutTransaction.DoLayout(this, this, PropertyNames.ShowImageMargin); } } } /// [ DefaultValue(false), SRDescription(SR.ToolStripDropDownMenuShowCheckMarginDescr), SRCategory(SR.CatAppearance) ] public bool ShowCheckMargin { get { return state[stateShowCheckMargin]; } set { if (value != state[stateShowCheckMargin]) { state[stateShowCheckMargin] = value; LayoutTransaction.DoLayout(this, this, PropertyNames.ShowCheckMargin); } } } internal Rectangle TextRectangle { get { return textRectangle; } } private ToolStripScrollButton UpScrollButton { get { if (upScrollButton == null) { upScrollButton = new ToolStripScrollButton(true); upScrollButton.ParentInternal = this; } return upScrollButton; } } /// this takes a native menu and builds up a managed toolstrip around it. /// Scenario: showing the items from the SystemMenu. /// targetWindow is the window to send WM_COMMAND, WM_SYSCOMMAND to /// hmenu is a handle to the native menu /// /// internal static ToolStripDropDownMenu FromHMenu(IntPtr hmenu, IWin32Window targetWindow) { ToolStripDropDownMenu managedDropDown = new ToolStripDropDownMenu(); managedDropDown.SuspendLayout(); HandleRef menuHandle = new HandleRef(null, hmenu); int count = UnsafeNativeMethods.GetMenuItemCount(menuHandle); ToolStripItem itemToAdd; // surf through the items in the collection, building up TSMenuItems and TSSeparators // corresponding to the native menu. for (int i = 0; i < count; i++) { // peek at the i'th item. NativeMethods.MENUITEMINFO_T_RW info = new NativeMethods.MENUITEMINFO_T_RW(); info.cbSize = Marshal.SizeOf(typeof(NativeMethods.MENUITEMINFO_T_RW)); info.fMask = NativeMethods.MIIM_FTYPE; info.fType = NativeMethods.MIIM_FTYPE; UnsafeNativeMethods.GetMenuItemInfo(menuHandle, i, /*fByPosition=*/ true, info); if (info.fType == NativeMethods.MFT_SEPARATOR){ // its a separator. itemToAdd = new ToolStripSeparator(); } else { // its a menu item... lets fish out the command id info = new NativeMethods.MENUITEMINFO_T_RW(); info.cbSize = Marshal.SizeOf(typeof(NativeMethods.MENUITEMINFO_T_RW)); info.fMask = NativeMethods.MIIM_ID; info.fType = NativeMethods.MIIM_ID; UnsafeNativeMethods.GetMenuItemInfo(menuHandle, i, /*fByPosition=*/ true, info); // create the managed object - toolstripmenu item knows how to grok hmenu for information. itemToAdd = new ToolStripMenuItem(hmenu, info.wID, targetWindow); // if there is a submenu fetch it. info = new NativeMethods.MENUITEMINFO_T_RW(); info.cbSize = Marshal.SizeOf(typeof(NativeMethods.MENUITEMINFO_T_RW)); info.fMask = NativeMethods.MIIM_SUBMENU; info.fType = NativeMethods.MIIM_SUBMENU; UnsafeNativeMethods.GetMenuItemInfo(menuHandle, i, /*fByPosition=*/ true, info); if (info.hSubMenu != IntPtr.Zero) { // set the dropdown to be the items from the submenu ((ToolStripMenuItem)itemToAdd).DropDown = FromHMenu(info.hSubMenu, targetWindow); } } managedDropDown.Items.Add(itemToAdd); } managedDropDown.ResumeLayout(); return managedDropDown; } [SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters")] // using "\t" to figure out the width of tab private void CalculateInternalLayoutMetrics() { Size maxTextSize = Size.Empty; Size maxImageSize = Size.Empty; Size maxCheckSize = defaultImageSize; Size maxArrowSize = Size.Empty; Size maxNonMenuItemSize = Size.Empty; // determine Text Metrics for (int i = 0; i < Items.Count; i++) { ToolStripItem item = Items[i]; ToolStripMenuItem menuItem = item as ToolStripMenuItem; if (menuItem != null) { Size menuItemTextSize = menuItem.GetTextSize(); if (menuItem.ShowShortcutKeys) { Size shortcutTextSize = menuItem.GetShortcutTextSize(); if (tabWidth == -1) { tabWidth = TextRenderer.MeasureText("\t", this.Font).Width; } menuItemTextSize.Width += tabWidth + shortcutTextSize.Width; menuItemTextSize.Height = Math.Max(menuItemTextSize.Height, shortcutTextSize.Height); } // we truly only care about the maximum size we find. maxTextSize.Width = Math.Max(maxTextSize.Width, menuItemTextSize.Width); maxTextSize.Height = Math.Max(maxTextSize.Height, menuItemTextSize.Height); // determine Image Metrics Size imageSize = Size.Empty; if (menuItem.Image != null) { imageSize = (menuItem.ImageScaling == ToolStripItemImageScaling.SizeToFit) ? ImageScalingSize : menuItem.Image.Size; } maxImageSize.Width = Math.Max(maxImageSize.Width, imageSize.Width); maxImageSize.Height = Math.Max(maxImageSize.Height, imageSize.Height); if (menuItem.CheckedImage != null) { Size checkedImageSize = menuItem.CheckedImage.Size; maxCheckSize.Width = Math.Max(checkedImageSize.Width, maxCheckSize.Width); maxCheckSize.Height = Math.Max(checkedImageSize.Height, maxCheckSize.Height); } } else if (!(item is ToolStripSeparator)) { maxNonMenuItemSize.Height = Math.Max(item.Bounds.Height, maxNonMenuItemSize.Height); maxNonMenuItemSize.Width = Math.Max(item.Bounds.Width, maxNonMenuItemSize.Width); } } this.maxItemSize.Height = Math.Max(maxTextSize.Height + TextPadding.Vertical, Math.Max(maxCheckSize.Height + CheckPadding.Vertical, maxArrowSize.Height + ArrowPadding.Vertical)); if (ShowImageMargin) { // only add in the image into the calculation if we're going to render it. this.maxItemSize.Height = Math.Max(maxImageSize.Height + ImagePadding.Vertical, maxItemSize.Height); } bool useDefaultCheckMarginWidth = (ShowCheckMargin && (maxCheckSize.Width == 0)); bool useDefaultImageMarginWidth = (ShowImageMargin && (maxImageSize.Width == 0)); // Always save space for an arrow maxArrowSize = new Size(10, maxItemSize.Height); maxTextSize.Height = maxItemSize.Height - TextPadding.Vertical; maxImageSize.Height = maxItemSize.Height - ImagePadding.Vertical; maxCheckSize.Height = maxItemSize.Height - CheckPadding.Vertical; // fixup if there are non-menu items that are larger than our normal menu items maxTextSize.Width = Math.Max(maxTextSize.Width, maxNonMenuItemSize.Width); Point nextPoint = Point.Empty; int checkAndImageMarginWidth = 0; int extraImageWidth = Math.Max(0, maxImageSize.Width - defaultImageSize.Width); if (ShowCheckMargin && ShowImageMargin) { // double column - check margin then image margin // default to 46px - grow if necessary. checkAndImageMarginWidth = DefaultImageAndCheckMarginWidth; // add in the extra space for the image... since the check size is locked down to 16x16. checkAndImageMarginWidth += extraImageWidth; // align the checkmark nextPoint = new Point(CheckPadding.Left, CheckPadding.Top); checkRectangle = LayoutUtils.Align(maxCheckSize, new Rectangle(nextPoint.X, nextPoint.Y, maxCheckSize.Width, maxItemSize.Height), ContentAlignment.MiddleCenter); // align the image rectangle nextPoint.X = checkRectangle.Right + CheckPadding.Right + ImagePadding.Left; nextPoint.Y = ImagePadding.Top; imageRectangle = LayoutUtils.Align(maxImageSize, new Rectangle(nextPoint.X, nextPoint.Y, maxImageSize.Width, maxItemSize.Height), ContentAlignment.MiddleCenter); } else if (ShowCheckMargin) { // no images should be shown in a ShowCheckMargin only scenario. // default to 24px - grow if necessary. checkAndImageMarginWidth = DefaultImageMarginWidth; // align the checkmark nextPoint = new Point(1,CheckPadding.Top); // nextPoint = new Point(CheckPadding.Left, CheckPadding.Top); checkRectangle = LayoutUtils.Align(maxCheckSize, new Rectangle(nextPoint.X, nextPoint.Y, checkAndImageMarginWidth, maxItemSize.Height), ContentAlignment.MiddleCenter); imageRectangle = Rectangle.Empty; } else if (ShowImageMargin) { // checks and images render in the same area. // default to 24px - grow if necessary. checkAndImageMarginWidth = DefaultImageMarginWidth; // add in the extra space for the image... since the check size is locked down to 16x16. checkAndImageMarginWidth += extraImageWidth; // NOTE due to the Padding property, we're going to have to recalc the vertical alignment in ToolStripMenuItemInternalLayout. // Dont fuss here over the Y, X is what's critical. // check and image rect are the same - take the max of the image size and the check size and align nextPoint = new Point(1,CheckPadding.Top); checkRectangle = LayoutUtils.Align(LayoutUtils.UnionSizes(maxCheckSize,maxImageSize), new Rectangle(nextPoint.X, nextPoint.Y, checkAndImageMarginWidth-1, maxItemSize.Height), ContentAlignment.MiddleCenter); // align the image imageRectangle = checkRectangle; } else { checkAndImageMarginWidth = 0; } nextPoint.X = checkAndImageMarginWidth+1; // calculate space for image // if we didnt have a check - make sure to ignore check padding // consider: should we constrain to a reasonable width? //imageMarginBounds = new Rectangle(0, 0, Math.Max(imageMarginWidth,DefaultImageMarginWidth), this.Height); imageMarginBounds = new Rectangle(0,0,checkAndImageMarginWidth, this.Height); // calculate space for shortcut and text nextPoint.X = imageMarginBounds.Right+ TextPadding.Left; nextPoint.Y = TextPadding.Top; textRectangle = new Rectangle(nextPoint, maxTextSize); // calculate space for arrow nextPoint.X = textRectangle.Right+ TextPadding.Right +ArrowPadding.Left; nextPoint.Y = ArrowPadding.Top; arrowRectangle = new Rectangle(nextPoint, maxArrowSize); // calculate space required for all of these pieces this.maxItemSize.Width = (arrowRectangle.Right + ArrowPadding.Right) - imageMarginBounds.Left; this.Padding = DefaultPadding; int trimPadding = imageMarginBounds.Width; if (RightToLeft == RightToLeft.Yes) { // reverse the rectangle alignment in RightToLeft.Yes trimPadding += TextPadding.Right; int width = maxItemSize.Width; checkRectangle.X = width - checkRectangle.Right; imageRectangle.X = width - imageRectangle.Right; textRectangle.X = width - textRectangle.Right; arrowRectangle.X = width - arrowRectangle.Right; imageMarginBounds.X = width - imageMarginBounds.Right; } else { trimPadding += TextPadding.Left; } // VSWhidbey 339274 - we need to make sure that the text really appears vertically centered - this can be a problem in // systems which force the text rectangle to be odd. // force this to be an even height. this.maxItemSize.Height += this.maxItemSize.Height%2; textRectangle.Y = LayoutUtils.VAlign(textRectangle.Size, new Rectangle(Point.Empty, maxItemSize), ContentAlignment.MiddleCenter).Y; textRectangle.Y += (textRectangle.Height %2); // if the height is odd, push down by one px, see 339274 for picture state[stateMaxItemSizeValid]=true; this.PaddingToTrim = trimPadding; } internal override void ChangeSelection(ToolStripItem nextItem) { if (nextItem != null) { Rectangle displayRect = DisplayRectangle; if (!displayRect.Contains(displayRect.X, nextItem.Bounds.Top) || !displayRect.Contains(displayRect.X, nextItem.Bounds.Bottom)) { int delta; if (displayRect.Y > nextItem.Bounds.Top) { delta = nextItem.Bounds.Top - displayRect.Y; } else { delta = nextItem.Bounds.Bottom - (displayRect.Y + displayRect.Height); // Now adjust so that the item at the top isn't truncated. int index = this.Items.IndexOf(nextItem); while (index >= 0) { if (this.Items[index].Visible && displayRect.Contains(displayRect.X, this.Items[index].Bounds.Top - delta)) { --index; } else { break; } } if (index >= 0) { if (displayRect.Contains(displayRect.X, this.Items[index].Bounds.Bottom - delta)) { // We found an item which is truncated at the top. delta += (this.Items[index].Bounds.Bottom - delta) - displayRect.Top; } } } this.ScrollInternal(delta); this.UpdateScrollButtonStatus(); } } base.ChangeSelection(nextItem); } protected internal override ToolStripItem CreateDefaultItem(string text, Image image, EventHandler onClick) { if (text == "-") { return new ToolStripSeparator(); } else { return new ToolStripMenuItem(text,image,onClick); } } internal override ToolStripItem GetNextItem(ToolStripItem start, ArrowDirection direction, bool rtlAware) { // for up/down we dont care about flipping left/right tab should still take you down. return GetNextItem(start, direction); } internal override void Initialize() { base.Initialize(); this.Padding = DefaultPadding; FlowLayoutSettings settings = FlowLayout.CreateSettings(this); settings.FlowDirection = FlowDirection.TopDown; state[stateShowImageMargin] = true; } /// protected override void OnLayout(LayoutEventArgs e) { if (!this.IsDisposed) { // We always layout as if we don't need scroll buttons. // If we do, then we'll adjust the positions to match. this.RequiresScrollButtons = false; CalculateInternalLayoutMetrics(); base.OnLayout(e); if (!this.RequiresScrollButtons) { this.ResetScrollPosition(); } } } protected override void OnFontChanged(EventArgs e) { tabWidth = -1; base.OnFontChanged(e); } /// protected override void OnPaintBackground(PaintEventArgs e) { base.OnPaintBackground(e); if (ShowCheckMargin || ShowImageMargin) { Renderer.DrawImageMargin(new ToolStripRenderEventArgs(e.Graphics, this, this.ImageMargin, SystemColors.Control)); } } internal override bool RequiresScrollButtons { get { return GetToolStripState(STATE_SCROLLBUTTONS); } set { bool changed = (RequiresScrollButtons != value); SetToolStripState(STATE_SCROLLBUTTONS, value); if (changed) { UpdateScrollButtonLocations(); if (this.Items.Count > 0) { int delta = this.Items[0].Bounds.Top - this.DisplayRectangle.Top; this.ScrollInternal(delta); this.scrollAmount -= delta; if (value) { RestoreScrollPosition(); } } else { this.scrollAmount = 0; } } } } internal void ResetScrollPosition() { this.scrollAmount = 0; } internal void RestoreScrollPosition() { if (!RequiresScrollButtons || this.Items.Count == 0) { return; } // We don't just scroll by the amount, because that might // cause the bottom of the menu to be blank if some items have // been removed/hidden since the last time we were displayed. // This also deals with items of different height, so that we don't truncate // and items under the top scrollbar. Rectangle displayRectangle = this.DisplayRectangle; int alreadyScrolled = displayRectangle.Top - this.Items[0].Bounds.Top; int requiredScrollAmount = this.scrollAmount - alreadyScrolled; int deltaToScroll = 0; if (requiredScrollAmount > 0) { for (int i = 0; i < this.Items.Count && deltaToScroll < requiredScrollAmount; ++i) { if (this.Items[i].Available) { Rectangle adjustedLastItemBounds = this.Items[this.Items.Count - 1].Bounds; adjustedLastItemBounds.Y -= deltaToScroll; if (displayRectangle.Contains(displayRectangle.X, adjustedLastItemBounds.Top) && displayRectangle.Contains(displayRectangle.X, adjustedLastItemBounds.Bottom)) { // Scrolling this amount would make the last item visible, so don't scroll any more. break; } // We use a delta between the tops, since it takes margin's and padding into account. if (i < this.Items.Count - 1) { deltaToScroll += this.Items[i + 1].Bounds.Top - this.Items[i].Bounds.Top; } else { deltaToScroll += this.Items[i].Bounds.Height; } } } } else { for (int i = this.Items.Count - 1; i >= 0 && deltaToScroll > requiredScrollAmount; --i) { if (this.Items[i].Available) { Rectangle adjustedLastItemBounds = this.Items[0].Bounds; adjustedLastItemBounds.Y -= deltaToScroll; if (displayRectangle.Contains(displayRectangle.X, adjustedLastItemBounds.Top) && displayRectangle.Contains(displayRectangle.X, adjustedLastItemBounds.Bottom)) { // Scrolling this amount would make the last item visible, so don't scroll any more. break; } // We use a delta between the tops, since it takes margin's and padding into account. if (i > 0) { deltaToScroll -= this.Items[i].Bounds.Top - this.Items[i - 1].Bounds.Top; } else { deltaToScroll -= this.Items[i].Bounds.Height; } } } } this.ScrollInternal(deltaToScroll); this.scrollAmount = this.DisplayRectangle.Top - this.Items[0].Bounds.Top; UpdateScrollButtonLocations(); } internal override void ScrollInternal(int delta) { base.ScrollInternal(delta); this.scrollAmount += delta; } internal void ScrollInternal(bool up) { UpdateScrollButtonStatus(); // calling this to get ScrollWindowEx. In actuality it does nothing // to change the display rect! int delta; if (this.indexOfFirstDisplayedItem == -1 || this.indexOfFirstDisplayedItem >= this.Items.Count) { Debug.Fail("Why wasn't 'UpdateScrollButtonStatus called'? We don't have the item to scroll by"); int menuHeight = SystemInformation.MenuHeight; delta = up ? -menuHeight : menuHeight; } else { if (up) { if (this.indexOfFirstDisplayedItem == 0) { Debug.Fail("We're trying to scroll up, but the top item is displayed!!!"); delta = 0; } else { ToolStripItem itemTop = this.Items[this.indexOfFirstDisplayedItem - 1]; ToolStripItem itemBottom = this.Items[this.indexOfFirstDisplayedItem]; // We use a delta between the tops, since it takes margin's and padding into account. delta = itemTop.Bounds.Top - itemBottom.Bounds.Top; } } else { if (this.indexOfFirstDisplayedItem == this.Items.Count - 1) { Debug.Fail("We're trying to scroll down, but the top item is displayed!!!"); delta = 0; } ToolStripItem itemTop = this.Items[this.indexOfFirstDisplayedItem]; ToolStripItem itemBottom = this.Items[this.indexOfFirstDisplayedItem + 1]; // We use a delta between the tops, since it takes margin's and padding into account. delta = itemBottom.Bounds.Top - itemTop.Bounds.Top; } } ScrollInternal(delta); UpdateScrollButtonLocations(); } /// protected override void SetDisplayedItems() { base.SetDisplayedItems(); if (RequiresScrollButtons) { this.DisplayedItems.Add(UpScrollButton); this.DisplayedItems.Add(DownScrollButton); UpdateScrollButtonLocations(); UpScrollButton.Visible = true; DownScrollButton.Visible = true; } else { UpScrollButton.Visible = false; DownScrollButton.Visible = false; } } private void UpdateScrollButtonLocations() { if (GetToolStripState(STATE_SCROLLBUTTONS)) { Size upSize = UpScrollButton.GetPreferredSize(Size.Empty); // Point upLocation = new Point(1, 0); UpScrollButton.SetBounds(new Rectangle(upLocation, upSize)); Size downSize = DownScrollButton.GetPreferredSize(Size.Empty); int height = GetDropDownBounds(this.Bounds).Height; Point downLocation = new Point(1, height - downSize.Height); DownScrollButton.SetBounds(new Rectangle(downLocation, downSize)); UpdateScrollButtonStatus(); } } private void UpdateScrollButtonStatus() { Rectangle displayRectangle = this.DisplayRectangle; this.indexOfFirstDisplayedItem = -1; int minY = int.MaxValue, maxY = 0; for (int i = 0; i < this.Items.Count; ++i) { ToolStripItem item = this.Items[i]; if (UpScrollButton == item) { continue; } if (DownScrollButton == item) { continue; } if (!item.Available) { continue; } if (this.indexOfFirstDisplayedItem == -1 && displayRectangle.Contains(displayRectangle.X, item.Bounds.Top)) { this.indexOfFirstDisplayedItem = i; } minY = Math.Min(minY, item.Bounds.Top); maxY = Math.Max(maxY, item.Bounds.Bottom); } UpScrollButton.Enabled = !displayRectangle.Contains(displayRectangle.X, minY); DownScrollButton.Enabled = !displayRectangle.Contains(displayRectangle.X, maxY); } internal sealed class ToolStripDropDownLayoutEngine : FlowLayout { public static ToolStripDropDownLayoutEngine LayoutInstance = new ToolStripDropDownLayoutEngine(); internal override Size GetPreferredSize(IArrangedElement container, Size proposedConstraints) { Size preferredSize = base.GetPreferredSize(container, proposedConstraints); ToolStripDropDownMenu dropDownMenu = container as ToolStripDropDownMenu; if (dropDownMenu != null) { preferredSize.Width = dropDownMenu.MaxItemSize.Width - dropDownMenu.PaddingToTrim; } return preferredSize; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- PasswordTextNavigator.cs
- SqlTopReducer.cs
- HtmlContainerControl.cs
- SoundPlayerAction.cs
- COM2PropertyDescriptor.cs
- DeferredElementTreeState.cs
- SQLInt64Storage.cs
- SamlAuthenticationStatement.cs
- MailAddressCollection.cs
- WebResourceUtil.cs
- Column.cs
- TypeExtensionConverter.cs
- NumberSubstitution.cs
- InternalResources.cs
- loginstatus.cs
- ColorBlend.cs
- XmlValidatingReaderImpl.cs
- ThemeableAttribute.cs
- ObjectDataSourceMethodEditor.cs
- OSFeature.cs
- InvalidEnumArgumentException.cs
- ResponseStream.cs
- XmlSchemaAnnotated.cs
- SerializableTypeCodeDomSerializer.cs
- DbDataRecord.cs
- DataListCommandEventArgs.cs
- CodeVariableDeclarationStatement.cs
- Base64Stream.cs
- DictionaryEntry.cs
- CssStyleCollection.cs
- EditorBrowsableAttribute.cs
- DPCustomTypeDescriptor.cs
- OleDbParameterCollection.cs
- SiteIdentityPermission.cs
- DataTemplate.cs
- ToolbarAUtomationPeer.cs
- Wow64ConfigurationLoader.cs
- WbmpConverter.cs
- SchemaExporter.cs
- NoneExcludedImageIndexConverter.cs
- AspNetSynchronizationContext.cs
- SplitContainer.cs
- StylusButtonEventArgs.cs
- TimelineGroup.cs
- DocumentApplicationDocumentViewer.cs
- ScrollBar.cs
- SingleBodyParameterMessageFormatter.cs
- TreeNodeEventArgs.cs
- Rfc2898DeriveBytes.cs
- OdbcUtils.cs
- RevocationPoint.cs
- ResourceWriter.cs
- NativeObjectSecurity.cs
- ProjectedSlot.cs
- GeneralTransform3DTo2D.cs
- Point4DValueSerializer.cs
- BinaryNode.cs
- BinaryFormatterWriter.cs
- QueryCacheManager.cs
- ToolStripDropTargetManager.cs
- ScrollBar.cs
- SpecialNameAttribute.cs
- BitmapSource.cs
- WindowsListViewItemStartMenu.cs
- XmlNamedNodeMap.cs
- SafeNativeMethodsMilCoreApi.cs
- ComAdminWrapper.cs
- MergeFilterQuery.cs
- ColumnHeaderConverter.cs
- DoubleAnimationUsingKeyFrames.cs
- UserInitiatedNavigationPermission.cs
- SqlLiftWhereClauses.cs
- ErrorWebPart.cs
- NgenServicingAttributes.cs
- FixedPageProcessor.cs
- ResourceSetExpression.cs
- ShaderEffect.cs
- webeventbuffer.cs
- DataTemplate.cs
- TextModifier.cs
- EndPoint.cs
- VBCodeProvider.cs
- SoapHelper.cs
- TextModifier.cs
- AnnotationResourceChangedEventArgs.cs
- IndexerNameAttribute.cs
- FrameworkElement.cs
- CompiledELinqQueryState.cs
- FixedDocument.cs
- VirtualPathExtension.cs
- ActivityValidationServices.cs
- StrokeSerializer.cs
- messageonlyhwndwrapper.cs
- NeutralResourcesLanguageAttribute.cs
- HtmlElementCollection.cs
- Grid.cs
- ContentValidator.cs
- OleDbPropertySetGuid.cs
- mongolianshape.cs
- HostnameComparisonMode.cs