コード例 #1
0
 internal void AddMessageItem(MessageListItem item, bool forceDisplayedBottom)
 {
     messageListBox.Items.Add(item);
     if (forceDisplayedBottom)
     {
         messageListBox.ScrollToBottom();
     }
 }
コード例 #2
0
        private void toolStripMenuItemMessage_Click(object sender, EventArgs e)
        {
            MessageListItem item = messageListBox.GetItemAtPosition(messageListBox.PointToClient(MousePosition)) as MessageListItem;

            if (item == null)
            {
                return;
            }

            Message m = item.Message;

            if (sender == toolStripMenuItemCopy)
            {
                if (m.Type == MessageType.Text)
                {
                    string selection = item.SelectedText;
                    if (!string.IsNullOrEmpty(selection))
                    {
                        Clipboard.SetText(selection);
                    }
                    else
                    {
                        Clipboard.SetText(m.Content);
                    }
                }
                else if (m.Type == MessageType.Image)
                {
                    Clipboard.SetImage((m as ImageMessage).Image);
                }
                else if (m.Type == MessageType.File)
                {
                    string filePath = (m as FileMessage).OriginFilePath;
                    if (File.Exists(filePath))
                    {
                        StringCollection sc = new StringCollection();
                        sc.Add(filePath);
                        Clipboard.SetFileDropList(sc);
                    }
                }
            }
            else if (sender == toolStripMenuItemOpenFolder)
            {
                if (m.Type == MessageType.Image)
                {
                }
                else if (m.Type == MessageType.File)
                {
                    string filePath = (m as FileMessage).OriginFilePath;
                    if (File.Exists(filePath))
                    {
                    }
                }
            }
            else if (sender == toolStripMenuItemSaveAs)
            {
            }
        }
コード例 #3
0
        protected override void OnItemClicked(ItemClickedEventArgs args)
        {
            if (args.Button == MouseButtons.Left)
            {
                MessageListItem item = args.Item as MessageListItem;
                Message         m    = item.Message;
                Rectangle       rect = item.Bounds;

                foreach (DrawingObject dobj in item.DrawingObjects)
                {
                    RectangleF drawingObjRect = dobj.Offset(rect.X, rect.Y);

                    switch (dobj.Type)
                    {
                    //头像
                    case DrawingObjectType.ProfilePhoto:
                        if (drawingObjRect.Contains(args.Location))
                        {
                            UserProfileControl control = new UserProfileControl();
                            control.User = item.User;
                            control.Show(this.PointToScreen(args.Location));
                            return;
                        }
                        break;

                    case DrawingObjectType.Image:
                    case DrawingObjectType.File:
                    {
                        if (drawingObjRect.Contains(args.Location))
                        {
                            //点击了图像,显示大图, 或者打开文件
                            string path;
                            if (m.Type == MessageType.Image)
                            {
                                path = (m as ImageMessage).OriginPath;
                            }
                            else
                            {
                                path = (m as FileMessage).OriginFilePath;
                            }
                            if (LanFile.Exists(path))
                            {
                                Process.Start(path);
                            }
                        }
                        break;
                    }
                    }
                }
            }
            else if (args.Button == MouseButtons.Right)
            {
                //交给显示右键菜单
            }
        }
コード例 #4
0
 internal void Invalidate(MessageListItem item)
 {
     if (item == null)
     {
         this.Invalidate();
     }
     else
     {
         this.Invalidate(item.Bounds);
     }
 }
コード例 #5
0
        internal MessageListItem GetMessageItem(long id)
        {
            //因为后后加的,倒过来循环速度更快应该
            for (int i = messageListBox.Items.Count - 1; i > -1; i--)
            {
                MessageListItem item = messageListBox.Items[i] as MessageListItem;

                if (item.ID == id)
                {
                    return(item);
                }
            }

            return(null);
        }
コード例 #6
0
ファイル: UserListItem.cs プロジェクト: prape/LanIM
        internal MessageListItem GetWaitDisplayMessageItem(long id)
        {
            //因为后后加的,倒过来循环速度更快应该
            for (int i = WaitDisplayMessages.Count - 1; i > -1; i--)
            {
                MessageListItem item = WaitDisplayMessages[i];

                if (item.ID == id)
                {
                    return(item);
                }
            }

            return(null);
        }
