public static void DrawChat(Graphics g, Dialog chat, Font fnt, ControlState state, int y = 0, int width = 200) { Color bg = Color.FromArgb(164, Color.White); if (state == ControlState.Hover) { bg = Color.FromArgb(182, Color.White); } else if (state == ControlState.Pressed) { bg = Color.FromArgb(196, Color.White); } g.FillRectangle(new SolidBrush(bg), 0, y, width, 50); if (chat == null) { return; } Message msg = chat.Message; if (msg == null) { return; } User usr = msg.User; if (usr != null) { Bitmap p = msg.GetPhoto(); if (p == null) { p = usr.GetPhoto(); } if (p != null) { g.DrawImage(p, new Rectangle(1, y + 1, 48, 48)); } } DrawString(g, chat.Title, fnt, Brushes.Black, new Rectangle(55, y, width - 55, 50), StringAlignment.Near); if (state == ControlState.Active) { g.FillPolygon(new SolidBrush(Color.FromArgb(78, Color.White)), new [] { new Point(width, y), new Point(width, y + 50), new Point(width - 25, y + 25) }); } }
public void SendMessage(String text, bool encrypt = false) { if (this._chat == null) { return; } new Thread(async() => { while (this._sending) { Thread.Sleep(10); } String chat = "user_id=" + this._chat.Message.UserID; if (this._chat.Message.ChatID > 0) { chat = "chat_id=" + this._chat.Message.ChatID; } if (!String.IsNullOrEmpty(text)) { this._sending = true; this.InvokeEx(t => t.Invalidate()); if (encrypt) { if (String.IsNullOrEmpty(this._chat.CryptKey)) { this.InvokeEx(t => { DecryptMessagesForm frm = new DecryptMessagesForm(); if (frm.ShowDialog(t.FindForm()) == DialogResult.OK) { t._chat.CryptKey = frm.Passphrase; } }); } if (!String.IsNullOrEmpty(this._chat.CryptKey)) { text = Message.Encrypt(text, this._chat.CryptKey); } } await Message.Send(chat, text); this._sending = false; this.InvokeEx(t => t.Invalidate()); } }).Start(); }
public ChatControl() : base() { AppEvents.On(AppEventType.OpenChat, OpenChat); LongPollServer.On(LPEventType.MessageAdded, async e => { if (this._chat == null) { return; } int msgID = (int)((long)((JValue)e.Data[0]).Value); Message msg = await Message.Get(msgID); if (msg.UserID == this._chat.Message.UserID || (msg.ChatID != 0 && msg.ChatID == this._chat.Message.ChatID)) { (new Thread(() => { if (msg.Attachments != null && msg.Attachments.Length > 0) { foreach (Attachment a in msg.Attachments) { if (a.Type == "photo" && a.Photo != null) { a.Photo.Load(); } } } if (msg.CryptedNow && this._chat.CryptKey != null) { msg.Decrypt(this._chat.CryptKey); } msg.Author.GetPhoto(); this._messages.Add(msg); this._loaded = true; this._heightCalculated = false; this.InvokeEx(t => { t.Invalidate(); }); })).Start(); } }); }
private void LoadChats() { (new Thread(async() => { if (API.API.Session == null) { return; } this.chats = await Dialog.GetDialogs(); this.loaded = true; List <int> ids = new List <int>(); foreach (Dialog chat in this.chats) { Message msg = chat.Message; if (!ids.Contains(msg.UserID)) { ids.Add(msg.UserID); } } User[] users = await User.GetAll(ids); foreach (User u in users) { u.GetPhoto(); } this.InvokeEx(t => { if (t != null && t.chats != null) { t.ContentHeight = t.chats.Count * 50; t.Invalidate(); } }); })).Start(); }
public static int DrawMessage(Graphics g, Message msg, Message prevMsg, Font fnt, ControlState state, int y = 0, int width = 500, int cHeight = 400, MouseState mouse = default(MouseState)) { if (msg == null) { return(y); } int height = 0; const int padding = 10; const int avatarSz = 48; int hWidth = width - avatarSz - 3 * padding; int msgWidth = width / 100 * 80; User usr = msg.Author; if (usr == null) { return(y); } Size hSize = Size.Empty; if (prevMsg == null || prevMsg.Author != usr) { int aX = padding; if (msg.Out) { aX = width - padding - avatarSz; } Bitmap p = usr.GetPhoto(); if (p != null && y > -avatarSz) { g.DrawImage(p, new Rectangle(aX, y, avatarSz, avatarSz)); } hSize = Size.Ceiling(g.MeasureString(usr.FullName, fnt, hWidth)); int hX = 2 * padding + avatarSz; if (msg.Out) { hX = width - 2 * padding - avatarSz - hSize.Width; } if (y > -hSize.Height) { DrawString(g, usr.FullName, fnt, Brushes.DimGray, new Rectangle(new Point(hX, y), hSize)); } } height += padding / 2 + hSize.Height; Size msgSize = Size.Ceiling(g.MeasureString(msg.Body, fnt, msgWidth)); Size msgRectSize = Size.Add(msgSize, new Size(2 * padding, 2 * padding)); int rX = 2 * padding + avatarSz + 5; if (msg.Out) { rX = width - 2 * padding - avatarSz - msgRectSize.Width - 5; } int rY = y + padding / 2 + hSize.Height; if (msg.Attachments != null && msg.Attachments.Length > 0) { int ax = 0, ay = 0; int mw = 0, mh = 0; foreach (Attachment a in msg.Attachments) { Size asz = a.Measure(g, fnt, msgWidth - ax, true); if (mh < asz.Height) { mh = asz.Height; } if (ax + asz.Width > msgWidth) { ax = 0; ay += mh + padding; mh = 0; } else { ax += asz.Width + padding; } if (mw < ax) { mw = ax; } } msgRectSize = new Size(Math.Max(msgSize.Width, mw) + padding, msgSize.Height + ay + mh + 2 * padding); rX = 2 * padding + avatarSz + 5; if (msg.Out) { rX = width - 2 * padding - avatarSz - msgRectSize.Width - 5; } rY = y + padding / 2 + hSize.Height; } Color msgRectColor = Color.White; if (msg.Crypted) { msgRectColor = Color.Lime; } if (!msg.Read) { msgRectColor = Color.DodgerBlue; if (msg.Crypted) { msgRectColor = Color.LimeGreen; } } Brush msgRectBrush = new SolidBrush(Color.FromArgb(128, msgRectColor)); if (rY > -msgRectSize.Height && rY < cHeight) { g.FillRoundRectangle(msgRectBrush, new Rectangle(new Point(rX, rY), msgRectSize), padding / 2); } int tX = rX; int tY = rY + padding; if (msg.Out) { tX = rX + msgRectSize.Width; } g.FillPolygon(msgRectBrush, new[] { new Point(tX, tY), new Point(tX, tY + 16), new Point(((msg.Out) ? tX + 10 : tX - 10), tY + 8) }); if (y + padding + padding / 2 + hSize.Height > -msgSize.Height && y < cHeight) { Rectangle msgRectangle = new Rectangle(new Point(rX + padding, y + padding + padding / 2 + hSize.Height), msgSize); /*if (msg.Body.Length > 256) * { * DrawString(g, msg.Body, fnt, Brushes.Black, msgRectangle, StringAlignment.Near); * } * else * {*/ List <TextBlock> blocks; if (msg.RuntimeData.ContainsKey("TextBlocks")) { blocks = (List <TextBlock>)msg.RuntimeData["TextBlocks"]; } else { blocks = new List <TextBlock>(); int blkend = 0; MatchCollection matches = _URL.Matches(msg.Body); if (matches.Count > 0) { foreach (Match m in matches) { String url = m.ToString(); int idx = msg.Body.IndexOf(url, StringComparison.Ordinal); if (idx > blkend) { blocks.Add(new TextBlock(msg.Body, blkend, idx - blkend)); } TextBlock blk = new TextBlock(msg.Body, idx, url.Length, TextStyle.Link); blocks.Add(blk); blkend = blk.End; } } if (msg.Body.Length > blkend) { blocks.Add(new TextBlock(msg.Body, blkend, msg.Body.Length - blkend)); } if (Emoji.FindEmojis(msg.Body).Count > 0) { List <TextBlock> nbl = new List <TextBlock>(); foreach (TextBlock b in blocks) { foreach (String em in Emoji.FindEmojis(b.Fragment)) { int idx = b.Fragment.IndexOf(em, StringComparison.Ordinal); if (idx > 0) { nbl.Add(new TextBlock(msg.Body, b.Start, idx, b.Style, b.State)); } nbl.Add(new EmojiBlock(msg.Body, b.Start + idx, em.Length, b.State)); if (idx + em.Length < b.Length) { nbl.Add(new TextBlock(msg.Body, b.Start + idx + em.Length, b.Length - idx - em.Length, b.Style, b.State)); } } } blocks = nbl; } Console.WriteLine(((msg.Body.Length > 32) ? msg.Body.Substring(0, 32) + "..." : msg.Body) + ": " + blocks.Count + " block(s)"); blocks.Sort((blk, blk2) => blk.Start.CompareTo(blk2.Start)); msg.RuntimeData.Add("TextBlocks", blocks); } if (blocks.Count > 16) { DrawString(g, msg.Body, fnt, Brushes.Black, msgRectangle, StringAlignment.Near); } else { int sX = rX + padding, sY = y + padding + padding / 2 + hSize.Height, eX = msgSize.Width, eY = msgSize.Height; int cX = 0, cY = 0, cH = 0; CharacterRange[] ranges = { new CharacterRange(0, 1) }; String _c; Rectangle charRect = Rectangle.Empty; int cP = 0; using (StringFormat stringFormat = new StringFormat()) { stringFormat.Alignment = StringAlignment.Near; stringFormat.LineAlignment = StringAlignment.Center; foreach (TextBlock blk in blocks) { blk.StartPoint = new Point(cX, cY); if (blk is EmojiBlock) { Bitmap e = ((EmojiBlock)blk).Emoji; if (e != null) { g.DrawImage(e, new Rectangle(new Point(sX + cX + 2, sY + cY), new Size(16, 16))); if (cH < 16) { cH = 16; } cX += 20; if (cX > eX) { cX = 0; cY += cH; } } cP += blk.Length; } else { while (cP >= blk.Start && cP < blk.End) { ranges[0].First = cP; stringFormat.SetMeasurableCharacterRanges(ranges); _c = msg.Body.Substring(cP, 1); charRect = Rectangle.Round( g.MeasureCharacterRanges(msg.Body, fnt, msgRectangle, stringFormat)[0] .GetBounds(g)); if (cH < charRect.Height) { cH = charRect.Height; } Color c = Color.Black; if (blk.Style == TextStyle.Link) { c = Color.Blue; if (mouse != null) { int mpX = mouse.Position.X; int mpY = mouse.Position.Y; if (mpY >= sY + blk.StartPoint.Y && mpY <= sY + blk.EndPoint.Y && mpX >= sX + blk.StartPoint.X && mpX <= sX + blk.EndPoint.X) { blk.State = ControlState.Hover; if (mouse.Clicked) { blk.State = ControlState.Pressed; mouse.Clicked = false; } } else { blk.State = ControlState.Idle; } if (blk.State != ControlState.Idle) { if (blk.State == ControlState.Hover) { c = Color.DarkOrange; } if (blk.State == ControlState.Pressed) { c = Color.Red; App.Platform.OpenUrl(msg.Body.Substring(blk.Start, blk.Length)); } g.FillRectangle(Brushes.White, charRect); } } else { blk.State = ControlState.Idle; c = Color.Blue; } } g.DrawString(_c, fnt, new SolidBrush(c), sX + cX, sY + cY); if (blk.Style == TextStyle.Link) { g.DrawLine(new Pen(c), sX + cX + 2, sY + cY + cH, sX + cX + charRect.Width + 2, sY + cY + cH); } cX += charRect.Width; if (cX > eX || _c == "\n") { cX = 0; cY += cH; if (_c != "\n") { cH = 0; } } cP++; } } blk.EndPoint = new Point(cX + charRect.Width + 2, cY + cH); } } } } height += msgRectSize.Height + padding; if (msg.Attachments != null && msg.Attachments.Length > 0) { int ax = 0, ay = 0; int mh = 0; foreach (Attachment a in msg.Attachments) { Size asz = a.Measure(g, fnt, msgWidth - ax, true); Rectangle aRect = new Rectangle(new Point(rX + padding + ax, rY + msgSize.Height + padding + ay), asz); bool aHover = false, aClick = false; if (mouse != null && aRect.Contains(mouse.Position)) { aHover = true; if (mouse.Clicked) { aClick = true; mouse.Clicked = false; } } a.Draw(g, aRect, fnt, true, aHover, aClick); if (mh < asz.Height) { mh = asz.Height; } if (ax + asz.Width > msgWidth) { ax = 0; ay += mh + padding; mh = 0; } else { ax += asz.Width + padding; } } } return(height); }
protected override void OnPaint(PaintEventArgs e) { this.OnPaintBackground(e); Graphics g = e.Graphics; g.SmoothingMode = SmoothingMode.HighQuality; g.FillRectangle(new SolidBrush(Color.FromArgb(196, Color.White)), this.ClientRectangle); if (!this._loaded || this._messages == null || this._messages.Count == 0) { Drawer.DrawString(g, "No messages", this.Font, Brushes.Black, this.ClientRectangle); } else { String bgi = this._chat.Message.Photo; if (String.IsNullOrEmpty(bgi)) { bgi = this._chat.Message.User.Photo; } if (!String.IsNullOrEmpty(bgi)) { Bitmap bg = Drawer.SetImageOpacity(bgi, 0.05f); if (bg != null) { int sz = Math.Max(this.Width, this.Height); g.DrawImage(bg, (this.Width - sz) / 2, (this.Height - sz) / 2, sz, sz); } } int y = -this.ScrollOffset + 10; Message prevMsg = null; lock (_messages_lock) { try { foreach (Message msg in this._messages) { y += Drawer.DrawMessage(g, msg, prevMsg, this.Font, ControlState.Idle, y, this.Width, this.Height, this.Mouse); prevMsg = msg; } } catch (Exception exception) { Console.WriteLine(exception); } } if (!this._heightCalculated) { this.ContentHeight = y + this.ScrollOffset; this.ScrollOffset = this.ContentHeight - this._oldH + this._so - ((this._oldH == 0) ? this.Height : 0); this._heightCalculated = true; } } this.Mouse.Clicked = false; base.OnPaint(e); }