private ShengAddressBarDropDown GetButtonDropDown(IShengAddressNode addressNode) { ShengAddressBarDropDown dropDown = new ShengAddressBarDropDown(); if (this.DropDownRenderer != null) { dropDown.Renderer = this.DropDownRenderer; } dropDown.LayoutStyle = ToolStripLayoutStyle.Table; dropDown.MaximumSize = new Size(1000, 400); dropDown.Opening += new CancelEventHandler(DropDown_Opening); /* * This is the primary bottleneck for this app, creating all the necessary drop-down menu items. * * To optimize performance of this control, this is the main area that needs tuning. */ IShengAddressNode curNode = null; for (int i = 0; i < addressNode.Children.Length; i++) { curNode = (IShengAddressNode)addressNode.Children.GetValue(i); ShengAddressBarDropDownItem tsb = null; tsb = new ShengAddressBarDropDownItem(curNode.DisplayName, curNode.Icon, NodeButtonClicked); tsb.AddressNode = curNode; tsb.Overflow = ToolStripItemOverflow.AsNeeded; dropDown.Items.Add(tsb); //THIS IS THE BIGGEST BOTTLENECK. LOTS OF TIME SPENT IN/CALLING THIS METHOD! } addressNode.DropDownMenu = dropDown; dropDown.LayoutStyle = ToolStripLayoutStyle.Table; dropDown.MaximumSize = new Size(1000, 400); dropDown.AddressNode = addressNode; //不起作用 dropDown.MouseWheel += new MouseEventHandler(ScrollDropDownMenu); dropDown.MouseEnter += new EventHandler(GiveToolStripDropDownMenuFocus); return(dropDown); }
/// <summary> /// Method to handle when a child has been selected from a node /// </summary> /// <param name="sender">Sender of this Event</param> /// <param name="e">Event Arguments</param> private void NodeButtonClicked(Object sender, EventArgs e) { if (sender.GetType() == typeof(ShengAddressBarDropDownItem) || sender.GetType() == typeof(ShengAddressBarButton)) { IShengAddressNode addressNode; if (sender.GetType() == typeof(ShengAddressBarDropDownItem)) { ShengAddressBarDropDownItem tsb = (ShengAddressBarDropDownItem)sender; addressNode = tsb.AddressNode; } else { ShengAddressBarButton tsb = (ShengAddressBarButton)sender; addressNode = tsb.AddressNode; } //set the current node _currentNode = addressNode; //cxs //用不着整个都重新加载,在当前最后一个Item后面加上点的这个就行了 //但是要额外考虑点击的是哪个下拉按钮,如果是中间的,还是要整个刷 ResetBar(); //if (sender.GetType().Equals(typeof(SEAddressBarButton))) //{ // UpdateBar(); //} //else //{ // AddToolStripItemUpdate(ref _currentNode,ButtonPosition.Behind); //} //if the selection changed event is handled if (SelectionChange != null) { NodeChangedArgs args = new NodeChangedArgs(_currentNode.UniqueID); SelectionChange(this, args); } return; } }
/// <summary> /// 添加一个地址栏项 /// </summary> /// <param name="button"></param> /// <param name="position"></param> private void AddAddressBarButton(ShengAddressBarButton button, ButtonPosition position) { //如果当前显示了最左下拉菜单,就需要直接加在最左下拉菜单下 //如果直接加左边,可能整个地址条是够显示的,就造成这一项出现在最左下拉前面 //并且如果直接加在最左下拉下面,就不用去管是否还有子级了,因为不需要显示那个向下箭头了 if (this.Items.Contains(_overflowButton)) { ShengAddressBarDropDownItem dropDownItem = new ShengAddressBarDropDownItem(button.Text, button.Image, NodeButtonClicked); dropDownItem.AddressNode = button.AddressNode; //_overflowButton.DropDown.Items.Add(dropDownItem); _overflowDropDown.Items.Add(dropDownItem); } else { //处理子级,如果需要,需要显示一个向下箭头 BuildChildItem(button); if (position == ButtonPosition.Behind) { this.Items.Add(button); if (button.DropDownButton != null) { this.Items.Add(button.DropDownButton); } _buttonList.Add(button); } else { this.Items.Insert(0, button); if (button.DropDownButton != null) { this.Items.Insert(1, button.DropDownButton); } _buttonList.Insert(0, button); } } }
/// <summary> /// 创建最左下拉菜单 /// </summary> private void CreateOverflowDropDown() { //在最左边添加下拉菜单 if (this.Items.Contains(_overflowButton) == false) { this.Items.Insert(0, _overflowButton); _overflowButton.OwnerChanged += new EventHandler(OverflowDestroyed); if (this.DropDownRenderer != null) { _overflowDropDown.Renderer = this.DropDownRenderer; } } /* * 把第一项移到前下拉里,然后测试是否还是不够显示,如果还是不够 * 再次把第一项移到前下拉里,如此反复 * 但有一点,需判断第一项是否就是当前项,如果就是当前项,则表示是当前项显示文本太长 * 所以不够显示,需要截断当前项的显示文本 */ _overflowDropDown.Items.Clear(); while (true) { ShengAddressBarButton frontButton = _buttonList[0]; //如果当前节点已经是最右边的节点了 if (_currentNode == frontButton.AddressNode) { //计算可以显示的宽度 int itemWidth = 0; foreach (ToolStripItem item in frontButton.Owner.Items) { if (item == frontButton) { continue; } itemWidth += item.Width; } itemWidth = frontButton.Owner.Width - itemWidth - 40; frontButton.Text = AdjustTextForDisplay(frontButton.Text, itemWidth, frontButton.Font); break; ////通过截断显示字符串的方式以让它能显示得下 ////简单起见,直接截一半,暂时不去测量文本了,截完以后需继续判断,不行再截一半,直到截到最后个字符 //if (frontButton.Text.Length <= 1) //{ // break; //} //else //{ // frontButton.Text = frontButton.Text.Substring(0, frontButton.Text.Length / 2) + "..."; // if (IsManyNodes()) // { // CreateOverflowDropDown(); // } // break; //} } else { ShengAddressBarDropDownItem dropDownItem = null; dropDownItem = new ShengAddressBarDropDownItem(frontButton.Text, frontButton.Image, NodeButtonClicked); dropDownItem.AddressNode = frontButton.AddressNode; //把靠左边的第一个项移入最左下拉菜单的顶部 _overflowDropDown.Items.Insert(0, dropDownItem); this.Items.Remove(frontButton); if (frontButton.DropDownButton != null) { this.Items.Remove(frontButton.DropDownButton); } _buttonList.Remove(frontButton); } if (IsManyNodes() == false) { break; } } }