コード例 #7
0
        private void contextMenuStripMessage_Opening(object sender, CancelEventArgs e)
        {
            MessageListItem item = messageListBox.GetItemAtPosition(messageListBox.PointToClient(MousePosition)) as MessageListItem;

            if (item == null)
            {
                e.Cancel = true;
                return;
            }

            contextMenuStripMessage.Items.Clear();
            contextMenuStripMessage.Items.Add(toolStripMenuItemCopy);
            if (item.Message.Type != MessageType.Text)
            {
                contextMenuStripMessage.Items.Add(new ToolStripSeparator());
                contextMenuStripMessage.Items.Add(toolStripMenuItemOpenFolder);
                contextMenuStripMessage.Items.Add(toolStripMenuItemSaveAs);
            }
        }
コード例 #8
0
        public void Clear()
        {
            if (_selectingTextItem != null)
            {
                foreach (DrawingObject dobj in _selectingTextItem.DrawingObjects)
                {
                    if (dobj.Type == DrawingObjectType.TextBlock)
                    {
                        TextBlockObj tb = dobj.Tag as TextBlockObj;
                        tb.ClearSelection();
                    }
                }
            }

            _selectingTextItem  = null;
            _selectStartDoIndex = -1;
            _selectEndDoIndex   = -1;
            _prevSelection.Clear();
        }
コード例 #9
0
        public void AddReceivedTextMessage(LanUser from, long id, string message)
        {
            Store.Models.Message m = new Store.Models.Message(MessageType.Text);
            m.FromUserId = from.ID;
            m.ToUserId   = this.OwnerUser.ID;
            m.Content    = message;
            m.Flag       = true; //默认成功,后面按照失败结果设定为false

            MessageListItem item = new MessageListItem();

            item.State   = MessageState.Received;
            item.ID      = id;
            item.Message = m;
            item.User    = from;

            item.Save();

            AddMessageListItem(from, item);
        }
コード例 #10
0
        private void SendImage_Click(object sender, EventArgs e)
        {
            if (!this.SendMessageEnabled)
            {
                return;
            }
            using (OpenFileDialog ofd = new OpenFileDialog())
            {
                ofd.Filter = "图像文件|*.png;*.jpg;*.bmp;";
                if (ofd.ShowDialog(this) == DialogResult.OK)
                {
                    string fileName = ofd.FileName;
                    Image  smallImg = LanImage.GetThumbnailImage(fileName, MessageListBox.PICTURE_THUMBNAIL_HEIGHT);
                    if (smallImg == null)
                    {
                        //可能不是合法的图片
                        return;
                    }

                    long id = User.SendImage(Contacter, fileName);

                    //保存发送记录,只保存缩略图,原图的Path也保存
                    Store.Models.ImageMessage m = new Store.Models.ImageMessage(smallImg);
                    m.FromUserId = this.User.ID;
                    m.ToUserId   = this.Contacter.ID;
                    m.OriginPath = fileName;
                    m.Flag       = true; //默认成功,后面按照失败结果设定为false

                    MessageListItem item = new MessageListItem();
                    item.ID      = id;
                    item.State   = MessageState.Sending;
                    item.Message = m;
                    item.User    = this.User;

                    item.Save();

                    AddMessageItem(item, true);

                    OnSendMessage(m);
                }
            }
        }
コード例 #11
0
        public void AddReceivedImageMessage(LanUser from, long id, Image image)
        {
            //保存记录
            Store.Models.ImageMessage m = new Store.Models.ImageMessage(image);
            m.FromUserId = from.ID;
            m.ToUserId   = this.OwnerUser.ID;
            m.OriginPath = "";
            m.Flag       = true; //默认成功,后面按照失败结果设定为false

            MessageListItem item = new MessageListItem();

            item.ID      = id;
            item.State   = MessageState.Received;
            item.Message = m;
            item.User    = from;

            item.Save();

            AddMessageListItem(from, item);
        }
