• Vui lòng đọc nội qui diễn đàn để tránh bị xóa bài viết
  • Tìm kiếm trước khi đặt câu hỏi

Nhờ kiểm tra lỗi chữ bị nhòe khi cuộn trong Control tự tạo

Nơi trao đổi về các vấn đề trong lập trình Windows Forms, Console dùng cú pháp ngôn ngữ Visual Basic .NET và C#

Điều hành viên: tungblt, vuathongtin

khoaph
Thành viên chính thức
Thành viên chính thức
Bài viết: 34
Ngày tham gia: T.Ba 08/12/2015 12:57 pm
Been thanked: 4 time

Nhờ kiểm tra lỗi chữ bị nhòe khi cuộn trong Control tự tạo

Gửi bàigửi bởi khoaph » CN 06/03/2016 3:48 pm

Mình mới tạo 1 control, công dụng của nó là hiển thị 1 đoạn text, nếu text không hiển thị hết trong cửa sổ sẽ xuất hiện thanh cuộn, có thể kéo lên kéo xuống. Lỗi chữ bị nhòe xảy ra khi có thanh cuộn, nhưng chỉ thỉnh thoảng mới xảy ra, nhờ các bạn tìm hiểu nguyên nhân của lỗi giúp mình
Đây là code của Form1.cs, chỉ cần copy dán là chạy được
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Text;
  7. using System.Windows.Forms;
  8.  
  9. namespace Test_cuon_noi_dung
  10. {
  11.     public partial class Form1 : Form
  12.     {
  13.         public Form1()
  14.         {
  15.             InitializeComponent();
  16.             TextView textview = new TextView("Rồi cậu leo lên xe đãp đi đến Thiên Đường buôn bán đồ cổ.Máy chỉnh hình mà Bob? phải đeo ở chân, từ khi cậu bị gãy chân trong một lấn thử leo núi, gần như không làm phiền cậu khi đạp xe, nên cậu nhanh chóng rời khỏi trung tâm thành phố và không trục trặc gì đến mục đích? chuyến đi của mình.Chính Hannibal đặt ra cái tên Thiên đường buôn bán Đồ cổ. Trước kia chỗ đó tên là Hiệu đồ cũ. Chính tại nơi này, ông Jones, chú của Hannibal bán đủ loại đồ vật hỗn tạp. Việc thay đổi tên cửa hàng đã rất có lợi cho ông : bây giờ, ở mấy chục cây số quanh vùng, người ta đến Thiên đường buôn bán đồ cổ để làm áp phe.Bob vượt qua cổng chính- một cổng sắt vĩ đại mua ở nhà biệt thự lân cận – và chỉ dừng lại? xa hơn ba trăm mét, ngay trước góc, nơi tranh tường có vẽ một? cảnh biến giận dữ và chiếc buồm sắp chìm đắm. Bob nhảy xuống đất trước hai tấm ván nơi Hannibal đã tự làm cho mình một cửa vào bí mật đặt tên là cửa xanh số 1. Trong mắt của một con cá đang bơi giữa hai làn nước cò giấu một nút ấn. Bob ấn ngón trỏ vào đó : các tấm ván xoay đi.Bob đẩy xe đạp vào và đóng cánh cửa mật lại.Hiện, Hannibal đang ngồi trong chiếc ghế bành đu cũ kỹ và đang dùng hai ngón tay bóp chặt môi dưới, điều này luôn? là dấu hiệu của một hoạt động trí óc dữ dội. Còn bạn của cậu, Peter Crentch, thì đang cho chạy cái máy in nhỏ, trước kia hư hỏng, nhưng được Haninibal vá víu thành công.Máy in kêu kích cắc, Peter, cao lớn tóc đen, đang cho vào máy in những tấm carton trắng vuông mà cậu rút ra ngay sau đó.Như vậy là Bob nói đúng: không có gì bí mật trong lời nhắn của Hannibal và lời nhắn chỉ có nghĩa: máy in đang chạy; hãy đến gặp mình ngay bằng cách đi qua cửa xanh số 1.Bob cất xe đạp vào góc xưởng; Peter ngừng chạy máy in và đưa cho Bob 1 tấm carton vừa mới in.(Ba thám tử trẻ-Alfred Hitchcock)");
  17.             textview.Font = new Font(new FontFamily("Verdana"), 13);
  18.             textview.BackColor = Color.White;
  19.             textview.Dock = DockStyle.Fill;
  20.             Controls.Add(textview);
  21.         }
  22.     }
  23.     public class TextView : Control
  24.     {
  25.         VScrollBar ThanhCuon;
  26.         int fCuonDoc = 0;//kích thước vùng text bị che phía trên
  27.         Size KichThuocCu=Size.Empty ;
  28.         int Height1;
  29.         int Height2;
  30.         int Vien = 2;
  31.         public TextView(string text)
  32.         {
  33.             text = text.Replace("\r\n", "");
  34.             this.Text = text;
  35.             Padding = new Padding(5);
  36.             ThanhCuon=new VScrollBar() ;
  37.             ThanhCuon.Top = Vien ;
  38.             ThanhCuon.Visible = false;
  39.             ThanhCuon.Scroll+=new ScrollEventHandler(ThanhCuon_Scroll);
  40.             Controls.Add(ThanhCuon);
  41.         }
  42.         private void ThanhCuon_Scroll(object sender, ScrollEventArgs e)
  43.         {
  44.             fCuonDoc = e.NewValue;
  45.             int h = Height - 2*Vien ;
  46.             if (Math.Abs(e.NewValue - e.OldValue) >= h)
  47.             {
  48.                 Invalidate();
  49.             }
  50.             else
  51.             {
  52.                 Point Diem1;
  53.                 Point Diem2;
  54.                 Size size;
  55.                 Graphics g = CreateGraphics();
  56.                 //có lẽ lỗi chữ bị nhòe là do cái if else này
  57.                 if (e.NewValue > e.OldValue)
  58.                 {
  59.                     Diem1 = new Point(Vien,Vien +e.NewValue-e.OldValue );
  60.                     Diem2 = new Point(Vien , Vien );
  61.                     size = new Size(Width - 2*Vien , Height - 2*Vien - e.NewValue + e.OldValue);
  62.                     //copy 1 phần hình ảnh phía dưới lên phía trên
  63.                     g.CopyFromScreen(PointToScreen(Diem1), Diem2, size);
  64.                     size.Height = e.NewValue - e.OldValue;
  65.                     //Diem1.Y = Height - Vien - e.NewValue + e.OldValue;
  66.                     Diem1.Y = Height - Vien-size.Height ;
  67.                     //vẽ lại 1 phần hình ảnh phía dưới
  68.                     Invalidate(new Rectangle(Diem1,size));
  69.                 }
  70.                 else
  71.                 {
  72.                     Diem1 = new Point(Vien,Vien);
  73.                     Diem2=new Point(Vien,Vien+e.OldValue-e.NewValue );
  74.                     size = new Size(Width - 2 * Vien, Height - 2 * Vien + e.NewValue - e.OldValue);
  75.                     //copy 1 phần hình ảnh từ phía trên xuống phía dưới
  76.                     g.CopyFromScreen(PointToScreen(Diem1), Diem2, size);
  77.                     size.Height = e.OldValue - e.NewValue;
  78.                     Diem1.Y = Vien;
  79.                     //vẽ lại 1 phần hình ảnh phía trên
  80.                     Invalidate(new Rectangle(Diem1,size ));
  81.                 }
  82.                 //liệu lỗi có thể là do khi chưa Invalidate toàn bộ vùng được chỉ định thì sự kiện scroll mới xảy ra làm gián đoạn nửa chừng không?
  83.             }
  84.         }
  85.         private int CuonDoc
  86.         {
  87.             set
  88.             {
  89.                 fCuonDoc = value;
  90.                 ThanhCuon.Value = value;
  91.             }
  92.         }
  93.         private int ChieuRong
  94.         {
  95.             set
  96.             {
  97.                 //tính toán lại độ cao của text khi width thay đổi
  98.                 Graphics g=CreateGraphics() ;
  99.                 int w = value - Padding.Left - Padding.Right - 2*Vien ;
  100.                 //Height1 độ cao text khi không có thanh cuộn
  101.                 Height1 = (int)g.MeasureString(Text, Font, w,StringFormat.GenericTypographic ).Height+Padding.Top+Padding.Bottom ;
  102.                 //Height2 độ cao text khi có thanh cuộn
  103.                 Height2 = (int)g.MeasureString(Text, Font, w - ThanhCuon.Width, StringFormat.GenericTypographic).Height + Padding.Top + Padding.Bottom;
  104.             }
  105.         }
  106.         protected override void OnPaint(PaintEventArgs e)
  107.         {
  108.             base.OnPaint(e);
  109.             Graphics g=e.Graphics ;
  110.             Rectangle rect = ClientRectangle;
  111.             StringFormat format = StringFormat.GenericTypographic;
  112.             rect.Inflate(-Vien , -Vien );
  113.             //vẽ viền
  114.             ControlPaint.DrawBorder(g, ClientRectangle, Color.CadetBlue, ButtonBorderStyle.Inset);
  115.             //xác định vùng clip không bao gồm đường viền
  116.             g.Clip = new Region(rect);
  117.  
  118.             g.TranslateTransform(Vien , Vien - fCuonDoc);
  119.             rect = new Rectangle( Padding.Left, Padding.Top, Width - 4 - Padding.Left - Padding.Right, Height2);
  120.             if (ThanhCuon.Visible)
  121.             {
  122.                 rect.Width -= ThanhCuon.Width;
  123.             }
  124.             g.DrawString(Text, Font, new SolidBrush(ForeColor), (RectangleF)rect ,format );
  125.         }
  126.         protected override void OnResize(EventArgs e)
  127.         {
  128.             base.OnResize(e);
  129.             ThanhCuon.Left = ClientSize.Width - Vien -ThanhCuon.Width ;
  130.             ThanhCuon.Height=ClientSize.Height-2*Vien ;
  131.             if (Size.Width != KichThuocCu.Width)
  132.             {
  133.                 ThayDoiChieuRong();
  134.             }
  135.             else
  136.             {
  137.                 ThayDoiChieuCao();
  138.             }
  139.             KichThuocCu=Size;
  140.         }
  141.         private void ThayDoiChieuRong()
  142.         {
  143.             ChieuRong = Size.Width;
  144.             ThayDoiChieuCao();
  145.         }
  146.         private void ThayDoiChieuCao()
  147.         {
  148.             int h = Size.Height - 4;
  149.             if (Height1 <= h)
  150.             {
  151.                 ThanhCuon.Visible = false;
  152.                 CuonDoc=0;
  153.             }
  154.             else
  155.             {
  156.                 ThanhCuon.Visible = true;
  157.                 //dòng dưới này lẽ ra là ThanhCuon.Maximum = Height2 - h
  158.                 //nhưng nếu dùng chuột kéo thanh cuộn xuống hết cỡ thì value cũng chỉ bằng Maximum -LargeChange +1
  159.                 ThanhCuon.Maximum = Height2 - h + ThanhCuon.LargeChange - 1;
  160.                 if (fCuonDoc > ThanhCuon.Maximum - ThanhCuon.LargeChange + 1)
  161.                 {
  162.                     CuonDoc = ThanhCuon.Maximum - ThanhCuon.LargeChange + 1;
  163.                 }
  164.             }
  165.             Invalidate();
  166.         }
  167.         protected override void OnClick(EventArgs e)
  168.         {
  169.             base.OnClick(e);
  170.             Invalidate();
  171.         }
  172.     }
  173. }

