12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550 |
- using PaintDotNet.SystemLayer;
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Drawing;
- using System.Drawing.Drawing2D;
- using System.Windows.Forms;
- using System.Windows.Forms.VisualStyles;
- namespace PaintDotNet
- {
- public class IBottomNameStrip : Control
- {
- public enum ItemPart
- {
- None,
- Image,
- CloseButton
- }
- public sealed class Item
- {
- private Rectangle rectangle;
- private PushButtonState imageRenderState;
- /// <summary>
- /// 图片
- /// </summary>
- private Image image;
- /// <summary>
- ///
- /// </summary>
- private string name;
- /// <summary>
- /// 文字颜色
- /// </summary>
- private Color nColor;
- private bool selected;
- private PushButtonState checkRenderState;
- private CheckState checkState;
- private PushButtonState closeRenderState;
- private bool dirty;
- private bool lockedDirtyValue;
- private int dirtyValueLockCount = 0;
- /// <summary>
- /// Tag
- /// </summary>
- private object tag;
- public event EventHandler Changed;
- private void OnChanged()
- {
- if (Changed != null)
- {
- Changed(this, EventArgs.Empty);
- }
- }
- /// <summary>
- /// checkbox的被选中/取消选中事件
- /// 实际上没有用checkbox,而是自己画的,自己控制的逻辑
- /// </summary>
- public event EventHandler CheckChanged;
- private void OnCheckChanged()
- {
- if (CheckChanged != null)
- {
- CheckChanged(this, EventArgs.Empty);
- }
- }
- public Rectangle Rectangle
- {
- get
- {
- return this.rectangle;
- }
- set
- {
- this.rectangle = value;
- }
- }
- public string Name
- {
- get
- {
- return this.name;
- }
- set
- {
- this.name = value;
- OnChanged();
- }
- }
- public Color NColor
- {
- get
- {
- return this.nColor;
- }
- set
- {
- this.nColor = value;
- OnChanged();
- }
- }
- public Image Image
- {
- get
- {
- return this.image;
- }
- set
- {
- this.image = value;
- OnChanged();
- }
- }
- public PushButtonState ImageRenderState
- {
- get
- {
- return this.imageRenderState;
- }
- set
- {
- if (this.imageRenderState != value)
- {
- this.imageRenderState = value;
- OnChanged();
- }
- }
- }
- public bool Selected
- {
- get
- {
- return this.selected;
- }
- set
- {
- if (this.selected != value)
- {
- this.selected = value;
- OnChanged();
- }
- }
- }
- public bool Dirty
- {
- get
- {
- if (this.dirtyValueLockCount > 0)
- {
- return this.lockedDirtyValue;
- }
- else
- {
- return this.dirty;
- }
- }
- set
- {
- if (this.dirty != value)
- {
- this.dirty = value;
- if (this.dirtyValueLockCount <= 0)
- {
- OnChanged();
- }
- }
- }
- }
- public void LockDirtyValue(bool forceValue)
- {
- ++this.dirtyValueLockCount;
- if (this.dirtyValueLockCount == 1)
- {
- this.lockedDirtyValue = forceValue;
- }
- }
- public void UnlockDirtyValue()
- {
- --this.dirtyValueLockCount;
- if (this.dirtyValueLockCount == 0)
- {
- OnChanged();
- }
- else if (this.dirtyValueLockCount < 0)
- {
- throw new InvalidOperationException("Calls to UnlockDirtyValue() must be matched by a preceding call to LockDirtyValue()");
- }
- }
- public bool Checked
- {
- get
- {
- return (CheckState == CheckState.Checked);
- }
- set
- {
- if (value)
- {
- CheckState = CheckState.Checked;
- }
- else
- {
- CheckState = CheckState.Unchecked;
- }
- }
- }
- public CheckState CheckState
- {
- get
- {
- return this.checkState;
- }
- set
- {
- if (this.checkState != value)
- {
- this.checkState = value;
- OnChanged();
- OnCheckChanged();
- }
- }
- }
- public PushButtonState CheckRenderState
- {
- get
- {
- return this.checkRenderState;
- }
- set
- {
- if (this.checkRenderState != value)
- {
- this.checkRenderState = value;
- OnChanged();
- }
- }
- }
- public PushButtonState CloseRenderState
- {
- get
- {
- return this.closeRenderState;
- }
- set
- {
- if (this.closeRenderState != value)
- {
- this.closeRenderState = value;
- OnChanged();
- }
- }
- }
- public void SetPartRenderState(ItemPart itemPart, PushButtonState renderState)
- {
- switch (itemPart)
- {
- case ItemPart.None:
- break;
- case ItemPart.CloseButton:
- CloseRenderState = renderState;
- break;
- case ItemPart.Image:
- ImageRenderState = renderState;
- break;
- default:
- throw new InvalidEnumArgumentException();
- }
- }
- public object Tag
- {
- get
- {
- return this.tag;
- }
- set
- {
- this.tag = value;
- OnChanged();
- }
- }
- public void Update()
- {
- OnChanged();
- }
- public Item()
- {
- }
- public Item(Image image)
- {
- this.image = image;
- }
- }
- private bool managedFocus = false;
- private bool showScrollButtons = true;//false;
- private bool allowMultiChoise = true;//模式是多选模式
- private ArrowButton leftScrollButton;
- private ArrowButton rightScrollButton;
- private int scrollOffset = 0;
- private bool showCheckButtons = false;
- private bool showCloseButtons = false;
- private const int closeButtonLength = 13;
- private int imagePadding = 2;
- private int closeButtonPadding = 2;
- private int mouseOverIndex = -1;
- private ItemPart mouseOverItemPart = ItemPart.None;
- private bool mouseOverApplyRendering = false;
- private int mouseDownIndex = -1;
- private MouseButtons mouseDownButton = MouseButtons.None;
- private ItemPart mouseDownItemPart = ItemPart.None;
- private bool mouseDownApplyRendering = false;
- private bool showCheckedColor = true;
- private bool drawDirtyOverlay = true;
- public bool ShowCheckedColor
- {
- get
- {
- return this.showCheckedColor;
- }
- set
- {
- if (this.showCheckedColor != value)
- {
- this.showCheckedColor = value;
- Refresh();
- }
- }
- }
- public bool DrawDirtyOverlay
- {
- get
- {
- return this.drawDirtyOverlay;
- }
- set
- {
- if (this.drawDirtyOverlay != value)
- {
- this.drawDirtyOverlay = value;
- Refresh();
- }
- }
- }
- // This is done as an optimization: otherwise we're getting flooded with MouseMove events
- // and constantly refreshing our rendering. So CPU usage goes to heck.
- private Point lastMouseMovePt = new Point(-32000, -32000);
- public List<Item> items = new List<Item>();
- protected ArrowButton LeftScrollButton
- {
- get
- {
- return this.leftScrollButton;
- }
- }
- protected ArrowButton RightScrollButton
- {
- get
- {
- return this.rightScrollButton;
- }
- }
- private void MouseStatesToItemStates()
- {
- UI.SuspendControlPainting(this);
- for (int i = 0; i < this.items.Count; ++i)
- {
- this.items[i].CheckRenderState = PushButtonState.Normal;
- this.items[i].CloseRenderState = PushButtonState.Normal;
- this.items[i].ImageRenderState = PushButtonState.Normal;
- this.items[i].Selected = false;
- }
- if (this.mouseDownApplyRendering)
- {
- if (this.mouseDownIndex < 0 || this.mouseDownIndex >= this.items.Count)
- {
- this.mouseDownApplyRendering = false;
- }
- else
- {
- this.items[this.mouseDownIndex].SetPartRenderState(this.mouseDownItemPart, PushButtonState.Pressed);
- this.items[this.mouseDownIndex].Selected = true;
- }
- }
- else if (this.mouseOverApplyRendering)
- {
- if (this.mouseOverIndex < 0 || this.mouseOverIndex >= this.items.Count)
- {
- this.mouseOverApplyRendering = false;
- }
- else
- {
- this.items[this.mouseOverIndex].SetPartRenderState(this.mouseOverItemPart, PushButtonState.Hot);
- this.items[this.mouseOverIndex].Selected = true;
- }
- }
- UI.ResumeControlPainting(this);
- Invalidate();
- }
- public IBottomNameStrip()
- {
- SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint, true);
- SetStyle(ControlStyles.Selectable, false);
- DoubleBuffered = true;
- ResizeRedraw = true;
- InitializeComponent();
- }
- private void InitializeComponent()
- {
- this.leftScrollButton = new ArrowButton();
- this.rightScrollButton = new ArrowButton();
- SuspendLayout();
- //
- // leftScrollButton
- //
- this.leftScrollButton.Name = "leftScrollButton";
- this.leftScrollButton.drawTransparentBackColor = false;
- this.leftScrollButton.ArrowDirection = ArrowDirection.Left;
- this.leftScrollButton.ArrowOutlineWidth = 1.0f;
- this.leftScrollButton.Click += new EventHandler(LeftScrollButton_Click);
- this.leftScrollButton.DrawWithGradient = true;
- //
- // rightScrollButton
- //
- this.rightScrollButton.Name = "rightScrollButton";
- this.rightScrollButton.drawTransparentBackColor = false;
- this.rightScrollButton.ArrowDirection = ArrowDirection.Right;
- this.rightScrollButton.ArrowOutlineWidth = 1.0f;
- this.rightScrollButton.Click += new EventHandler(RightScrollButton_Click);
- this.rightScrollButton.DrawWithGradient = true;
- //
- // ImageStrip
- //
- this.Name = "ImageStrip";
- this.TabStop = false;
- this.Controls.Add(this.leftScrollButton);
- this.Controls.Add(this.rightScrollButton);
- ResumeLayout();
- PerformLayout();
- }
- public event EventHandler<EventArgs<ArrowDirection>> ScrollArrowClicked;
- protected virtual void OnScrollArrowClicked(ArrowDirection arrowDirection)
- {
- if (ScrollArrowClicked != null)
- {
- ScrollArrowClicked(this, new EventArgs<ArrowDirection>(arrowDirection));
- }
- }
- private void LeftScrollButton_Click(object sender, EventArgs e)
- {
- Focus();
- OnScrollArrowClicked(ArrowDirection.Left);
- }
- private void RightScrollButton_Click(object sender, EventArgs e)
- {
- Focus();
- OnScrollArrowClicked(ArrowDirection.Right);
- }
- /// <summary>
- /// This event is raised when this control wishes to relinquish focus.
- /// </summary>
- public event EventHandler RelinquishFocus;
- private void OnRelinquishFocus()
- {
- if (RelinquishFocus != null)
- {
- RelinquishFocus(this, EventArgs.Empty);
- }
- }
- /// <summary>
- /// Gets or sets whether the control manages focus.
- /// </summary>
- /// <remarks>
- /// If this is true, the toolstrip will capture focus when the mouse enters its client area. It will then
- /// relinquish focus (via the RelinquishFocus event) when the mouse leaves. It will not capture or
- /// attempt to relinquish focus if MenuStripEx.IsAnyMenuActive returns true.
- /// </remarks>
- public bool ManagedFocus
- {
- get
- {
- return this.managedFocus;
- }
- set
- {
- this.managedFocus = value;
- }
- }
- public void AddItem(Item newItem)
- {
- if (this.items.Contains(newItem))
- {
- throw new ArgumentException("newItem was already added to this control");
- }
- //在这里计算名称的宽度开始 zyh
- //需要保证名称不能为空
- Size textSize = TextRenderer.MeasureText(newItem.Name, new Font(SystemFonts.DefaultFont.Name, 10, FontStyle.Regular));
- newItem.Rectangle = new Rectangle(0, 0, textSize.Width + 33, ClientSize.Height);
- //在这里计算名称的宽度结束 zyh
- newItem.Changed += Item_Changed;
- this.items.Add(newItem);
- PerformLayout();
- Invalidate();
- }
- public void RemoveItem(Item item)
- {
- if (!this.items.Contains(item))
- {
- throw new ArgumentException("item was never added to this control");
- }
- item.Changed -= Item_Changed;
- this.items.Remove(item);
- PerformLayout();
- Invalidate();
- }
- public void ClearItems()
- {
- SuspendLayout();
- UI.SuspendControlPainting(this);
- while (this.items.Count > 0)
- {
- RemoveItem(this.items[this.items.Count - 1]);
- }
- UI.ResumeControlPainting(this);
- ResumeLayout(true);
- Invalidate();
- }
- private void Item_Changed(object sender, EventArgs e)
- {
- Invalidate();
- }
- /// <summary>
- /// Raised when an item is clicked on.
- /// </summary>
- /// <remarks>
- /// e.Data.First is a reference to the Item.
- /// e.Data.Second is the ItemPart.
- /// e.Data.Third is the MouseButtons that was used to click on the ItemPart.
- /// </remarks>
- public event EventHandler<EventArgs<Triple<Item, ItemPart, MouseButtons>>> ItemClicked;
- protected virtual void OnItemClicked(Item item, ItemPart itemPart, MouseButtons mouseButtons)
- {
- if (ItemClicked != null)
- {
- ItemClicked(this, new EventArgs<Triple<Item, ItemPart, MouseButtons>>(
- Triple.Create(item, itemPart, mouseButtons)));
- }
- }
- public void PerformItemClick(int itemIndex, ItemPart itemPart, MouseButtons mouseButtons)
- {
- PerformItemClick(this.items[itemIndex], itemPart, mouseButtons);
- }
- public void PerformItemClick(Item item, ItemPart itemPart, MouseButtons mouseButtons)
- {
- OnItemClicked(item, itemPart, mouseButtons);
- }
- public Item[] Items
- {
- get
- {
- return this.items.ToArray();
- }
- }
- public int ItemCount
- {
- get
- {
- return this.items.Count;
- }
- }
- public bool AllowMultiChoise
- {
- get
- {
- return this.allowMultiChoise;
- }
- set
- {
- if (this.allowMultiChoise != value)
- {
- this.allowMultiChoise = value;
- PerformLayout();
- Invalidate(true);
- }
- }
- }
- public int MinScrollOffset
- {
- get
- {
- return 0;
- }
- }
- public int MaxScrollOffset
- {
- get
- {
- int itemsLength = GetAllItemWidth();//itemSize.Width * this.items.Count;
- int viewLength = itemsLength - ClientSize.Width;
- int maxScrollOffset = Math.Max(0, viewLength);
- return maxScrollOffset;
- }
- }
- public int ScrollOffset
- {
- get
- {
- return this.scrollOffset;
- }
- set
- {
- int clampedValue = Utility.Clamp(value, MinScrollOffset, MaxScrollOffset);
- if (this.scrollOffset != clampedValue)
- {
- this.scrollOffset = clampedValue;
- OnScrollOffsetChanged();
- Invalidate(true);
- }
- }
- }
- public event EventHandler ScrollOffsetChanged;
- protected virtual void OnScrollOffsetChanged()
- {
- PerformLayout();
- if (ScrollOffsetChanged != null)
- {
- ScrollOffsetChanged(this, EventArgs.Empty);
- }
- }
- /// <summary>
- /// 获取所有item的宽度和,
- /// 因为每个item和原来不一样了
- /// 原本item是等宽
- /// </summary>
- /// <returns></returns>
- public int GetAllItemWidth()
- {
- int widths = 0;
- for (int y = 0; y < items.Count; y++)
- {
- widths += items[y].Rectangle.Width;
- }
- return widths;
- }
- /// <summary>
- /// Gets the viewable area, in View coordinate space.
- /// </summary>
- public Rectangle ViewRectangle
- {
- get
- {
- Size itemSize = ItemSize;
- return new Rectangle(0, 0, GetAllItemWidth(), itemSize.Height);
- }
- }
- protected override void OnLayout(LayoutEventArgs levent)
- {
- int arrowWidth = UI.ScaleWidth(16);
- ScrollOffset = Utility.Clamp(this.scrollOffset, MinScrollOffset, MaxScrollOffset);
- // Determine arrow visibility / position
- this.leftScrollButton.Size = new Size(arrowWidth, ClientSize.Height);
- this.leftScrollButton.Location = new Point(0, 0);
- this.rightScrollButton.Size = new Size(arrowWidth, ClientSize.Height);
- this.rightScrollButton.Location = new Point(ClientSize.Width - this.rightScrollButton.Width, 0);
- bool showEitherButton = this.showScrollButtons && (this.ViewRectangle.Width > ClientRectangle.Width);
- bool showRightButton = (this.scrollOffset < MaxScrollOffset) && showEitherButton;
- bool showLeftButton = (this.scrollOffset > MinScrollOffset) && showEitherButton;
- this.rightScrollButton.Enabled = showRightButton;
- this.rightScrollButton.Visible = showRightButton;
- this.leftScrollButton.Enabled = showLeftButton;
- this.leftScrollButton.Visible = showLeftButton;
- base.OnLayout(levent);
- }
- public bool ShowCheckButtons
- {
- get
- {
- return this.showCheckButtons;
- }
- set
- {
- if (this.showCheckButtons != value)
- {
- this.showCheckButtons = value;
- PerformLayout();
- Invalidate();
- }
- }
- }
- public bool ShowCloseButtons
- {
- get
- {
- return this.showCloseButtons;
- }
- set
- {
- if (this.showCloseButtons != value)
- {
- this.showCloseButtons = value;
- PerformLayout();
- Invalidate();
- }
- }
- }
- public int PreferredMinClientWidth
- {
- get
- {
- if (this.items.Count == 0)
- {
- return 0;
- }
- int minWidth = ItemSize.Width;
- if (this.leftScrollButton.Visible || this.rightScrollButton.Visible)
- {
- minWidth += this.leftScrollButton.Width;
- minWidth += this.rightScrollButton.Width;
- }
- minWidth = Math.Min(minWidth, ViewRectangle.Width);
- return minWidth;
- }
- }
- public Size PreferredImageSize
- {
- get
- {
- Rectangle itemRect;
- MeasureItemPartRectangles(out itemRect, null);
- return new Size(itemRect.Width - imagePadding * 2, itemRect.Height - imagePadding * 2);
- }
- }
- public Size ItemSize
- {
- get
- {
- Rectangle itemRect;
- MeasureItemPartRectangles(out itemRect, null);
- return itemRect.Size;
- }
- }
- protected virtual void DrawItemBackground(Graphics g, Item item, Rectangle itemRect)
- {
- }
- protected virtual void DrawItemHighlight(
- Graphics g,
- Item item,
- Rectangle itemRect,
- Rectangle highlightRect)
- {
- Color backFillColor;
- Color outlineColor;
- Color textColor;
- if (item.Checked && this.showCheckedColor)
- {
- backFillColor = Color.FromArgb(192, SystemColors.Highlight);
- outlineColor = backFillColor;
- textColor = Color.White;
- }
- else if (item.Selected)
- {
- backFillColor = Color.FromArgb(64, SystemColors.HotTrack);
- outlineColor = Color.FromArgb(64, SystemColors.HotTrack);
- textColor = Color.Black;
- }
- else
- {
- backFillColor = Color.Transparent;
- outlineColor = Color.Transparent;
- textColor = Color.Black;
- }
- using (SolidBrush backFillBrush = new SolidBrush(backFillColor))
- {
- g.FillRectangle(backFillBrush, highlightRect);
- }
- using (Pen outlinePen = new Pen(outlineColor))
- {
- g.DrawRectangle(outlinePen, highlightRect.X, highlightRect.Y, highlightRect.Width - 1, highlightRect.Height - 1);
- }
- CheckBoxRenderer.DrawCheckBox(g, new Point(itemRect.X + 10, itemRect.Y + 10), (item.Checked && !this.showCheckedColor) ? CheckBoxState.CheckedNormal : CheckBoxState.UncheckedNormal);
- //CheckBoxRenderer.dr
- g.DrawString(item.Name, new Font(SystemFonts.DefaultFont.Name, 10, FontStyle.Regular), new SolidBrush(item.NColor != null ? item.NColor : textColor), new PointF(itemRect.X + 24, itemRect.Y + 10));
- g.DrawLine(new Pen(Color.FromArgb(189, 189, 189)), itemRect.X + itemRect.Width - 1, itemRect.Y, itemRect.X + itemRect.Width - 1, itemRect.Y + 25);
- }
- protected virtual void DrawItemCloseButton(
- Graphics g,
- Item item,
- Rectangle itemRect,
- Rectangle closeButtonRect)
- {
- if (item.Checked && item.Selected)
- {
- const string resourceNamePrefix = "Images.ImageStrip.CloseButton.";
- const string resourceNameSuffix = ".png";
- string resourceNameInfix = item.CloseRenderState.ToString();
- string resourceName = resourceNamePrefix + resourceNameInfix + resourceNameSuffix;
- ImageResource imageResource = PdnResources.GetImageResource(resourceName);
- Image image = imageResource.Reference;
- g.SmoothingMode = SmoothingMode.AntiAlias;
- g.InterpolationMode = InterpolationMode.HighQualityBicubic;
- g.DrawImage(image, closeButtonRect, new Rectangle(0, 0, image.Width, image.Width), GraphicsUnit.Pixel);
- }
- }
- protected virtual void DrawItemDirtyOverlay(
- Graphics g,
- Item item,
- Rectangle itemRect,
- Rectangle dirtyOverlayRect)
- {
- Color outerPenColor = Color.White;
- Color innerPenColor = Color.Orange;
- const int xInset = 2;
- int scaledXInset = UI.ScaleWidth(xInset);
- const float outerPenWidth = 4.0f;
- const float innerPenWidth = 2.0f;
- float scaledOuterPenWidth = UI.ScaleWidth(outerPenWidth);
- float scaledInnerPenWidth = UI.ScaleWidth(innerPenWidth);
- SmoothingMode oldSM = g.SmoothingMode;
- g.SmoothingMode = SmoothingMode.AntiAlias;
- int left = dirtyOverlayRect.Left + scaledXInset;
- int top = dirtyOverlayRect.Top + scaledXInset;
- int right = dirtyOverlayRect.Right - scaledXInset;
- int bottom = dirtyOverlayRect.Bottom - scaledXInset;
- float r = Math.Min((right - left) / 2.0f, (bottom - top) / 2.0f);
- PointF centerPt = new PointF((left + right) / 2.0f, (top + bottom) / 2.0f);
- float twoPiOver5 = (float)(Math.PI * 0.4);
- PointF a = new PointF(centerPt.X + r * (float)Math.Sin(twoPiOver5), centerPt.Y - r * (float)Math.Cos(twoPiOver5));
- PointF b = new PointF(centerPt.X + r * (float)Math.Sin(2 * twoPiOver5), centerPt.Y - r * (float)Math.Cos(2 * twoPiOver5));
- PointF c = new PointF(centerPt.X + r * (float)Math.Sin(3 * twoPiOver5), centerPt.Y - r * (float)Math.Cos(3 * twoPiOver5));
- PointF d = new PointF(centerPt.X + r * (float)Math.Sin(4 * twoPiOver5), centerPt.Y - r * (float)Math.Cos(4 * twoPiOver5));
- PointF e = new PointF(centerPt.X + r * (float)Math.Sin(5 * twoPiOver5), centerPt.Y - r * (float)Math.Cos(5 * twoPiOver5));
- PointF[] lines =
- new PointF[]
- {
- centerPt, a,
- centerPt, b,
- centerPt, c,
- centerPt, d,
- centerPt, e
- };
- using (Pen outerPen = new Pen(outerPenColor, scaledOuterPenWidth))
- {
- for (int i = 0; i < lines.Length; i += 2)
- {
- g.DrawLine(outerPen, lines[i], lines[i + 1]);
- }
- }
- using (Pen innerPen = new Pen(innerPenColor, scaledInnerPenWidth))
- {
- for (int i = 0; i < lines.Length; i += 2)
- {
- g.DrawLine(innerPen, lines[i], lines[i + 1]);
- }
- }
- g.SmoothingMode = oldSM;
- }
- private void DrawItem(Graphics g, Item item, Point offset)
- {
- Rectangle itemRect;
- //Rectangle checkButtonRect;
- Rectangle closeButtonRect;
- Rectangle dirtyOverlayRect;
- MeasureItemPartRectangles(
- item,
- out itemRect,
- out closeButtonRect,
- out dirtyOverlayRect);
- itemRect.X += offset.X;
- itemRect.Y += offset.Y;
- closeButtonRect.X += offset.X;
- closeButtonRect.Y += offset.Y;
- dirtyOverlayRect.X += offset.X;
- dirtyOverlayRect.Y += offset.Y;
- DrawItemBackground(g, item, itemRect);
- Rectangle highlightRect = itemRect;
- DrawItemHighlight(g, item, itemRect, highlightRect);
- if (this.showCloseButtons)
- {
- DrawItemCloseButton(g, item, itemRect, closeButtonRect);
- }
- if (this.drawDirtyOverlay && item.Dirty)
- {
- DrawItemDirtyOverlay(g, item, itemRect, dirtyOverlayRect);
- }
- }
- public Point ClientPointToViewPoint(Point clientPt)
- {
- int viewX = clientPt.X + this.scrollOffset;
- return new Point(viewX, clientPt.Y);
- }
- public Rectangle ClientRectangleToViewRectangle(Rectangle clientRect)
- {
- Point viewPt = ClientPointToViewPoint(clientRect.Location);
- return new Rectangle(viewPt, clientRect.Size);
- }
- public Point ViewPointToClientPoint(Point viewPt)
- {
- int clientX = viewPt.X - this.scrollOffset;
- return new Point(clientX, viewPt.Y);
- }
- public Rectangle ViewRectangleToClientRectangle(Rectangle viewRect)
- {
- Point clientPt = ViewPointToClientPoint(viewRect.Location);
- return new Rectangle(clientPt, viewRect.Size);
- }
- private Point ViewPointToItemPoint(int itemIndex, Point viewPt)
- {
- Rectangle itemRect = ItemIndexToItemViewRectangle(itemIndex);
- Point itemPt = new Point(viewPt.X - itemRect.X, viewPt.Y);
- return itemPt;
- }
- private Rectangle ItemIndexToItemViewRectangle(int itemIndex)
- {
- return items[itemIndex].Rectangle;
- //Size itemSize = ItemSize;
- //return new Rectangle(itemSize.Width * itemIndex, itemSize.Height, itemSize.Width, itemSize.Height);
- }
- public int ViewPointToItemIndex(Point viewPt)
- {
- if (!ViewRectangle.Contains(viewPt))
- {
- return -1;
- }
- int index = -1;// viewPt.X / itemSize.Width;
- int width = 0;
- //循环所有item,判断是第几个
- for (int i = 0; i < items.Count; i++)
- {
- if (viewPt.X >= items[i].Rectangle.X + width &&
- viewPt.X < items[i].Rectangle.X + width + items[i].Rectangle.Width)
- {
- index = i;
- break;
- }
- width += items[i].Rectangle.Width;
- }
- return index;
- }
- private void MeasureItemPartRectangles(
- out Rectangle itemRect,
- Item item)
- {
- //CheckBoxRenderer
- Size textSize = new Size(0, 0);
- if (item != null)
- textSize = /*CheckBoxRenderer*/TextRenderer.MeasureText(item.Name, new Font(SystemFonts.DefaultFont.Name, 10, FontStyle.Regular));
- itemRect = new Rectangle(
- 0,
- 0,
- textSize.Width == 0 ? 120 : textSize.Width + 33,//120,//ClientSize.Height
- ClientSize.Height);
- if (item != null)
- item.Rectangle = itemRect;
- }
- /// <summary>
- /// 计算位置,关闭按钮、修改标记
- /// </summary>
- /// <param name="item"></param>
- /// <param name="itemRect"></param>
- /// <param name="closeButtonRect"></param>
- /// <param name="dirtyOverlayRect"></param>
- private void MeasureItemPartRectangles(
- Item item,
- out Rectangle itemRect,
- out Rectangle closeButtonRect,
- out Rectangle dirtyOverlayRect)
- {
- MeasureItemPartRectangles(out itemRect, item);
- int scaledCloseButtonLength = UI.ScaleWidth(closeButtonLength);
- int scaledCloseButtonPadding = UI.ScaleWidth(closeButtonPadding);
- closeButtonRect = new Rectangle(
- itemRect.Width - scaledCloseButtonLength - scaledCloseButtonPadding,
- scaledCloseButtonPadding,
- scaledCloseButtonLength,
- scaledCloseButtonLength);
- dirtyOverlayRect = new Rectangle(
- scaledCloseButtonPadding,
- scaledCloseButtonPadding,
- scaledCloseButtonLength,
- scaledCloseButtonLength);
- }
- private ItemPart ItemPointToItemPart(Item item, Point pt)
- {
- Rectangle itemRect;
- Rectangle closeButtonRect;
- Rectangle dirtyOverlayRect;
- MeasureItemPartRectangles(
- item,
- out itemRect,
- out closeButtonRect,
- out dirtyOverlayRect);
- //判断是否是点击了关闭按钮
- int dhud = 0;
- int index = items.FindIndex(a => a == item);
- if (index > 0)
- {
- dhud = GetZeroToIndexWidth(index - 1);
- }
- closeButtonRect.X += dhud;
- if (closeButtonRect.Contains(pt))
- {
- return ItemPart.CloseButton;
- }
- int width = 0;
- bool isPart = false;
- //循环所有item,判断是第几个
- for (int i = 0; i < items.Count; i++)
- {
- if (pt.X >= items[i].Rectangle.X + width &&
- pt.X < items[i].Rectangle.X + width + items[i].Rectangle.Width)
- {
- isPart = true;
- break;
- }
- width += items[i].Rectangle.Width;
- }
- if (isPart)
- {
- return ItemPart.Image;
- }
- return ItemPart.None;
- }
- private int GetZeroToIndexWidth(int index)
- {
- int m = 0;
- for (int i = 0; i < items.Count; i++)
- {
- if (i <= index)
- m += items[i].Rectangle.Width;
- }
- return m;
- }
- private Rectangle ItemIndexToClientRect(int itemIndex)
- {
- Size itemSize = ItemSize;
- Rectangle clientRect = new Rectangle(
- GetZeroToIndexWidth(itemIndex),//itemSize.Width * itemIndex,
- 0,
- itemIndex < 0 ? itemSize.Width : items[itemIndex].Rectangle.Width,//itemSize.Width,
- itemSize.Height);
- return clientRect;
- }
- /// <summary>
- /// 计算偏移量
- /// </summary>
- /// <param name="itemIndex">下标</param>
- /// <param name="minOffset">最小偏移</param>
- /// <param name="maxOffset">最大偏移</param>
- /// <param name="minFullyShownOffset"></param>
- /// <param name="maxFullyShownOffset"></param>
- private void CalculateVisibleScrollOffsets(
- int itemIndex,
- out int minOffset,
- out int maxOffset,
- out int minFullyShownOffset,
- out int maxFullyShownOffset)
- {
- Rectangle itemClientRect = ItemIndexToClientRect(itemIndex);
- minOffset = itemClientRect.Left + 1 - ClientSize.Width;
- maxOffset = itemClientRect.Right - 1;
- minFullyShownOffset = itemClientRect.Right - ClientSize.Width;
- maxFullyShownOffset = itemClientRect.Left;
- if (this.leftScrollButton.Visible)
- {
- maxOffset -= this.leftScrollButton.Width;
- maxFullyShownOffset -= this.leftScrollButton.Width;
- }
- if (this.rightScrollButton.Visible)
- {
- minOffset += this.rightScrollButton.Width;
- minFullyShownOffset += this.rightScrollButton.Width;
- }
- }
- public Rectangle ScrolledViewRect
- {
- get
- {
- return new Rectangle(this.scrollOffset, 0, ClientSize.Width, ClientSize.Height);
- }
- }
- /// <summary>
- /// 判断item是否显示
- /// </summary>
- /// <param name="index"></param>
- /// <returns></returns>
- public bool IsItemVisible(int index)
- {
- Rectangle itemRect = ItemIndexToClientRect(index);
- Rectangle intersect = Rectangle.Intersect(itemRect, ScrolledViewRect);
- return (intersect.Width > 0 || intersect.Height > 0);
- }
- public bool IsItemFullyVisible(int index)
- {
- Rectangle itemRect = ItemIndexToClientRect(index);
- Rectangle svRect = ScrolledViewRect;
- if (this.leftScrollButton.Visible)
- {
- svRect.X += this.leftScrollButton.Width;
- svRect.Width -= this.leftScrollButton.Width;
- }
- if (this.rightScrollButton.Visible)
- {
- svRect.Width -= this.rightScrollButton.Width;
- }
- Rectangle intersect = Rectangle.Intersect(itemRect, svRect);
- return (intersect == itemRect);
- }
- public void EnsureItemFullyVisible(Item item)
- {
- int index = this.items.IndexOf(item);
- EnsureItemFullyVisible(index);
- }
- public void EnsureItemFullyVisible(int index)
- {
- if (IsItemFullyVisible(index))
- {
- return;
- }
- int minOffset;
- int maxOffset;
- int minFullyShownOffset;
- int maxFullyShownOffset;
- CalculateVisibleScrollOffsets(index, out minOffset, out maxOffset,
- out minFullyShownOffset, out maxFullyShownOffset);
- // Pick the offset that moves the image the fewest number of pixels
- int oldOffset = this.scrollOffset;
- int dxMin = Math.Abs(oldOffset - minFullyShownOffset);
- int dxMax = Math.Abs(oldOffset - maxFullyShownOffset);
- if (dxMin <= dxMax)
- {
- this.ScrollOffset = minFullyShownOffset;
- }
- else
- {
- this.ScrollOffset = maxFullyShownOffset;
- }
- }
- private void ForceMouseMove()
- {
- Point clientPt = PointToClient(Control.MousePosition);
- this.lastMouseMovePt = new Point(this.lastMouseMovePt.X + 1, this.lastMouseMovePt.Y + 1);
- MouseEventArgs me = new MouseEventArgs(MouseButtons.None, 0, clientPt.X, clientPt.Y, 0);
- OnMouseMove(me);
- }
- private void GetFocus()
- {
- if (this.managedFocus && !MenuStripEx.IsAnyMenuActive && UI.IsOurAppActive)
- {
- this.Focus();
- }
- }
- #region 绘制、鼠标进入、离开、按下、移动、抬起、滚轮事件
- protected override void OnPaint(PaintEventArgs e)
- {
- if (UI.IsControlPaintingEnabled(this))
- {
- if (this.items != null && this.items.Count > 0)
- {
- Size itemSize = ItemSize;
- Rectangle firstItemRect = new Rectangle(-this.scrollOffset, 0, items[0].Rectangle.Width, itemSize.Height);
- for (int i = 0; i < this.items.Count; ++i)
- {
- //if (IsItemVisible(i)) //暂时注释掉,在观察
- {
- Point itemOffset = new Point(firstItemRect.X + GetZeroToIndexWidth(i - 1), firstItemRect.Y);
- //Point itemOffset = new Point(firstItemRect.X + itemSize.Width * i, firstItemRect.Y);
- DrawItem(e.Graphics, this.items[i], itemOffset);
- }
- }
- }
- }
- base.OnPaint(e);
- }
- protected override void OnMouseDown(MouseEventArgs e)
- {
- if (this.mouseDownButton == MouseButtons.None)
- {
- Point clientPt = new Point(e.X, e.Y);
- Point viewPt = ClientPointToViewPoint(clientPt);
- int itemIndex = ViewPointToItemIndex(viewPt);
- if (itemIndex >= 0 && itemIndex < this.items.Count)
- {
- Item item = this.items[itemIndex];
- Point itemPt = ViewPointToItemPoint(itemIndex, viewPt);
- ItemPart itemPart = ItemPointToItemPart(item, itemPt);
- if (itemPart == ItemPart.Image)
- {
- OnItemClicked(item, itemPart, e.Button);
- this.mouseDownApplyRendering = false;
- this.mouseOverIndex = itemIndex;
- this.mouseOverItemPart = itemPart;
- this.mouseOverApplyRendering = true;
- }
- else
- {
- this.mouseDownIndex = itemIndex;
- this.mouseDownItemPart = itemPart;
- this.mouseDownButton = e.Button;
- this.mouseDownApplyRendering = true;
- this.mouseOverApplyRendering = false;
- }
- MouseStatesToItemStates();
- Refresh();
- }
- }
- base.OnMouseDown(e);
- }
- protected override void OnMouseMove(MouseEventArgs e)
- {
- GetFocus();
- Point clientPt = new Point(e.X, e.Y);
- if (clientPt != this.lastMouseMovePt)
- {
- Point viewPt = ClientPointToViewPoint(clientPt);
- int itemIndex = ViewPointToItemIndex(viewPt);
- if (this.mouseDownButton == MouseButtons.None)
- {
- if (itemIndex >= 0 && itemIndex < this.items.Count)
- {
- Item item = this.items[itemIndex];
- Point itemPt = ViewPointToItemPoint(itemIndex, viewPt);
- ItemPart itemPart = ItemPointToItemPart(item, itemPt);
- this.mouseOverIndex = itemIndex;
- this.mouseOverItemPart = itemPart;
- this.mouseOverApplyRendering = true;
- }
- else
- {
- this.mouseOverApplyRendering = false;
- }
- }
- else
- {
- this.mouseOverApplyRendering = false;
- if (itemIndex != this.mouseDownIndex)
- {
- this.mouseDownApplyRendering = false;
- }
- else if (itemIndex < 0 || itemIndex >= this.items.Count)
- {
- this.mouseDownApplyRendering = false;
- }
- else
- {
- Item item = this.Items[itemIndex];
- Point itemPt = ViewPointToItemPoint(itemIndex, viewPt);
- ItemPart itemPart = ItemPointToItemPart(item, itemPt);
- if (itemPart != this.mouseDownItemPart)
- {
- this.mouseDownApplyRendering = false;
- }
- }
- }
- MouseStatesToItemStates();
- Refresh();
- }
- this.lastMouseMovePt = clientPt;
- base.OnMouseMove(e);
- }
- protected override void OnMouseUp(MouseEventArgs e)
- {
- bool raisedClickEvent = false;
- if (this.mouseDownButton == e.Button)
- {
- Point clientPt = new Point(e.X, e.Y);
- Point viewPt = ClientPointToViewPoint(clientPt);
- int itemIndex = ViewPointToItemIndex(viewPt);
- if (itemIndex >= 0 && itemIndex < this.items.Count)
- {
- Item item = this.items[itemIndex];
- Point itemPt = ViewPointToItemPoint(itemIndex, viewPt);
- ItemPart itemPart = ItemPointToItemPart(item, itemPt);
- if (itemIndex == this.mouseDownIndex && itemPart == this.mouseDownItemPart)
- {
- if (itemPart == ItemPart.CloseButton && !item.Checked)
- {
- // Can only close 'checked' images, just like how tab switching+closing works in IE7
- itemPart = ItemPart.Image;
- }
- OnItemClicked(item, itemPart, this.mouseDownButton);
- raisedClickEvent = true;
- }
- this.mouseOverApplyRendering = true;
- this.mouseOverItemPart = itemPart;
- this.mouseOverIndex = itemIndex;
- }
- this.mouseDownApplyRendering = false;
- this.mouseDownButton = MouseButtons.None;
- MouseStatesToItemStates();
- Refresh();
- }
- if (raisedClickEvent)
- {
- ForceMouseMove();
- }
- base.OnMouseUp(e);
- }
- protected override void OnMouseWheel(MouseEventArgs e)
- {
- float count = (float)e.Delta / SystemInformation.MouseWheelScrollDelta;
- int pixels = GetAllItemWidth();//(int)(count * ItemSize.Width);
- int newSO = ScrollOffset - pixels;
- ScrollOffset = newSO;
- ForceMouseMove();
- base.OnMouseWheel(e);
- }
- protected override void OnMouseEnter(EventArgs e)
- {
- GetFocus();
- base.OnMouseEnter(e);
- }
- protected override void OnMouseLeave(EventArgs e)
- {
- this.mouseDownApplyRendering = false;
- this.mouseOverApplyRendering = false;
- MouseStatesToItemStates();
- Refresh();
- if (this.managedFocus && !MenuStripEx.IsAnyMenuActive && UI.IsOurAppActive)
- {
- OnRelinquishFocus();
- }
- base.OnMouseLeave(e);
- }
- #endregion
- }
- }
|