コード例 #12
0
        public void SetMessageResult(string fromUserId, string toUserId, long id, bool success)
        {
            string userItemId = fromUserId;

            if (fromUserId == this.OwnerUser.ID)
            {
                //如果是我自己,那么则是发送消息
                if (success)
                {
                    //发送时就按照默认成功的,发送成功的消息可以忽略了
                    return;
                }
                userItemId = toUserId;
            }

            UserListItem    userItem = this[userItemId];
            UserChatControl chatCtrl = userItem.ChatControl;

            MessageListItem item = null;

            if (chatCtrl == null)
            {
                //如果还没表示则取出来
                item = userItem.GetWaitDisplayMessageItem(id);
            }
            else
            {
                item = chatCtrl.GetMessageItem(id);
            }

            Store.Models.Message m = item.Message;
            m.Flag = success;
            item.Update();

            if (chatCtrl != null && userItemId == this.SelectedUser.ID)
            {
                //当前表示着,更新
                chatCtrl.Invalidate();
            }
        }
コード例 #13
0
        internal void SetSelectionStartItem(Point p)
        {
            //清除其他的选择状态
            this.Clear();

            MessageListItem item = _owner.GetItemAtPosition(p) as MessageListItem;

            if (item == null)
            {
                return;
            }

            //设定文本选中
            if (item.Message.Type == MessageType.Text)
            {
                this._selectingTextItem = item;
                Rectangle rect = item.Bounds;

                for (int i = 0; i < this._selectingTextItem.DrawingObjects.Count; i++)
                {
                    DrawingObject dobj = item.DrawingObjects[i];
                    if (dobj.Type == DrawingObjectType.TextBlock)
                    {
                        Rectangle bounds = dobj.Offset(rect.X, rect.Y);

                        if (bounds.Contains(p))
                        {
                            TextBlockObj tb = dobj.Tag as TextBlockObj;
                            StringPart   sp = tb.StringPart;
                            using (Graphics g = _owner.CreateGraphics())
                            {
                                tb.SelectionStart        = StringMeasurer.GetCharIndex(g, sp.Font, p.X - (int)dobj.X, sp.String);
                                this._selectStartDoIndex = i;
                                break;
                            }
                        }
                    }
                }
            }
        }
コード例 #14
0
        private void AddMessageListItem(LanUser from, MessageListItem item)
        {
            UserListItem userItem = this[from.ID];

            bool bRefresh = false;

            if (this.SelectedUser == null || from.ID != this.SelectedUser.ID)
            {
                //不是当前用户则增加未读数
                userItem.UnreadMessageCount++;
                bRefresh = true;
            }

            //移动到第一个
            if (this.Items[0] != userItem)
            {
                this.Items.Remove(userItem);
                this.Items.Insert(0, userItem);
                bRefresh = true;
            }

            if (bRefresh)
            {
                this.Invalidate(userItem.Bounds);
            }

            UserChatControl chatCtrl = userItem.ChatControl;

            if (chatCtrl == null)
            {
                //如果还没表示则先缓存一下
                userItem.WaitDisplayMessages.Add(item);
            }
            else
            {
                chatCtrl.AddMessageItem(item, userItem.UserID == from.ID);
            }
        }
コード例 #15
0
        private void textBoxInput_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter && !e.Control)
            {
                if (!this.SendMessageEnabled)
                {
                    return;
                }
                if (string.IsNullOrEmpty(textBoxInput.Text) ||
                    string.IsNullOrEmpty(textBoxInput.Text.Replace("\r", "").Replace("\n", "")))
                {
                    //空或者只有空行不发送
                    return;
                }
                long id = User.SendTextMessage(Contacter, textBoxInput.Text);

                Store.Models.Message m = new Store.Models.Message(MessageType.Text);
                m.FromUserId = this.User.ID;
                m.ToUserId   = this.Contacter.ID;
                m.Content    = textBoxInput.Text;
                m.Flag       = true; //默认成功,后面按照失败结果设定为false

                MessageListItem item = new MessageListItem();
                item.State   = MessageState.Sending;
                item.ID      = id;
                item.Message = m;
                item.User    = this.User;

                item.Save();

                AddMessageItem(item, true);

                textBoxInput.Text = "";
                e.Handled         = true;

                OnSendMessage(m);
            }
        }
