[Tutorial] Graphic User Interface (GUI)

Lee

Cố Vấn CLB
Staff member
Chào các bạn !

Giao tiếp với máy tính là 1 phần không thể thiếu trong các hệ thống điều khiển ngày nay. Chúng ta có thể xây dựng 1 GUI (Graphic User Interface) bằng nhiều loại ngôn ngữ khác nhau như C++, VB , C# ... (Matlab cũng có thể xây dựng được GUI). Ngôn ngữ được xem là "mạnh" nhất, có nhiều thư viện hỗ trợ nhất hiện nay là C#.Net. Chính vì thế, tutorials sau đây sẽ giúp các bạn tiếp cận với C# dễ dàng hơn.

Tutorials Basic sẽ hướng dẫn các bạn giao tiếp với ngoại vi thông qua Com Port, thu thập dữ liệu từ ngoại vi, hiển thị đồ thị hoặc xuất ra file text để lưu trữ.

Mục lục :

Phần 1:
- Bài 1: Tìm Hiểu Giao Diện
- Bài 2: Tạo Project Window Form
- Bài 3: Các lệnh cơ bản
- Bài 4: Xuất/Nhập Dữ Liệu Ra File Text
- Bài 5: "Đóng Gói Sản Phẩm"

Phần 2:
- Bài 6: Đóng Mở Cổng Com
- Bài 7: Autodetect Com
- Bài 8: Read/Write Data

Phần 3:
- Bài 9 : Demo ZedGraph (Vẽ Đồ Thị)
- Bài 10: Add Thư Viện Dll
- Bài 11: Code Vẽ Đồ Thị

P/S : Mong rằng mọi người học tập và đóng góp để Tuts ngày càng tốt hơn !
 
anh LEE ơi! anh có thể hướng dẫn em viết code để lấy nội dung trong form Messenger của yahoo khi đang chát thành chỗi txt bằng c# được không. hình như là cái đó lấy từ file .dat trong mục Program Files/yahoo/messenger/Profiles..... ra phải không anh?
 

Lee

Cố Vấn CLB
Staff member
Anh có xem qua 2 file .dat trong thư mục em nói. Nó chả có gì,(mở bằng notepad). :d

Anh nghĩ, khi chúng ta chat, nội dung không được lưu trong bất kì file nào trong máy tính chúng ta. Anh lướt qua chức năng lưu nhật kí của yahoo, nếu muốn xem lại nội dung thì nó sẽ hiện thông báo loading... --> nội dung được lưu trên server--> muốn lấy được nội dung, chúng ta phải hiểu về mạng, cách truyền dữ liệu... và dĩ nhiên áp dụng nó như thế nào trong c# !!!

Áp dụng kiến thức mạng vào c# như thế nào, em có thể xem tut phần tcp server và tcp client ! Clip chỉ trình bày cách áp dụng chứ ko nói đến cấu trúc mạng, để hiểu rõ hơn thì em nên xem file pdf kèm theo (lí thuyết đó) :d.

Mà làm cái này chi vậy em ?
 

tungbk

Cố Vấn CLB
Staff member
Mình mò vào file cái yahoo thì đúng là khi ta chat ND sẽ lưu vào file .dat trong file :
C:\Program Files\Yahoo!\Messenger\Profiles\"nick của mình"\Archive\Messages
trong này có các folder chứa các file .dat lưu ND chat nhưng mở 2 file .dat này toàn mã k ah.Mình pải biết cách lập trình của nó thì mới mở lại được ND nó lưu(cái này trên mạng hình như có các phần mềm mở được).
Vì thường khi trong option Yahoo Preference tab Achive default là "Save all of my mesage ,but clear them each time I sign out" nên sẽ k lưu sau khi sign out
Vì vậy đơn giản để lưu toàn bộ ND chat chọn lại Option "Yes save all of my mesages" là xong ;
Nhưng theo ý bạn Tuấn là đọc ngay khi mình chat qua lại thì cái này mình no comment do k biết về cái giao thức trao đổi qua lại của nó .(Thử hỏi tụi bên máy tính;hôm trước có thèn bạn nó viết 2 form giống 2 client kết nối chat qua lại trên khung )
Vài ý kiến đóng góp! (^_^)
 

