/// <summary> /// 绘制列表子项 /// </summary> /// <param name="g">绘图表面</param> /// <param name="subItem">要绘制的子项</param> /// <param name="rectSubItem">该子项的区域</param> /// <param name="sb">画刷</param> protected virtual void DrawSubItem(Graphics g, ChatListSubItem subItem, ref Rectangle rectSubItem, SolidBrush sb) { if (subItem.Equals(selectSubItem)) { //判断改子项是否被选中 rectSubItem.Height = (int)ChatListItemIcon.Large; //如果选中则绘制成大图标 sb.Color = this.subItemSelectColor; g.FillRectangle(sb, rectSubItem); DrawHeadImage(g, subItem, rectSubItem); //绘制头像 DrawLargeSubItem(g, subItem, rectSubItem); //绘制大图标 显示的个人信息 subItem.Bounds = new Rectangle(rectSubItem.Location, rectSubItem.Size); return; } else if (subItem.Equals(m_mouseOnSubItem)) { sb.Color = this.subItemMouseOnColor; } else { sb.Color = this.subItemColor; } g.FillRectangle(sb, rectSubItem); DrawHeadImage(g, subItem, rectSubItem); if (iconSizeMode == ChatListItemIcon.Large) //没有选中则根据 图标模式绘制 { DrawLargeSubItem(g, subItem, rectSubItem); } else { DrawSmallSubItem(g, subItem, rectSubItem); } subItem.Bounds = new Rectangle(rectSubItem.Location, rectSubItem.Size); }
/// <summary> /// 移除一个子项 /// </summary> /// <param name="subItem">要移除的子项</param> public void Remove(ChatListSubItem subItem) { int index = this.IndexOf(subItem); if (-1 != index) { this.RemoveAt(index); } }
//实现排序接口 int IComparable.CompareTo(object obj) { if (!(obj is ChatListSubItem)) { throw new NotImplementedException("obj is not ChatListSubItem"); } ChatListSubItem subItem = obj as ChatListSubItem; return((this.status).CompareTo(subItem.status)); }
private void ClearSubItemMouseOn() { if (m_mouseOnSubItem != null) { this.Invalidate(new Rectangle( m_mouseOnSubItem.Bounds.X, m_mouseOnSubItem.Bounds.Y - chatVScroll.Value, m_mouseOnSubItem.Bounds.Width, m_mouseOnSubItem.Bounds.Height)); m_mouseOnSubItem = null; } }
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { if (destinationType == null) { throw new ArgumentNullException("DestinationType cannot be null"); } //MessageBox.Show("Convertto OK"); if (destinationType == typeof(InstanceDescriptor) && (value is ChatListItem)) { ConstructorInfo constructor = null; ChatListItem item = (ChatListItem)value; ChatListSubItem[] subItems = null; //MessageBox.Show("Convertto Start Item:" + item.Text); //MessageBox.Show("Item.SubItems.Count:" + item.SubItems.Count); if (item.SubItems.Count > 0) { subItems = new ChatListSubItem[item.SubItems.Count]; item.SubItems.CopyTo(subItems, 0); } //MessageBox.Show("Item.SubItems.Count:" + item.SubItems.Count); if (item.Text != null && subItems != null) { constructor = typeof(ChatListItem).GetConstructor(new Type[] { typeof(string), typeof(ChatListSubItem[]) }); } //MessageBox.Show("Constructor(Text,item[]):" + (constructor != null)); if (constructor != null) { return(new InstanceDescriptor(constructor, new object[] { item.Text, subItems }, false)); } if (subItems != null) { constructor = typeof(ChatListItem).GetConstructor(new Type[] { typeof(ChatListSubItem[]) }); } if (constructor != null) { return(new InstanceDescriptor(constructor, new object[] { subItems }, false)); } if (item.Text != null) { //MessageBox.Show("StartGetConstructor(text)"); constructor = typeof(ChatListItem).GetConstructor(new Type[] { typeof(string), typeof(bool) }); } //MessageBox.Show("Constructor(Text):" + (constructor != null)); if (constructor != null) { //System.Windows.Forms.MessageBox.Show("text OK"); return(new InstanceDescriptor(constructor, new object[] { item.Text, item.IsOpen })); } } return(base.ConvertTo(context, culture, value, destinationType)); }
/// <summary> /// 绘制列表子项的头像 /// </summary> /// <param name="g">绘图表面</param> /// <param name="subItem">要绘制头像的子项</param> /// <param name="rectSubItem">该子项的区域</param> protected virtual void DrawHeadImage(Graphics g, ChatListSubItem subItem, Rectangle rectSubItem) { if (subItem.IsTwinkle) { //判断改头像是否闪动 if (subItem.IsTwinkleHide) //同理该值 在线程中 取反赋值 { return; } } int imageHeight = rectSubItem.Height - 10; //根据子项的大小计算头像的区域 subItem.HeadRect = new Rectangle(5, rectSubItem.Top + 5, imageHeight, imageHeight); if (subItem.HeadImage == null) //如果头像位空 用默认资源给定的头像 { subItem.HeadImage = global::CWebQQ.Properties.Resources._null; } if (subItem.Status == ChatListSubItem.UserStatus.OffLine) { g.DrawImage(subItem.GetDarkImage(), subItem.HeadRect); } else { g.DrawImage(subItem.HeadImage, subItem.HeadRect); //如果在线根据在想状态绘制小图标 if (subItem.Status == ChatListSubItem.UserStatus.QMe) { g.DrawImage(global::CWebQQ.Properties.Resources.QMe, new Rectangle(subItem.HeadRect.Right - 10, subItem.HeadRect.Bottom - 10, 11, 11)); } if (subItem.Status == ChatListSubItem.UserStatus.Away) { g.DrawImage(global::CWebQQ.Properties.Resources.Away, new Rectangle(subItem.HeadRect.Right - 10, subItem.HeadRect.Bottom - 10, 11, 11)); } if (subItem.Status == ChatListSubItem.UserStatus.Busy) { g.DrawImage(global::CWebQQ.Properties.Resources.Busy, new Rectangle(subItem.HeadRect.Right - 10, subItem.HeadRect.Bottom - 10, 11, 11)); } if (subItem.Status == ChatListSubItem.UserStatus.DontDisturb) { g.DrawImage(global::CWebQQ.Properties.Resources.Dont_Disturb, new Rectangle(subItem.HeadRect.Right - 10, subItem.HeadRect.Bottom - 10, 11, 11)); } } if (subItem.Equals(selectSubItem)) //根据是否选中头像绘制头像的外边框 { g.DrawRectangle(Pens.Cyan, subItem.HeadRect); } else { g.DrawRectangle(Pens.Gray, subItem.HeadRect); } }
//确认存储空间 private void EnsureSpace(int elements) { if (m_arrSubItems == null) { m_arrSubItems = new ChatListSubItem[Math.Max(elements, 4)]; } else if (elements + this.count > m_arrSubItems.Length) { ChatListSubItem[] arrTemp = new ChatListSubItem[Math.Max(m_arrSubItems.Length * 2, elements + this.count)]; m_arrSubItems.CopyTo(arrTemp, 0); m_arrSubItems = arrTemp; } }
/// <summary> /// 根据在线状态添加一个子项 /// </summary> /// <param name="subItem">要添加的子项</param> public void AddAccordingToStatus(ChatListSubItem subItem) { if (subItem.Status == ChatListSubItem.UserStatus.OffLine) { this.Add(subItem); return; } for (int i = 0, len = this.count; i < len; i++) { if (subItem.Status <= m_arrSubItems[i].Status) { this.Insert(i, subItem); return; } } this.Add(subItem); }
/// <summary> /// 添加一个子项 /// </summary> /// <param name="subItem">要添加的子项</param> public void Add(ChatListSubItem subItem) { if (subItem == null) { throw new ArgumentNullException("SubItem cannot be null"); } this.EnsureSpace(1); if (-1 == IndexOf(subItem)) { subItem.OwnerListItem = owner; m_arrSubItems[this.count++] = subItem; if (this.owner.OwnerChatListBox != null) { this.owner.OwnerChatListBox.Invalidate(); } } }
/// <summary> /// 绘制大图标模式的个人信息 /// </summary> /// <param name="g">绘图表面</param> /// <param name="subItem">要绘制信息的子项</param> /// <param name="rectSubItem">该子项的区域</param> protected virtual void DrawLargeSubItem(Graphics g, ChatListSubItem subItem, Rectangle rectSubItem) { rectSubItem.Height = (int)ChatListItemIcon.Large; //重新赋值一个高度 string strDraw = subItem.DisplayName; Size szFont = TextRenderer.MeasureText(strDraw, this.Font); if (szFont.Width > 0) { //判断是否有备注名称 g.DrawString(strDraw, this.Font, Brushes.Black, rectSubItem.Height, rectSubItem.Top + 5); g.DrawString("(" + subItem.NicName + ")", this.Font, Brushes.Gray, rectSubItem.Height + szFont.Width, rectSubItem.Top + 5); } else { //如果没有备注名称 这直接绘制昵称 g.DrawString(subItem.NicName, this.Font, Brushes.Black, rectSubItem.Height, rectSubItem.Top + 5); } //绘制个人签名 g.DrawString(subItem.PersonalMsg, this.Font, Brushes.Gray, rectSubItem.Height, rectSubItem.Top + 5 + this.Font.Height); }
/// <summary> /// 绘制小图标模式的个人信息 /// </summary> /// <param name="g">绘图表面</param> /// <param name="subItem">要绘制信息的子项</param> /// <param name="rectSubItem">该子项的区域</param> protected virtual void DrawSmallSubItem(Graphics g, ChatListSubItem subItem, Rectangle rectSubItem) { rectSubItem.Height = (int)ChatListItemIcon.Small; //重新赋值一个高度 StringFormat sf = new StringFormat(); sf.LineAlignment = StringAlignment.Center; sf.FormatFlags = StringFormatFlags.NoWrap; string strDraw = subItem.DisplayName; if (string.IsNullOrEmpty(strDraw)) { strDraw = subItem.NicName; //如果没有备注绘制昵称 } Size szFont = TextRenderer.MeasureText(strDraw, this.Font); sf.SetTabStops(0.0F, new float[] { rectSubItem.Height }); g.DrawString("\t" + strDraw, this.Font, Brushes.Black, rectSubItem, sf); sf.SetTabStops(0.0F, new float[] { rectSubItem.Height + 5 + szFont.Width }); g.DrawString("\t" + subItem.PersonalMsg, this.Font, Brushes.Gray, rectSubItem, sf); }
/// <summary> /// 根据索引插入一个子项 /// </summary> /// <param name="index">索引位置</param> /// <param name="subItem">要插入的子项</param> public void Insert(int index, ChatListSubItem subItem) { if (index < 0 || index >= this.count) { throw new IndexOutOfRangeException("Index was outside the bounds of the array"); } if (subItem == null) { throw new ArgumentNullException("SubItem cannot be null"); } this.EnsureSpace(1); for (int i = this.count; i > index; i--) { m_arrSubItems[i] = m_arrSubItems[i - 1]; } subItem.OwnerListItem = this.owner; m_arrSubItems[index] = subItem; this.count++; if (this.owner.OwnerChatListBox != null) { this.owner.OwnerChatListBox.Invalidate(); } }
public ChatListEventArgs(ChatListSubItem mouseonsubitem, ChatListSubItem selectsubitem) { this.mouseOnSubItem = mouseonsubitem; this.selectSubItem = selectsubitem; }
/// <summary> /// 判断子项是否在集合内 /// </summary> /// <param name="subItem">要判断的子项</param> /// <returns>是否在集合内</returns> public bool Contains(ChatListSubItem subItem) { return(this.IndexOf(subItem) != -1); }
protected override void OnMouseMove(MouseEventArgs e) { m_ptMousePos = e.Location; if (chatVScroll.IsMouseDown) { //如果滚动条的滑块处于被点击 那么移动 chatVScroll.MoveSliderFromLocation(e.Y); return; } if (chatVScroll.ShouldBeDraw) { //如果控件上有滚动条 判断鼠标是否在滚动条区域移动 if (chatVScroll.Bounds.Contains(m_ptMousePos)) { ClearItemMouseOn(); ClearSubItemMouseOn(); if (chatVScroll.SliderBounds.Contains(m_ptMousePos)) { chatVScroll.IsMouseOnSlider = true; } else { chatVScroll.IsMouseOnSlider = false; } if (chatVScroll.UpBounds.Contains(m_ptMousePos)) { chatVScroll.IsMouseOnUp = true; } else { chatVScroll.IsMouseOnUp = false; } if (chatVScroll.DownBounds.Contains(m_ptMousePos)) { chatVScroll.IsMouseOnDown = true; } else { chatVScroll.IsMouseOnDown = false; } return; } else { chatVScroll.ClearAllMouseOn(); } } m_ptMousePos.Y += chatVScroll.Value; //如果不在滚动条范围类 那么根据滚动条当前值计算虚拟的一个坐标 for (int i = 0, Len = items.Count; i < Len; i++) { //然后判断鼠标是否移动到某一列表项或者子项 if (items[i].Bounds.Contains(m_ptMousePos)) { if (items[i].IsOpen) { //如果展开 判断鼠标是否在某一子项上面 for (int j = 0, lenSubItem = items[i].SubItems.Count; j < lenSubItem; j++) { if (items[i].SubItems[j].Bounds.Contains(m_ptMousePos)) { if (m_mouseOnSubItem != null) { //如果当前鼠标下子项不为空 if (items[i].SubItems[j].HeadRect.Contains(m_ptMousePos)) { //判断鼠标是否在头像内 if (!m_bOnMouseEnterHeaded) { //如果没有触发进入事件 那么触发用户绑定的事件 OnMouseEnterHead(new ChatListEventArgs(this.m_mouseOnSubItem, this.selectSubItem)); m_bOnMouseEnterHeaded = true; } } else { if (m_bOnMouseEnterHeaded) { //如果已经执行过进入事件 那触发用户绑定的离开事件 OnMouseLeaveHead(new ChatListEventArgs(this.m_mouseOnSubItem, this.selectSubItem)); m_bOnMouseEnterHeaded = false; } } } if (items[i].SubItems[j].Equals(m_mouseOnSubItem)) { return; } ClearSubItemMouseOn(); ClearItemMouseOn(); m_mouseOnSubItem = items[i].SubItems[j]; this.Invalidate(new Rectangle( m_mouseOnSubItem.Bounds.X, m_mouseOnSubItem.Bounds.Y - chatVScroll.Value, m_mouseOnSubItem.Bounds.Width, m_mouseOnSubItem.Bounds.Height)); //this.Invalidate(); return; } } ClearSubItemMouseOn(); //循环做完没发现子项 那么判断是否在列表上面 if (new Rectangle(0, items[i].Bounds.Top - chatVScroll.Value, this.Width, 20).Contains(e.Location)) { if (items[i].Equals(m_mouseOnItem)) { return; } ClearItemMouseOn(); m_mouseOnItem = items[i]; this.Invalidate(new Rectangle( m_mouseOnItem.Bounds.X, m_mouseOnItem.Bounds.Y - chatVScroll.Value, m_mouseOnItem.Bounds.Width, m_mouseOnItem.Bounds.Height)); //this.Invalidate(); return; } } else { //如果列表项没有展开 重绘列表项 if (items[i].Equals(m_mouseOnItem)) { return; } ClearItemMouseOn(); ClearSubItemMouseOn(); m_mouseOnItem = items[i]; this.Invalidate(new Rectangle( m_mouseOnItem.Bounds.X, m_mouseOnItem.Bounds.Y - chatVScroll.Value, m_mouseOnItem.Bounds.Width, m_mouseOnItem.Bounds.Height)); //this.Invalidate(); return; } } }//若循环结束 既不在列表上也不再子项上 清空上面的颜色 ClearItemMouseOn(); ClearSubItemMouseOn(); base.OnMouseMove(e); }
/// <summary> /// 获取索引位置 /// </summary> /// <param name="subItem">要获取索引的子项</param> /// <returns>索引</returns> public int IndexOf(ChatListSubItem subItem) { return(Array.IndexOf <ChatListSubItem>(m_arrSubItems, subItem)); }
protected override void OnClick(EventArgs e) { if (chatVScroll.IsMouseDown) { return; //MouseUp事件触发在Click后 滚动条滑块为点下状态 单击无效 } if (chatVScroll.ShouldBeDraw) { //如果有滚动条 判断是否在滚动条类点击 if (chatVScroll.Bounds.Contains(m_ptMousePos)) { //判断在滚动条那个位置点击 if (chatVScroll.UpBounds.Contains(m_ptMousePos)) { chatVScroll.Value -= 50; } else if (chatVScroll.DownBounds.Contains(m_ptMousePos)) { chatVScroll.Value += 50; } else if (!chatVScroll.SliderBounds.Contains(m_ptMousePos)) { chatVScroll.MoveSliderToLocation(m_ptMousePos.Y); } return; } }//否则 如果在列表上点击 展开或者关闭 在子项上面点击则选中 foreach (ChatListItem item in items) { if (item.Bounds.Contains(m_ptMousePos)) { if (item.IsOpen) { foreach (ChatListSubItem subItem in item.SubItems) { if (subItem.Bounds.Contains(m_ptMousePos)) { if (!subItem.Equals(selectSubItem)) { selectSubItem = subItem; this.Invalidate(); } if (_MouseClickButton == System.Windows.Forms.MouseButtons.Right) { OnContextSubItem(new ChatListEventArgs(m_mouseOnSubItem, subItem)); //Debug.WriteLine("子项被选中"); } return; } } if (new Rectangle(0, item.Bounds.Top, this.Width, 20).Contains(m_ptMousePos)) { selectSubItem = null; item.IsOpen = !item.IsOpen; this.Invalidate(); return; } } else { selectSubItem = null; item.IsOpen = !item.IsOpen; this.Invalidate(); return; } } } base.OnClick(e); }