コード例 #16
0
        public void AddFileReceivingMessage(LanUser from, TransportFile file)
        {
            //保存记录
            Store.Models.FileMessage m = new Store.Models.FileMessage();
            m.FromUserId     = from.ID;
            m.ToUserId       = this.OwnerUser.ID;
            m.OriginFilePath = file.SavePath;
            m.FileName       = Path.GetFileName(file.SavePath);
            m.FileLength     = file.File.Length;
            m.Flag           = true; //默认成功,后面按照失败结果设定为false

            MessageListItem item = new MessageListItem();

            item.ID      = file.ID;
            item.Message = m;
            item.User    = from;
            item.State   = MessageState.Receiving;

            //保存到数据库
            item.Save();

            AddMessageListItem(from, item);
        }
コード例 #17
0
        protected override void OnItemHover(ItemHoverEventArgs args)
        {
            MessageListItem item = args.Item as MessageListItem;
            Rectangle       rect = item.Bounds;

            foreach (DrawingObject dobj in item.DrawingObjects)
            {
                RectangleF drawingObjRect = dobj.Offset(rect.X, rect.Y);
                switch (dobj.Type)
                {
                case DrawingObjectType.ProfilePhoto:
                case DrawingObjectType.Image:
                case DrawingObjectType.File:
                {
                    //头像 鼠标变化
                    if (drawingObjRect.Contains(args.Location))
                    {
                        this.Cursor = Cursors.Hand;
                        return;
                    }
                    break;
                }

                case DrawingObjectType.TextBlock:
                {
                    if (drawingObjRect.Contains(args.Location))
                    {
                        this.Cursor = Cursors.IBeam;
                        return;
                    }
                    break;
                }
                }
            }

            this.Cursor = Cursors.Default;
        }
コード例 #18
0
        public void SetFileTransportProgress(TransportFile file)
        {
            UserListItem    userItem = this[file.MAC];
            UserChatControl chatCtrl = userItem.ChatControl;

            MessageListItem item = null;

            if (chatCtrl == null)
            {
                //如果还没表示则取出来
                item = userItem.GetWaitDisplayMessageItem(file.ID);
            }
            else
            {
                item = chatCtrl.GetMessageItem(file.ID);
            }

            item.FileTransportedLength = file.TransportedLength;
            item.FileTransportedSpeed  = file.TransportedSpeed;
            item.Progress = file.Progress;

            if (file.Progress == 100)
            {
                //传输完毕
                Store.Models.Message m = item.Message;
                m.Flag = true;
                item.Update();

                item.State = MessageState.Received;
            }

            if (chatCtrl != null && file.MAC == this.SelectedUser.MAC)
            {
                //当前表示着,更新
                chatCtrl.RefreshMessageList(item);
            }
        }
コード例 #19
0
        private void SendFile_Click(object sender, EventArgs e)
        {
            if (!this.SendMessageEnabled)
            {
                return;
            }
            using (OpenFileDialog ofd = new OpenFileDialog())
            {
                ofd.Filter = "所有文件|*.*";
                if (ofd.ShowDialog(this) == DialogResult.OK)
                {
                    string fileName = ofd.FileName;
                    long   id       = User.SendFile(Contacter, fileName);

                    //保存发送记录
                    Store.Models.FileMessage m = new Store.Models.FileMessage();
                    m.FromUserId     = this.User.ID;
                    m.ToUserId       = this.Contacter.ID;
                    m.OriginFilePath = fileName;
                    m.FileName       = Path.GetFileName(fileName);
                    m.FileLength     = LanFile.GetFileLength(fileName);
                    m.Flag           = true; //默认成功,后面按照失败结果设定为false

                    MessageListItem item = new MessageListItem();
                    item.ID      = id;
                    item.Message = m;
                    item.User    = this.User;
                    item.State   = MessageState.Sending;

                    item.Save();

                    AddMessageItem(item, true);

                    OnSendMessage(m);
                }
            }
        }