Đây là ảnh của lỗi, lỗi nhòe thực sự nằm ở sát cạnh trên hoặc cạnh dưới của Control, trên screenshot vùng bị nhòe nằm ở giữa là do kéo quá tay, không biết có phải lỗi là do lệnh invalidate không được thực thi hoàn toàn không nữa
TextViewCuon5.JPG
TextViewCuon5.JPG (117.08 KiB) Đã xem 355 lần
TextViewCuon7.JPG
TextViewCuon7.JPG (115.76 KiB) Đã xem 355 lần

Xin cảm ơn các bạn!



khoaph
Thành viên chính thức
Thành viên chính thức
Bài viết: 34
Ngày tham gia: T.Ba 08/12/2015 12:57 pm
Been thanked: 4 time

Re: Nhờ kiểm tra lỗi chữ bị nhòe khi cuộn trong Control tự tạo

Gửi bàigửi bởi khoaph » T.Ba 08/03/2016 2:42 pm

Mình đã tìm ra cách thay thế
tạo 1 control tên Nhan là con của control TextView, ThanhCuon cũng là con của TextView
khi TextView.Width thay đổi thì thay đổi Nhan.Width và tính lại chiều cao của text rồi thay đổi Nhan.Height cho vừa với text, cập nhật ThanhCuon
khi thanh cuộn thay đổi thì thay đổi Nhan.Top = -giá trị mới của thanh cuộn
cái Form1.cs đây
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Text;
  7. using System.Windows.Forms;
  8. using System.Diagnostics;
  9.  
  10. namespace Test_cuon_noi_dung_label_2
  11. {
  12.     public partial class Form1 : Form
  13.     {
  14.         public Form1()
  15.         {
  16.             InitializeComponent();
  17.             View2 view = new View2("Rồi cậu leo lên xe đãp đi đến Thiên Đường buôn bán đồ cổ.Máy chỉnh hình mà Bob? phải đeo ở chân, từ khi cậu bị gãy chân trong một lấn thử leo núi, gần như không làm phiền cậu khi đạp xe, nên cậu nhanh chóng rời khỏi trung tâm thành phố và không trục trặc gì đến mục đích? chuyến đi của mình.Chính Hannibal đặt ra cái tên Thiên đường buôn bán Đồ cổ. Trước kia chỗ đó tên là Hiệu đồ cũ. Chính tại nơi này, ông Jones, chú của Hannibal bán đủ loại đồ vật hỗn tạp. Việc thay đổi tên cửa hàng đã rất có lợi cho ông : bây giờ, ở mấy chục cây số quanh vùng, người ta đến Thiên đường buôn bán đồ cổ để làm áp phe.Bob vượt qua cổng chính- một cổng sắt vĩ đại mua ở nhà biệt thự lân cận – và chỉ dừng lại? xa hơn ba trăm mét, ngay trước góc, nơi tranh tường có vẽ một? cảnh biến giận dữ và chiếc buồm sắp chìm đắm. Bob nhảy xuống đất trước hai tấm ván nơi Hannibal đã tự làm cho mình một cửa vào bí mật đặt tên là cửa xanh số 1. Trong mắt của một con cá đang bơi giữa hai làn nước cò giấu một nút ấn. Bob ấn ngón trỏ vào đó : các tấm ván xoay đi.Bob đẩy xe đạp vào và đóng cánh cửa mật lại.Hiện, Hannibal đang ngồi trong chiếc ghế bành đu cũ kỹ và đang dùng hai ngón tay bóp chặt môi dưới, điều này luôn? là dấu hiệu của một hoạt động trí óc dữ dội. Còn bạn của cậu, Peter Crentch, thì đang cho chạy cái máy in nhỏ, trước kia hư hỏng, nhưng được Haninibal vá víu thành công.Máy in kêu kích cắc, Peter, cao lớn tóc đen, đang cho vào máy in những tấm carton trắng vuông mà cậu rút ra ngay sau đó.Như vậy là Bob nói đúng: không có gì bí mật trong lời nhắn của Hannibal và lời nhắn chỉ có nghĩa: máy in đang chạy; hãy đến gặp mình ngay bằng cách đi qua cửa xanh số 1.Bob cất xe đạp vào góc xưởng; Peter ngừng chạy máy in và đưa cho Bob 1 tấm carton vừa mới in.(Ba thám tử trẻ-Alfred Hitchcock)");
  18.             view.Dock = DockStyle.Fill;
  19.             Controls.Add(view);
  20.         }
  21.     }
  22.     public class View2 : Control
  23.     {
  24.         VScrollBar ThanhCuon;
  25.         Control Nhan;
  26.         Size KichThuocCu = Size.Empty;
  27.         public View2(string text)
  28.         {
  29.             ThanhCuon=new VScrollBar();
  30.             ThanhCuon.Dock=DockStyle.Right ;
  31.             ThanhCuon.Visible=false;
  32.             ThanhCuon.Scroll+=new ScrollEventHandler(ThanhCuon_Scroll);
  33.             Controls.Add(ThanhCuon);
  34.             Nhan=new Control();
  35.             Nhan.Text=text;
  36.             Nhan.BackColor = Color.WhiteSmoke;
  37.             Nhan.Font = new Font(new FontFamily("Verdana"),13,FontStyle.Regular);
  38.             Nhan.Paint+=new PaintEventHandler(Nhan_Paint);
  39.             Nhan.Padding = new Padding(5);
  40.             Controls.Add(Nhan);
  41.         }
  42.         private void Nhan_Paint(object sender, PaintEventArgs e)
  43.         {
  44.             Control nhan=(Control)sender;
  45.             Graphics g =e.Graphics;
  46.             RectangleF r = new RectangleF(new Point(0, 0), nhan.Size);
  47.             r.Inflate(-nhan.Padding.Left,-nhan.Padding.Top );
  48.             g.DrawString(nhan.Text,nhan.Font,new SolidBrush(nhan.ForeColor ),r,StringFormat.GenericTypographic );
  49.         }
  50.         protected override void OnResize(EventArgs e)
  51.         {
  52.             base.OnResize(e);
  53.             if (Size.Width != KichThuocCu.Width)
  54.             {
  55.                 ThayDoiChieuRong();
  56.             }
  57.             else
  58.             {
  59.                 ThayDoiChieuCao();
  60.             }
  61.             KichThuocCu=Size;
  62.         }
  63.         private void ThayDoiChieuCao()
  64.         {
  65.             if (Nhan.Height > Height)
  66.             {
  67.                 ThanhCuon.Visible = true;
  68.                 ThanhCuon.Maximum = Nhan.Height - Height + ThanhCuon.LargeChange - 1;
  69.                 if (-Nhan.Top > ThanhCuon.Maximum - ThanhCuon.LargeChange + 1)
  70.                 {
  71.                     Nhan.Top = -(ThanhCuon.Maximum - ThanhCuon.LargeChange + 1);
  72.                 }
  73.             }
  74.             else
  75.             {
  76.                 ThanhCuon.Visible = false;
  77.                 ThanhCuon.Value = 0;
  78.                 Nhan.Top = 0;
  79.             }
  80.             Nhan.Invalidate();
  81.         }
  82.         private void ThayDoiChieuRong()
  83.         {
  84.             Nhan.Width = Width - ThanhCuon.Width;
  85.             Debug.WriteLine(Nhan.Size.ToString());
  86.             Graphics g = Nhan.CreateGraphics();
  87.             int w = Nhan.Width - Nhan.Padding.Left - Nhan.Padding.Right;
  88.             int h=g.MeasureString(Nhan.Text,Nhan.Font,w,StringFormat.GenericTypographic ).ToSize ().Height+1;
  89.             Nhan.Height = h + Nhan.Padding.Top + Nhan.Padding.Bottom;
  90.             ThayDoiChieuCao();
  91.         }
  92.         private void ThanhCuon_Scroll(object sender,ScrollEventArgs e)
  93.         {
  94.             Nhan.Top = -e.NewValue;
  95.         }
  96.     }
  97. }

nếu ai có hứng thú thì vẫn có thể tiếp tục đề tài này
mình vẫn muốn biết nguyên nhân vấn đề đã nêu:)


Quay về “Visual Basic .NET và C# (VB.NET & C#)”

Đang trực tuyến

Đang xem chuyên mục này: Google [Bot]2 khách