tungbk

Cố Vấn CLB
Staff member
A lee cho hỏi là muốn lưu vào file text không phải 1 giá trị mà một mảng nhiều giá trị chẳng hạn.VD e đã viết cái form giải PT bậc 2 nên muốn lưu 2 nghiệm cùng lúc nhưng có thể đọc ra mỗi giá trị riêng biệt.(hiện e lưu vào string là chuỗi add 2 nghiệm liên tiếp rồi xuất ra text box multi-line nhưng cách này có vẻ chuối vì không lấy được từng nghiệm)
Rồi mình có thể lưu thành file log giống trong win .VD ngày tháng năm dùng phần mêm GPTB2 kết quả giải ra sao.
Cảm ơn anh trước.
 
đúng là như tùng nói. ý định của em là dùng yahoo để điều khiển vi điều khiển thông qua mạng máy tính. thông qua các câu lệnh điều khiển được chuyển đến từ yahoo. nhưng em lại không biết cách lấy được nội dung trên Messenger. vì em thấy khi mình chát thì trên máy tính có lưu lại file *.dat khi out thi file đó cũng biến mất. nên em nghĩ nội dung mình chát nó sẽ được lưu trên file này. vì nó được lưu dưới dạng file .dat nên không mở nó bằng notepad được mà phải có một phần mềm chuyên dụng đêr đọc được nó. nên khi mở bằng notepad thì thấy giống hiện tượng lỗi font vậy
 

Lee

Cố Vấn CLB
Staff member
A lee cho hỏi là muốn lưu vào file text không phải 1 giá trị mà một mảng nhiều giá trị chẳng hạn.VD e đã viết cái form giải PT bậc 2 nên muốn lưu 2 nghiệm cùng lúc nhưng có thể đọc ra mỗi giá trị riêng biệt.(hiện e lưu vào string là chuỗi add 2 nghiệm liên tiếp rồi xuất ra text box multi-line nhưng cách này có vẻ chuối vì không lấy được từng nghiệm)
Rồi mình có thể lưu thành file log giống trong win .VD ngày tháng năm dùng phần mêm GPTB2 kết quả giải ra sao.
Cảm ơn anh trước.
Em có thể làm như sau:
- Lưu nghiệm vào 2 mảng double : double[] x1=new double[1000] , double[] x2=new double[1000]. (1000 là độ dài của mảng)
- Đặt 1 biến streamWriter để ghi ra text : StreamWriter sw=new StreamWriter("logs.txt");
- Khi ghi ra text thì làm như sau : for(int i=0;i<1000;i++) sw.WriteLine(x1.ToString()+" "+x2.ToString()); ( cho 1 cái khoảng trắng giữa 2 nghiệm)
- Đặt 1 biến streamreader để đọc về : StreamReader sr=new StreamReader("logs.txt");
- Muốn đọc về thì ta cần phải biến đc vị trí của khoảng trắng : (đặt 3 biến kiểu string s,s1,s2, biến space khiểu int)
s = sr.ReadLine();
space=s.IndexOf(" ");
s1 = s.Substring(0, space);
s2 = s.Substring(space+1, s.Length-space-1);

- Vậy là đc 2 biến s1,s2 ( 2 nghiệm ). Nếu muốn lấy hết tất cả các nghiệm nằm trong text thì em cho đoạn chương trình trên vào trong vòng for. Để coi cấu trúc và cách thức hoạt động của các lệnh trên, em gõ nó vào trong project, rê cho con trỏ đến ngay lệnh đó và nhấn f1, sẽ ra help online ngay lệnh đó.
- Để lưu ngược lại 2 biến s1,s2 thành kiểu double lưu vào mảng thì :
double.TryParse(s1, out x1);
double.TryParse(s2, out x2);