コード例 #20
0
        internal void InitializeLatastMessage(List <MessageListItem> cacheWaitDisplayMessages)
        {
            long            id   = -1;
            MessageListItem item = null;

            if (messageListBox.Items.Count != 0)
            {
                item = messageListBox.Items[0] as MessageListItem;
                id   = item.Message.ID;
            }

            MessageHistoryMapper messageHistoryMapper = new MessageHistoryMapper();
            List <Message>       list = messageHistoryMapper.QueryUserLatestMessages(this.Contacter.ID, id);

            List <MessageListItem> items = new List <MessageListItem>();

            foreach (Message m in list)
            {
                //优先追加缓存中的数据
                int index = -1;
                if (cacheWaitDisplayMessages != null)
                {
                    index = cacheWaitDisplayMessages.FindIndex((i) =>
                    {
                        if (i.Message.ID == m.ID)
                        {
                            return(true);
                        }
                        return(false);
                    }
                                                               );
                }

                if (index == -1)
                {
                    item         = new MessageListItem();
                    item.Message = m;
                    if (m.Flag)
                    {
                        if (m.FromUserId == User.ID)
                        {
                            item.State = MessageState.SendSuccess;
                        }
                        else
                        {
                            item.State = MessageState.Received;
                        }
                    }
                    else
                    {
                        if (m.FromUserId == User.ID)
                        {
                            item.State = MessageState.SendError;
                        }
                        else
                        {
                            item.State = MessageState.ReceiveError;
                        }
                    }
                    item.User = m.FromUserId == User.ID ? User : Contacter;
                }
                else
                {
                    item = cacheWaitDisplayMessages[index];
                    cacheWaitDisplayMessages.RemoveAt(index);
                }
                items.Add(item);
            }

            if (cacheWaitDisplayMessages != null)
            {
                items.AddRange(cacheWaitDisplayMessages);
            }

            messageListBox.Items.InsertRange(0, items);

            if (items.Count != 0)
            {
                //向上滚动取有记录的话,选中添加的最后1个
                messageListBox.ScrollToBottom();
            }
        }
コード例 #21
0
        protected override void OnMeasureItem(UI.MeasureItemEventArgs args)
        {
            base.OnMeasureItem(args);

            MessageListItem item = args.Item as MessageListItem;
            Message         m    = item.Message;

            Graphics g = args.Graphics;

            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

            int x = MARGIN;
            int y = MARGIN;

            item.DrawingObjects.Clear();

            //头像
            DrawingObject dobj = new DrawingObject(DrawingObjectType.ProfilePhoto, new Rectangle(x, y, ICON_WIDTH, ICON_WIDTH));

            item.DrawingObjects.Add(dobj);

            //时间, 昵称,状态
            x   += ICON_WIDTH + MARGIN;
            dobj = new DrawingObject(DrawingObjectType.Title, new Rectangle(x, y, this.ClientSize.Width - x, args.Font.Height));
            item.DrawingObjects.Add(dobj);

            y = MARGIN + args.Font.Height + MARGIN;
            int height = y;
            int width  = 0;

            if (m.Type == MessageType.Text)
            {
                width = item.Width - ICON_WIDTH - 3 * MARGIN;
                //height = (int)g.MeasureString(m.Content, args.Font, width).Height;

                List <StringPart> spList = StringMeasurer.Measure(g, args.Font, width, m.Content);
                foreach (StringPart sp in spList)
                {
                    Rectangle textRect = sp.Bounds;
                    textRect.X += x;
                    textRect.Y += y;
                    dobj        = new DrawingObject(DrawingObjectType.TextBlock, textRect);
                    dobj.Tag    = new TextBlockObj(sp);
                    item.DrawingObjects.Add(dobj);

                    height += sp.Bounds.Height;
                }
            }
            else if (m.Type == MessageType.Image)
            {
                Image image = (m as ImageMessage).Image;
                //对于一些过小的图片最小32,此时图片会画歪掉,算了就这样
                width = Math.Max(32, (int)(1.0 * image.Width * PICTURE_THUMBNAIL_HEIGHT / image.Height));
                width = Math.Min(width, this.ClientSize.Width - 64);//当然也不要超过当前宽度

                dobj = new DrawingObject(DrawingObjectType.Image, new Rectangle(x, y, width, PICTURE_THUMBNAIL_HEIGHT));
                item.DrawingObjects.Add(dobj);

                height += PICTURE_THUMBNAIL_HEIGHT;
            }
            else if (m.Type == MessageType.File)
            {
                width = FILE_SEND_WIDTH;

                dobj = new DrawingObject(DrawingObjectType.File, new Rectangle(x, y, width, FILE_SEND_HEIGHT));
                item.DrawingObjects.Add(dobj);

                height += FILE_SEND_HEIGHT;
            }

            item.Height = Math.Max(ICON_WIDTH + MARGIN, height) + MARGIN;
        }
コード例 #22
0
        internal void SetSelectionEndItem(Point location)
        {
            if (!this.HasSelection)
            {
                return;
            }

            MessageListItem hoverItem = _owner.GetItemAtPosition(location) as MessageListItem;

            if (hoverItem == null)
            {
                //鼠标移动到其他地方了,算了,不选了
                this.Clear();
                return;
            }

            if (hoverItem != this._selectingTextItem)
            {
                //当前的选择的不是上面一个
                this.Clear();
                return;
            }

            Rectangle rect = this._selectingTextItem.Bounds;

            for (int i = 0; i < this._selectingTextItem.DrawingObjects.Count; i++)
            {
                DrawingObject dobj = this._selectingTextItem.DrawingObjects[i];

                if (dobj.Type == DrawingObjectType.TextBlock)
                {
                    Rectangle    bounds = dobj.Offset(rect.X, rect.Y);
                    TextBlockObj tb     = dobj.Tag as TextBlockObj;

                    if (bounds.Contains(location))
                    {
                        StringPart sp = tb.StringPart;
                        using (Graphics g = _owner.CreateGraphics())
                        {
                            tb.SelectionEnd        = StringMeasurer.GetCharIndex(g, sp.Font, location.X - (int)dobj.X, sp.String);
                            this._selectEndDoIndex = i;
                            break;
                        }
                    }
                }
            }

            //开始与结束直接的所有TextBlock都设定为全选中
            int startIndex = Math.Min(this._selectStartDoIndex, this._selectEndDoIndex);
            int endIndex   = Math.Max(this._selectStartDoIndex, this._selectEndDoIndex);

            List <TextBlockObj> selObj = new List <TextBlockObj>();

            for (int i = startIndex; i <= endIndex; i++)
            {
                DrawingObject dobj = this._selectingTextItem.DrawingObjects[i];
                if (dobj.Type == DrawingObjectType.TextBlock)
                {
                    TextBlockObj tbObj = dobj.Tag as TextBlockObj;

                    if (this._selectStartDoIndex < this._selectEndDoIndex)
                    {
                        //从上往下选择时
                        if (i == this._selectStartDoIndex)
                        {
                            tbObj.SelectionEnd = tbObj.Length - 1;
                        }
                        else if (i == this._selectEndDoIndex)
                        {
                            tbObj.SelectionStart = 0;
                        }
                    }
                    else if (this._selectStartDoIndex > this._selectEndDoIndex)
                    {
                        //从下往上选择时
                        if (i == this._selectStartDoIndex)
                        {
                            tbObj.SelectionEnd = 0;
                        }
                        else if (i == this._selectEndDoIndex)
                        {
                            tbObj.SelectionStart = tbObj.Length - 1;
                        }
                    }
                    if (i != this._selectStartDoIndex && i != this._selectEndDoIndex)
                    {
                        tbObj.SelectAll();
                    }

                    selObj.Add(tbObj);
                    this._prevSelection.Remove(tbObj);
                }
            }

            //清除选择
            foreach (TextBlockObj item in this._prevSelection)
            {
                item.ClearSelection();
            }
            this._prevSelection = selObj;
        }
コード例 #23
0
 internal void RefreshMessageList(MessageListItem item)
 {
     this.messageListBox.Invalidate(item);
 }