- Muốn hiển thị lên textbox thì chỉ cần 2 biến string s1,s2 lúc này là dc. Còn muốn làm gì nữa với dữ liệu đó thì dùng các phần tử trong x1[] và x2[].

Cách này đc anh áp dụng cho tất cả trường hợp cần đọc/ghi dữ liệu ra text. :d

Làm thử , rồi báo kết quả anh biết. Chúc may mắn! :d
 

Lee

Cố Vấn CLB
Staff member
Mình mò vào file cái yahoo thì đúng là khi ta chat ND sẽ lưu vào file .dat trong file :
C:\Program Files\Yahoo!\Messenger\Profiles\"nick của mình"\Archive\Messages
trong này có các folder chứa các file .dat lưu ND chat nhưng mở 2 file .dat này toàn mã k ah.Mình pải biết cách lập trình của nó thì mới mở lại được ND nó lưu(cái này trên mạng hình như có các phần mềm mở được).
Lạ nhỉ, các em dùng bản yahoo version mấy vậy.Anh dùng bản 11, ko tìm ra cái thư mục Archive đó, vào nick của mình là hết, trong đó có 1 file .dat và nôi dung đọc được bằng notepad.
 

tungbk

Cố Vấn CLB
Staff member
E dùng yahoo 10 mới cài trên web yahoo.Anh Lee vào "C:\Program Files\Yahoo!\Messenger\Profiles\"nickcuaminh"\Archive" mà anh phải có cái achive lúc đó tức là anh chat vd với 1 nik nào đó.Hoặc anh thay đổi cái option như e post ở trên thì mới thấy.file dat mở đầu bằng ngày tháng năm +tên nik mình vừa chat.
Cảm ơn Anh Lee giúp code ở trên.Từ từ e làm thử được k.Sắp thi DKTD mà Tuấn cứ post ý tưởng mới lạ k chịu k được.(^_^)
 

tungbk

Cố Vấn CLB
Staff member
Sau khi ngâm cứu thêm thì theo mình ý tưởng của Tuấn khá hay và có thể thực hiện được.
BToan giải quyết 2 vấn đề chính
1. làm sao lấy được kí tự vừa type
2. gửi xuống VDK bằng cách nào
Không cần dùng file .dat cho rắc rối mình đề xuất 2 p/an

+TH1: bạn muốn dùng dạng form giống yahoo tức là khi điền mã vào Enter thì dữ liệu sẽ truyền xuống VDK .VD: "Clear"Enter thì gửi xuống kí tự C xóa màn hình LCD chẳng hạn =>cái này bản chất nó giống như giao tiếp sử dụng HyperTerminal hồi TN VXl bằng 8051==> k cần dùng yahoo cho rắc rối ;mình tạo 1 textbox1 giống yahoo tức là có phần điền chữ Enter đọc chuỗi này lưu vào file Text ("Stream Writer")giống Anh lee chỉ ;sau đó đọc ra lại từ file text("Streamreader") mà chú ý so sánh chuỗi"CLEAR-Enter"=kí tự"C" gửi xuống VXL bằng cổng Ntiep hiện trên text box2 là đã nhận kí tự C và đã gửi( cũng có trong tut anh Lee.)
==> Cái này khả thi
+TH2: bạn muốn điều khiển qua mạng (cái này mới cần yahoo chứ k thì dùng TH1 là được rồi) .các bạn cũng từng nghe bot auto_answer trên yahoo là mình sign out nhưng nik mình tự trả lời khi có người chat.
vào trang này http://www.imified.com/developers/api để tìm hiểu thêm.
tức là tạo 1 nik yahoo VD VDKPIC chẳng hạn ;tạo bot cho nó; sau đó bạn đăng nhập nik chat của mình add nik VDKPIC vào chat với con bot này .Mỗi lần send qua thì bên bot sẽ lưu lại ND trên 1 cái host để xử lí và reply lại
==>Vấn đề đặt ra 2 bước
1.lấy ND lưu lại trên host để xử lí ==>cần kiến thức lập trình mạng
2.G/su ta lấyđược rồi thì sẽ phải truyền qua Internet đi đến con VDK đang nối mạng ==>Lập trình gửi dữ liệu đến VDK qua mạng.
(kì trước đồ án Anh lee đã làm trong đồ án dk tbi qua Ethernet,internet gì đó. Anh lee góp ý thêm)
==>pan này làm thành cái đồ án được;)
Cái này chỉ là ý kiến tui chắc chắn là chưa làm bao giờ nên k biết la khả thi k
vài ý kiến đóng góp .
 