コード例 #24
0
        protected override void OnDrawItem(UI.DrawItemEventArgs args)
        {
            MessageListItem item = args.Item as MessageListItem;
            Message         m    = item.Message;

            args.DrawBackground();

            Graphics g = args.Graphics;

            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

            Rectangle rect = item.Bounds;

            Rectangle drawingObjRect;
            Point     pos = PointToClient(MousePosition);

            foreach (DrawingObject dobj in item.DrawingObjects)
            {
                drawingObjRect = dobj.Offset(rect.X, rect.Y);

                switch (dobj.Type)
                {
                //头像
                case DrawingObjectType.ProfilePhoto:
                {
                    g.DrawImage(ProfilePhotoPool.GetPhoto(item.User.ID), drawingObjRect);

                    if (drawingObjRect.Contains(pos))
                    {
                        g.DrawRectangle(IMAGE_BORDER_PEN_FOCUS, drawingObjRect.X, drawingObjRect.Y, drawingObjRect.Width, drawingObjRect.Height);
                    }
                    break;
                }

                //时间, 昵称,状态
                case DrawingObjectType.Title:
                {
                    string text = item.User.NickName + "  " + m.Time.ToString("yyyy/MM/dd HH:mm:ss");
                    if (!m.Flag)
                    {
                        text += "  传送失败";
                    }
                    TextRenderer.DrawText(g, text,
                                          args.Font, new Point((int)drawingObjRect.X, (int)drawingObjRect.Y)
                                          , m.Flag ? SUCCESS_TITLE_COLOR : ERROR_TITLE_COLOR, TextFormatFlags.Left);
                    break;
                }

                //文本消息
                case DrawingObjectType.TextBlock:
                {
                    TextBlockObj tb       = dobj.Tag as TextBlockObj;
                    StringPart   sp       = tb.StringPart;
                    int          selStart = Math.Min(tb.SelectionStart, tb.SelectionEnd);
                    int          selEnd   = Math.Max(tb.SelectionStart, tb.SelectionEnd);

                    string str1 = selStart == -1 ? sp.String : sp.String.Substring(0, selStart);
                    string str2 = selStart == -1 ? "" : sp.String.Substring(selStart, tb.SelectionLength);
                    string str3 = selEnd == -1 ? "" : sp.String.Substring(selEnd + 1);

                    //选择前的文本
                    if (!string.IsNullOrEmpty(str1))
                    {
                        TextRenderer.DrawText(g, str1, sp.Font, new Point((int)drawingObjRect.X, (int)drawingObjRect.Y), args.ForeColor,
                                              StringMeasurer.TextFormatFlags);
                    }

                    //选择中文本
                    if (!string.IsNullOrEmpty(str2))
                    {
                        int w1 = StringMeasurer.Width(g, sp.Font, str1, sp.TextFormatFlags);
                        int w2 = StringMeasurer.Width(g, sp.Font, str2, sp.TextFormatFlags);
                        drawingObjRect.X    += w1;
                        drawingObjRect.Width = w2;

                        g.FillRectangle(BrushPool.GetBrush(TEXT_SELECTION_BACK_COLOR), drawingObjRect);
                        TextRenderer.DrawText(g, str2, sp.Font, new Point((int)drawingObjRect.X, (int)drawingObjRect.Y),
                                              TEXT_SELECTION_FORE_COLOR, StringMeasurer.TextFormatFlags);

                        //选择后的文本
                        if (!string.IsNullOrEmpty(str3))
                        {
                            drawingObjRect.X    += w2;
                            drawingObjRect.Width = dobj.Width - w1 - w2;
                            TextRenderer.DrawText(g, str3, sp.Font, new Point((int)drawingObjRect.X, (int)drawingObjRect.Y), args.ForeColor,
                                                  StringMeasurer.TextFormatFlags);
                        }
                    }
                    break;
                }

                case DrawingObjectType.Image:
                {
                    Image image = (m as ImageMessage).Image;
                    g.DrawImage(image, drawingObjRect);

                    if (drawingObjRect.Contains(pos))
                    {
                        g.DrawRectangle(IMAGE_BORDER_PEN_FOCUS, drawingObjRect.X, drawingObjRect.Y, drawingObjRect.Width, drawingObjRect.Height);
                    }
                    else
                    {
                        g.DrawRectangle(IMAGE_BORDER_PEN, drawingObjRect.X, drawingObjRect.Y, drawingObjRect.Width, drawingObjRect.Height);
                    }
                    break;
                }

                case DrawingObjectType.File:
                {
                    FileMessage fm = m as FileMessage;

                    //底背景
                    g.FillRectangle(Brushes.White, drawingObjRect);
                    if (drawingObjRect.Contains(pos))
                    {
                        g.DrawRectangle(IMAGE_BORDER_PEN_FOCUS, drawingObjRect.X, drawingObjRect.Y, drawingObjRect.Width, drawingObjRect.Height);
                    }
                    else
                    {
                        g.DrawRectangle(IMAGE_BORDER_PEN, drawingObjRect.X, drawingObjRect.Y, drawingObjRect.Width, drawingObjRect.Height);
                    }

                    //文件名,文件大小,ICON
                    Image image       = FileIconPool.GetIcon(fm.OriginFilePath);
                    int   imageWidth  = 64;
                    int   imageHeight = 64 * image.Height / image.Width;

                    Rectangle imageRect    = new Rectangle(drawingObjRect.X + FILE_SEND_WIDTH - imageWidth - MARGIN, drawingObjRect.Y + MARGIN, imageWidth, FILE_SEND_HEIGHT - Font.Height - MARGIN * 3);
                    Rectangle fileNameRect = new Rectangle(drawingObjRect.X + MARGIN, drawingObjRect.Y + MARGIN, FILE_SEND_WIDTH - imageWidth - MARGIN * 3, FILE_SEND_HEIGHT - Font.Height - MARGIN * 3);
                    Rectangle fontRect     = new Rectangle(drawingObjRect.X + MARGIN, drawingObjRect.Y + FILE_SEND_HEIGHT - Font.Height - MARGIN, FILE_SEND_WIDTH - MARGIN * 2, Font.Height);
                    Rectangle pieRect      = new Rectangle(drawingObjRect.X + (FILE_SEND_WIDTH - PROGRESS_PIE_D) / 2, drawingObjRect.Y + (FILE_SEND_HEIGHT - PROGRESS_PIE_D) / 2, PROGRESS_PIE_D, PROGRESS_PIE_D);
                    Rectangle processRect  = new Rectangle(drawingObjRect.X, drawingObjRect.Y + (FILE_SEND_HEIGHT - Font.Height * 2) / 2, FILE_SEND_WIDTH, Font.Height * 2);

                    //当文件名超过显示部分时,中间用省略号表示
                    string str = fm.FileName;
                    SizeF  s   = g.MeasureString(fm.FileName, Font, new System.Drawing.SizeF((float)fileNameRect.Width, (float)fileNameRect.Height), StringFormat.GenericDefault, out int count, out int lines);
                    if (s.Height >= fileNameRect.Height & str.Length >= count)
                    {
                        //由于会出现半行的情况,直接写死了所取的字符串数目
                        str = str.Substring(0, 36) + "・・・" + str.Substring(str.Length - 4);
                    }
                    g.DrawImage(image, imageRect.X, imageRect.Y, imageWidth, imageHeight);
                    g.DrawString(str, args.Font, Brushes.Black, fileNameRect);
                    TextRenderer.DrawText(g, LanFile.HumanReadbleLen(fm.FileLength), args.Font, fontRect, Color.FromArgb(0, 0, 0), TextFormatFlags.Left);

                    if (item.State == MessageState.Receiving ||
                        item.State == MessageState.Sending)
                    {
                        //接受进度
                        g.FillRectangle(MESSAGELIST_PROGRESS_BACKGROUND_BRUSH, drawingObjRect);

                        g.DrawPie(PROGRESS_PEN, pieRect, 0, 360);
                        g.FillPie(MESSAGELIST_PROGRESS_FILLED_BRUSH, pieRect, 0, 360 * item.Progress / 100);

                        //TODO 显示剩余时间,传输速度
                        TextRenderer.DrawText(g, item.Progress + "%" + "\r\n" + LanFile.HumanReadbleLen(item.FileTransportedLength) + "/" + LanFile.HumanReadbleLen(fm.FileLength),
                                              args.Font, processRect, Color.FromArgb(0, 0, 0), TextFormatFlags.HorizontalCenter);
                    }
                    break;
                }
                }
            }
        }