đó cũng là một ý kiến hay. nhưng liệu rằng mình có lập trình được cho pic kết nối trực tiếp với mạng được không đó là một vấn đề rất khó. chủ yếu là mình xuất ra cổng com thôi. tức là mình tạo 2 nick yahoo onlien trên 2 máy. ngồi máy ko kết nối với vi điều khiển để điều khiển thông qua yahoo. mô hình của nó là thế này. nick yahoo 1=>máy ko kết nối vdk=>nick yahoo2 =>máy kết nối vdk=>vdk. đại khái là thế chứ mình kết nối vdk trực tiếp với internet thì mình vẫn chưa có phương án để làm, kêt nối trực tiếp thì phải nghiên cứu sâu về cấu trúc mạng xem có thể lập trình được cho vdk không đã
 

tungbk

Cố Vấn CLB
Staff member
Ah ý tuấn là ở máy 2 làm sao chỉ cần đọc file .dat rồi gửi xuống VDK là được phải k.
 
đúng vậy. chứ cái giao tiếp trực tiếp vdk khiển với internet là một vấn đề lớn mình cần tìm hiểu sâu hơn giao thức mạng. mới bước đầu thì làm vậy đã dần dần sẽ làm trực tiếp.
không biết ý anh LEE thế nào. anh có thể gọi ý thêm cho bọn em được không
 

tungbk

Cố Vấn CLB
Staff member
mới lập cái bot vui vui;) ae add nik này vào yahoo thử nghe;) anhtunghcmut08 (code copy trên mạng rồi sửa lại)
 

Lee

Cố Vấn CLB
Staff member
Decode Yahoo Message Archive

Tình hình là anh đã giải mã được file .dat như tụi em nói --> Phương án 1 mà Tùng nói là khả thi !:p:p:p

Đầu tiên mình tạo 1 form giao diện, cho user nhập tên file cần decode và nickname của người đó ( nickname chính la key để giải mã ) :
- Nếu muốn giải mã 1 file nào đó thì nhấn nút DECODE.
- Nếu mình muốn giải mã ngay cả khi đang chat, mình chọn mode AUTO, chương trình sẽ tự động giải mã nếu có sự thay đổi độ dài dữ liệu trong file --> điều khiển qua mạng có thể thực hiện được theo cách này !

Sau khi đã giải mã dc, dữ liệu đó ta muốn làm gì tiếp cũng dc. Chẳng hạn, t gửi nội dung chat xuống cho vi điều khiển thông qua UART, hiển thị LCD. Thú vị đó !:cool:

Còn phương án 2, để từ từ coi tiếp !;););)

Xem ảnh:


P/S: Bạn nào đã có VS2010, có thể down project tại đây --> ngâm cứu thử.
 
ok anh LEE. em sẽ nghiên cứu . và đồ án sắp tới có lẽ em sẽ làm với đề tài điều khiển thiết bị qua mạng.:)). thank anh nhiều
 

Lee

Cố Vấn CLB
Staff member
Bạn xem kĩ lại các dòng code của mình, coi có đúng chưa. Thường bị nhầm lẫn khi code là curve với curve1, list với list1. Nếu nhầm nhau thì chạy không đúng đâu. :D
Code here :
Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ZedGraph;
 
namespace Bai_2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
int TickStart, intMode=1;
[COLOR=red]private void Form1_Load(object sender, EventArgs e)[/COLOR]
{
GraphPane myPane = zed.GraphPane;
myPane.Title.Text = "MOTOR POSITION";
myPane.XAxis.Title.Text = "Time , Seconds";
myPane.YAxis.Title.Text = "Angle , Deg";
 
// Save 60000 points. At 50 ms sample rate, this is one minute
// The RollingPointPairList is an efficient storage class that always
// keeps a rolling set of point data without needing to shift any data values
RollingPointPairList list = new RollingPointPairList(60000);
RollingPointPairList list1 = new RollingPointPairList(60000);
 
// Initially, a curve is added with no data points (list is empty)
// Color is blue, and there will be no symbols
LineItem curve = myPane.AddCurve("Set Value", list, Color.Red, SymbolType.None);
LineItem curve1 = myPane.AddCurve("Current Value", list1, Color.Blue, SymbolType.None);
// Sample at 50ms intervals
 
 
// Just manually control the X axis range so it scrolls continuously
// instead of discrete step-sized jumps
myPane.XAxis.Scale.Min = 0;
myPane.XAxis.Scale.Max = 30;
myPane.XAxis.Scale.MinorStep = 1;
myPane.XAxis.Scale.MajorStep = 5;
 
// Scale the axes
zed.AxisChange();
 
// Save the beginning time for reference
TickStart = Environment.TickCount;
}
 
[COLOR=red]private void PbMode_Click(object sender, EventArgs e)[/COLOR]
{
if (PbMode.Text == "SROLL")
{
intMode = 1;
PbMode.Text = "COMPACT";
}
else
{
intMode = 0;
PbMode.Text = "SROLL";
}
}
 
[COLOR=red] private void Draw(string setpoint, string current)[/COLOR]
{ // Make sure that the curvelist has at least one curve
double intsetpoint;
double intcurrent;
double.TryParse(setpoint, out intsetpoint);
double.TryParse(current, out intcurrent);
if (zed.GraphPane.CurveList.Count <= 0)
return;
 
// Get the first CurveItem in the graph
LineItem curve = zed.GraphPane.CurveList[0] as LineItem;
LineItem curve1 = zed.GraphPane.CurveList[1] as LineItem;
if (curve == null)
return;
if (curve1 == null)
return;
 
// Get the PointPairList
IPointListEdit list = curve.Points as IPointListEdit;
IPointListEdit list1 = curve1.Points as IPointListEdit;
// If this is null, it means the reference at curve.Points does not
// support IPointListEdit, so we won't be able to modify it
if (list == null)
return;
if (list1 == null)
return;
 
// Time is measured in seconds
double time = (Environment.TickCount - TickStart) / 1000.0;
 
 
list.Add(time, intsetpoint);
list1.Add(time, intcurrent);
 
// Keep the X scale at a rolling 30 second interval, with one
// major step between the max X value and the end of the axis
Scale xScale = zed.GraphPane.XAxis.Scale;
if (time > xScale.Max - xScale.MajorStep)
{
if (intMode == 1)
{
xScale.Max = time + xScale.MajorStep;
xScale.Min = xScale.Max - 30.0;
}
else
{
xScale.Max = time + xScale.MajorStep;
xScale.Min = 0;
}
}
 
// Make sure the Y axis is rescaled to accommodate actual data
zed.AxisChange();
// Force a redraw
zed.Invalidate();
}
 
[COLOR=red] private void PbExit_Click(object sender, EventArgs e)[/COLOR]
{
Close();
}
 
[COLOR=red] private void timer1_Tick(object sender, EventArgs e)[/COLOR]
{
Draw("100", "200");
}
 
[COLOR=red]private void zed_Load(object sender, EventArgs e)[/COLOR]
{
 
}
}
}
P/S : cách đặt tên biến có vẻ chưa hợp lí lắm. Các bạn đặt tên biến lại cho dễ nhớ :D
 
Top