Chỉnh sửa thông báo DevExpress (XtraMessageBox)

thuvienwinform - Mình rất là không thích những đoạn mà xen lấn tiếng anh, tiếng việt. Điển hình là các thông báo. Mặc định các nút đề là tiếng anh(OK, Yes, No, Cancel,...) chúng ta nên việt hóa toàn bộ. Vừa dễ dàng cho người sử dụng, vừa có được giao diện đẹp.



Công việc này khá đơn giản. Tạo 1 lớp (class) là xong!
Chú ý: cần thêm DevExpress.Data; và DevExpress.XtraEditors; (Add Reference)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DevExpress.XtraEditors.Controls;
using DevExpress.Utils.Localization;

namespace ThuVienWinform.ThongBaoDevExpress
{
    //https://documentation.devexpress.com/#WindowsForms/CustomDocument1866
    public class TuyChinhDevExpress : Localizer
    {
        public string Abort { set; get; }
        public string Cancel { set; get; }
        public string Ignore { set; get; }
        public string No { set; get; }
        public string Ok { set; get; }
        public string Retry { set; get; }
        public string Yes { set; get; }

        public TuyChinhDevExpress(string abort, string cancel, string ignore, string no, string ok, string retry, string yes)
        {
            this.Abort = abort;
            this.Cancel = cancel;
            this.Ignore = ignore;
            this.No = no;
            this.Ok = ok;
            this.Retry = retry;
            this.Yes = yes;
        }

        public override string GetLocalizedString(StringId id)
        {
            if (id == StringId.XtraMessageBoxAbortButtonText) return this.Abort;
            if (id == StringId.XtraMessageBoxCancelButtonText) return this.Cancel;
            if (id == StringId.XtraMessageBoxIgnoreButtonText) return this.Ignore;
            if (id == StringId.XtraMessageBoxNoButtonText) return this.No;
            if (id == StringId.XtraMessageBoxOkButtonText) return this.Ok;
            if (id == StringId.XtraMessageBoxRetryButtonText) return this.Retry;
            if (id == StringId.XtraMessageBoxYesButtonText) return this.Yes;
            return base.GetLocalizedString(id);
        }
    }
}

Sử dụng:
Khai báo đoạn này trong sự kiện nạp (Form_load), hay trong tệp Program.cs đều được:
Chú ý: using DevExpress.XtraEditors.Controls;

Localizer.Active = new TuyChinhDevExpress("&Hủy bỏ", "&Hủy", "&Chấp nhận", "&Xác nhận", "&Được", "&Thử lại", "&Được");

Vậy là xong rồi!
6/17/2014
Đăng bởi :

Tối ưu hóa chương trình lớn gồm nhiều Form

thuvienwinform
Trích đoạn "Nếu làm theo cách này, chương trình của bạn dù  nặng đến đâu thì cũng chỉ khác nhau ở thời gian Load thôi, chứ chạy thì mượt thôi rồi :))" haha

I. Vấn đề
Những chương trình "lớn" - nhất là liên quan tới quản lí đào tạo, quản lí các loại .... đều thường dùng 20 tới 30 Form..... Hầu hết các form được gọi đi gọi lại rất nhiều trong quá trình sử dụng (nhất là những form con trong thiết kế MDI) Như vậy sẽ rất ngốn RAM ... với phương thức "this.Hide()" sẽ không giúp giải phóng bộ nhớ RAM . và bạn sẽ không thể gọi "this.Close()" để đóng hẳn form này (vì nó sẽ làm toàn bộ chương trình đóng) --> Nói chung không có phương thức nào giải phóng RAM khi các form này được gọi.

Vậy hôm nay mình sẽ hướng dẫn các bạn cách tối ưu hóa những chương trình kiểu này :)
Rất đơn giản thôi

II. Thực hiện
Ví dụ ở đây mình tạo chương trình mẫu có 6 form : frmMain, frmSplash, frm1 --> frm4

Bây giờ thay vì mỗi lần gọi phải tạo 1 đối tương như kiểu :
frmMain frm = new frmMain();
frm.Show()
Mình sẽ tận dụng form frmSplash ( 1 form load trước khi form Main hiện ra) để khởi tạo tất cả các đối tượng (mà ở đây là 5 form : frmMain, frm1--> frm4) (Không Show đâu nhé) và biến đối tượng được lưu vào 1 class có tên DTO.cs .
Ưu điểm của việc này là làm 1 cái form kiểu Loading nhìn "rất chuyên nghiệp" và các winform đã khởi tạo luôn trong trạng thái "Sẵn sàng" , gọi .Show() 1 cái là lên luôn (chứ không có tình trạng nếu form nhiều Control quá thì load lâu nữa... vì nó load sẽ rồi)

+  DTO.cs
class Winform
{
         public static frmMain MAIN;
         public static frm1 FORM1;
         public static frm2 FORM2;
         public static frm3 FORM3;
         public static frm4 FORM4;
}

+ Trong Form Splash (Load) chỉ cần khởi tạo rất đơn giản (nhớ cái form là MdiParent phải khởi tạo trước nhé)  --> Đúng nghĩa là Load nhé :))

Winform.MAIN = new frmMain();
Winform.FORM1 = new frm1();
Winform.FORM2 = new frm2();
Winform.FORM3 = new frm3();
Winform.FORM4 = new frm4();

Và từ giờ hãy tương tác với các Form theo biến static trong class Winform
Ví dụ ở form Main muốn Show frm1 chỉ cần gọi :

Winform.FORM1.Show()
Đơn giản đúng không ^^! Bây giờ nó sẽ tiết kiệm bộ nhớ đồng thời chạy nhanh hơn rất nhiều đấy :) (Vì mọi thức đều được Load trước khi dùng mà ^^!)

* Update dữ liệu
Giờ có 1 vấn đề là cần Update dữ liệu mỗi lần bật 1 form lên  (Vì form mình đã load từ khi bật chương trình - bây giờ dữ liệu có thể đã bị sửa rồi ) :D
Nếu gọi theo cách truyền thống "mỗi lần gọi lại tạo 1 đối tương mới rồi Show" thì nó tự update là đương nhiên

Nhưng theo cách này bạn sẽ làm 1 công việc khá đơn giản là viết thêm 1 phương thức Update dữ liệu nữa rồi gọi theo mỗi lần gọi phương thức Show().

Ví dụ : frm1 mình có 1 GridView, cần được làm mới mỗi khi frm1 hiện.
Trong class frm1 mình viêt:

public void CapNhatDuLieu()
{
// GetData() là 1 phương thức cập nhật lại dữ liệu
         GridView.DataSource = GetData();
}

=> Mỗi lần Show Form 1 hãy kèm thêm 1 lệnh cập nhật
Winform.FORM1.CapNhatDuLieu();
Winform.FORM1.Show();

Vậy là xong rồi.... Có vẻ hơi dài dòng nhỉ ^^!
Nếu làm theo cách này, chương trình của bạn dù  nặng đến đâu thì cũng chỉ khác nhau ở thời gian Load thôi, chứ chạy thì mượt thôi rồi :))





6/15/2014
Đăng bởi :
Nhãn :

Thêm nút lên GridView của DevExpress bằng HyperLinkEdit

thuvienwinform - Với gridView của DevExpress, nếu không nói quá thì có thể hiển thị dữ liệu với mọi cách mà ta muốn. Nó hỗ trợ quá tuyệt vời! Nhưng thêm những thứ khác ngoài dữ liệu. Cụ thể như nút,  ô lựa chọn,...ta làm thế nào! Sau đây mình xin được giới thiệu cách thêm nút lên gridView của DevExpress. Cách là là thêm một cột HyperLinkEdit cho GridView sau đó hiển thị HyperLink đó bằng hình ảnh (nhìn giống nút)



CÁC BƯỚC THỰC HIỆN (3 BƯỚC)

Bước 1: Thêm 1 cột cho GridView

Ấn mũi tên chọn Add Column

Bước 2: Chỉnh Column Edit cho cột vừa thêm. Chọn New -> HyperLinkEdit
Ấn mũi tên của cột xong sủa giá tị của Column Edit thành HyperLinkEdit

Bước 3:  Đặt ảnh cho HyperLinkEdit

Ấn mũi tên chọn Run Designer

Columns -> chọn cột vừa thêm. Chú ý tên biến ở đây là repositoryItemHyperLinkEdit1

Kéo xuống đến thuộc tính Image Chọn hình ảnh cẩn hiển thị

Căn giữa cho ảnh (mục đích là che đi chữ của cột)


Bước 4: Viết mã cho sự kiện ấn (Click) cho nó. Chúng nó sẽ viết nó trong sự kiện Form_Load:
Cách 1:
private void frmQuanLiBaiSoan_Load(object sender, EventArgs e)
{
    repositoryItemHyperLinkEdit1.Click += repositoryItemHyperLinkEdit1_Click;//Gõ += xong ấn Tab
}

private void repositoryItemHyperLinkEdit1_Click(object sender, EventArgs e)
{
    //mã sự kiện
}

Cách 2:
private void frmQuanLiBaiSoan_Load(object sender, EventArgs e)
{
    repositoryItemHyperLinkEdit1.Click += (s1, e1) =>
        {
            //mã sự kiện
        };
}

Tham khảo thêm việc tùy chình GridView tại http://nvnhan2910.blogspot.com/2014/06/windowform-lam-viec-voi-gridview-grid.html

Xem thêm:

Phân trang trong winform | Paging in winform

thuvienwinform - Phân trang thực ra là một đặc trưng trong lập trình web. Chia dữ liệu cần tải (load) ra làm nhiều phần nhỏ giúp việc hiển thị nhanh hơn (do dữ liệu tải về nhỏ hơn). Trong winform thì phân trang giúp cho sử dụng tài nguyên (cụ thể là RAM) ít hơn. Nhưng mình thử thì không giảm đi là bao :)), có lẽ do mình chưa giải phòng bộ nhớ tốt.




Sau đây mình xin giới thiệu với các bạn phân trang trong winform đằng LINQToSQL

Thư viện phân trang: https://www.dropbox.com/s/nj6fnuso2b2138p/ThuVienWinform.PhanTrang.dll (14KB)
Chương trình mẫu: https://www.dropbox.com/s/z9dvnbtceu3xv40/ThuVienWinform-PhanTrangLINQ.rar (710KB)

Nếu không tải được trên DropBox các bạn liên hệ trực tiếp thuvienwinform@gmail.com để mình gửi hoặc chạy Ultrasuft để truy cập lại DropBox

Trong chương trình mẫu có 2 tệp tin chứa cơ sở dữ liệu cho nó chạy các bạn nạp nó vào rồi sửa lại kết nối cho LINQ mới chạy được

Giới thiệu ThuVienWinform.PhanTrang:
- Với thư viện này sẽ không làm ảnh hưởng đến mã đã viết vì không cần thêm dòng code nào cả, chỉ việc khai báo và xài thui
- Khai báo:
phanTrang = new PhanTrangTruyenThong<tbPhanTrang>(this.db, this.bindingNavigator1, 20);
Hoặc
PhanTrangTuyChinh<tbPhanTrang> pTrang = new PhanTrangTuyChinh<tbPhanTrang>(this.db, button1, comboBox1, button2, bindingNavigator1.BindingSource, 20);
Trong đó:
+ tbPhanTrang là đối tượng cần phân trang, ở đây là một bảng tbPhanTrang trong CSDL
+ db là biến DataContext của LINQToSQL
+ bindingNavigator1: thanh điều hướng cho datagridView
+ 20: số hàng trên 1 trang
+ button1: là nút nhảy về trang sau
+ button2: là nút nhảy về trang trước
+ comboBox1: là comboBox để hiển thị các trang
+ bindingNagigator1.BindingSource là BindingSource của datagridView

- Chế độ:
+ PhanTrangTruyenThong: phân trang dựa vào bindingNavigator có sẵn, mình sẽ thêm 2 nút tiến lùi và 2 cái comboBox để hiển thị số trang lên đó
+ PhanTrangTuyChinh: truyền vào 2 nút và 1 comboBox có sẵn để làm 2 nút tiến lùi và hiển thị danh sách trang.

- Thuộc tính và sự kiện:
+ TrangHienTai: lấy về hoặc đặt trang hiện tại (set, get)
+ sự kiện NhayTrang: trả về hướng nhảy (tiến hoặc lùi) và số trang nhảy

- Mã phân trang bằng LINQ
 
/// <summary>
/// Lấy dữ liệu từ chiSoDau đến chiSoCuoi
/// </summary>
/// <typeparam name="doiTuongCanPhanTrang">Đối tượng cần phân trang</typeparam>
/// <param name="db">DataContext chứa dữ liệu cần phân trang</param>
/// <param name="chiSoDau">Chỉ số đầu</param>
/// <param name="chiSoCuoi">Chỉ số cuối</param>
/// <returns></returns>
public object DuLieuPhanTrang<doiTuongCanPhanTrang>(DataContext db, int chiSoDau, int chiSoCuoi) where doiTuongCanPhanTrang : class
{
    try
    {
        var phanTrangs = (from p in db.GetTable<doiTuongCanPhanTrang>()
                            select p).Skip(chiSoDau).Take(chiSoCuoi - chiSoDau);
        return phanTrangs;
    }
    catch
    {
        return null;
    }
}

- Tư tưởng phân trang theo mình hiểu như sau: có một kho dữ liệu lớn (ví dụ 10 tỷ trường), ta không tải hết 10 tỷ trường đấy về để hiển thị lên dataGridView được (cháy máy mà chết mất). Nên phải chia nhỏ ra mỗi lần hiển thị 10 nghìn cái thôi!
- Có lỗi về thư viện hoặc ý tưởng mới về phân trang cùng nhau chia sẻ các bạn nha
- Chia sẻ mã ThuVienWinform.PhanTrang.dll quan hòm thư thuvienwinform@gmail.com nha!
6/13/2014
Đăng bởi :
Nhãn : ,

Hiển thị một đối tượng lên DatagridView

thuvienwinform - Có rất nhiều trường hợp ta cần hiển thị đối tượng lên bảng để hiển thị đẹp hơn cũng như dễ dàng trong việc nhập, xử lí dữ liệu. Tương tự cách làm với LINQ thì ra chỉ cần thêm đối tượng của minh vào Data Sources rồi kéo ra dataGridview là xong (đơn giản nhất) hoặc viết mã hiển thị đối tượng đó lên bảng cũng được (nhưng công việc thiết kế như đặt tên cột, thứ tự cột, ... sẽ khó khăn hơn). Mình sẽ giới thiệu cả 2 cách

Mẫu: https://www.dropbox.com/s/9tdv0s2f5bmnxsr/thuvienwinform-HienThiDoiTuongLenDgv.rar (55KB)

Cách 1: Thêm đối tượng và Data Sources rồi kéo thả ra bảng (đơn giản nhất)
- cách này nhanh, tùy biến, thêm, xóa thuộc tính của đối tượng và thiết kế dễ  dàng (nên dùng cách này)

B1: Khai báo đối tượng:
- Đối tượng Class1 với các thuộc tính của nó

class Class1
{
    public string ThuocTinh1 { set; get; }
    public string ThuocTinh2 { set; get; }
    public string ThuocTinh3 { set; get; }
    public string ThuocTinh4 { set; get; }
    public string ThuocTinh5 { set; get; }
    public string ThuocTinh6 { set; get; }
}

B2: Thêm nó vào Data Sources 



B3: Đối tượng này ra form (phải ở chế độ thiết kế (Design))

Chọn DataGridView

Kéo ra

DataSource tự sinh

B4: thêm dữ liệu
- Chỉ cẩn thêm và data source là nó sẽ tự hiện lên bảng:

//Khai báo và truyền giá trị cho các thuộc tính của dối tượng
Class1 doiTuong = new Class1();
doiTuong.ThuocTinh1 = "1";
doiTuong.ThuocTinh2 = "2";
doiTuong.ThuocTinh3 = "3";
doiTuong.ThuocTinh4 = "4";
doiTuong.ThuocTinh5 = "5";
doiTuong.ThuocTinh6 = "6";

class1BindingSource.Add(doiTuong);//Thêm đối tượng này vào bảng

Kết quả:

- Để tùy biến giao diện ấn vào mũi tên nhỏ -> Edit Columns



Cách 2: Viết mã để hiển thị:
- Cách này khi thêm một thuộc tính cho đối tượng sẽ khó khăn trong việc sửa mã.

B1: cũng khai báo đối tượng như ở Cách 1
B2: Kéo một dataGridView ra form
B3: Viết mã nạp đối tượng lên bảng

//Dùng code
BindingSource dts = new BindingSource();//Khai báo BindingSource
dts.DataSource = typeof(Class1);// => datasource này chỉ thêm được những đối tượng Class1. Nếu không thì nó sẽ nhận typeof(đối tượng đầu tiên thêm vào)
dataGridView1.DataSource = dts;

dts.Add(doiTuong);//Thêm 1 đối tượng lên bảng (sẽ tự tạo ra 1 hàng mới). Biến doiTuong giống như ở cách 1
dts.AddNew();//Thêm 1 hàng mới (các giá trị đều rỗng)

//Đặt tên cho các cột
dataGridView1.Columns["ThuocTinh1"].HeaderText = "cột 1";
dataGridView1.Columns["ThuocTinh2"].HeaderText = "cột 2";
for (int i = 3; i <= 6; i++)
    dataGridView1.Columns["ThuocTinh" + i].HeaderText = "cột " + i;

//Sắp xếp vị trí cho cột
dataGridView1.Columns["ThuocTinh2"].DisplayIndex = 0;

Kết quả:

Lấy, sửa dữ liệu đã được thêm vào:

//Lấy dữ liệu
string dt1 = ((Class1)class1BindingSource.Current).ThuocTinh1;
string dt2 = ((Class1)class1BindingSource.Current).ThuocTinh2;

//Sửa
((Class1)class1BindingSource.Current).ThuocTinh2 = "sửa";
foreach (Class1 thuocTinh in class1BindingSource)
    thuocTinh.ThuocTinh1 = "OK";

6/03/2014
Đăng bởi :
Nhãn :

Sự kiện thay đổi nội dung tệp tin. Event change file


thuvienwinform - Chắc hẳn các bạn rất hay gặp phải thông báo này nếu dùng 2 chương trình cùng chỉnh sửa nội dung 1 tệp tin. Để bắt được sự kiện tệp tin bị thay đổi nội dung, được tạo mới hoặc bị xóa đi ta dùng FileSystemWatcher tron System.IO.

Project demo: https://www.dropbox.com/s/vv25p45gmdkat2s/thuvienwinform-FileSystemWatcher%28Kiem%20tra%20su%20thay%20doi%20cua%20file%29.rar (49KB)
 
private void KiemTraSuThayDoiCuaFile(string thuMuc, string tenFile)
{
    FileSystemWatcher fwc = new FileSystemWatcher();
    fwc.Path = thuMuc;
    fwc.Filter = tenFile;
    fwc.NotifyFilter = NotifyFilters.LastWrite;
    fwc.EnableRaisingEvents = true;
    fwc.Changed += (s1, e1) =>
    {
        //code cần thực hiện khi file thay đổi
        MessageBox.Show("File da bi thay doi");
    };
}


6/01/2014
Đăng bởi :
Nhãn :

Bắt sự kiện bật, tắt chương trình. Event start, stop process


thuvienwinform - C# hỗ trợ người lập trình biết được chương trình nào vừa được bắt đầu, chương trình nào vừa kết thúc thông qua sự kiện EventArrivedEventHandler của ManagementEventWatcher nằm trong bộ thư viện System.Management. Để bắt được các sự kiện này, đầu tiên chương trình phải có quyền admin. Để thực hiện gán quyền admin cho chương trình xem thêm tại: http://thuvienwinform.blogspot.com/2013/09/item-manifes-tchay-ung-dung-winform-voi-quyen-admin.html

Project demo: https://www.dropbox.com/s/es33d1d5413oqop/thuvienwinform-ManagermentEventWatcher%28KiemTraSuThayDoiCuaTaskMgr%29.rar

Sau khi thêm quyền admin cho chương trình, ta thoát visual ra và chạy lại nó với quyền admin
Chú ý: nếu không sử dụng được ManagementEventWatcher thì phải thực hiện Add reference System.Management bằng tay
Rồi, ok code như sau:
1. Bắt sự kiện chương trình mới được bật lên

void ChuongTrinhBat()
{
    WqlEventQuery q = new WqlEventQuery("Win32_ProcessStartTrace");
    ManagementEventWatcher w = new ManagementEventWatcher(q);
    w.EventArrived += new EventArrivedEventHandler(voidChuongTrinhBat);
    w.Start();
}

private void voidChuongTrinhTat(object sender, EventArrivedEventArgs e)
{
    string s = "";
    foreach (var pd in e.NewEvent.Properties)
        if(pd.Value != null)
            if (pd.Name == "ProcessName")// ngoai ra con co ProcessID, TIME_CREATED
                s += pd.Value.ToString() + "\n";
    MessageBox.Show("Co mot chuong trinh vua moi tat\n" + s);
}

2. Bắt sự kiện chương trình bị tắt đi

void ChuongTrinhTat()
{
    ManagementEventWatcher w1 = new ManagementEventWatcher("select ProcessName from Win32_ProcessStopTrace");
    w1.EventArrived += new EventArrivedEventHandler(voidChuongTrinhTat);
    w1.Start();
}
private void voidChuongTrinhBat(object sender, EventArrivedEventArgs e)
{
    string s = "";
    foreach (var pd in e.NewEvent.Properties)
        if (pd.Value != null)
            if (pd.Name == "ProcessName")// ngoai ra con co ProcessID, TIME_CREATED
                s += pd.Value.ToString() + "\n";
    MessageBox.Show("Co mot chuong trinh vua moi bat\n" + s);
}

- Ngoài ra có thể chỉnh lại cái đoạn select một chút để lấy những giá trị cần thiết như:
+ Lấy ProcessName: select ProcessName from Win32_ProcessStopTrace
+ Lấy thời gian: select TIME_CREATE from Win32_ProcessStartTrace
+...
5/31/2014
Đăng bởi :
Nhãn :

[CODE] Truyền dữ liệu qua lại giữa các Process và ứng dụng

thuvienwinform - Xin chào ! Hôm nay mình sẽ hướng dẫn truyền dữ liệu qua lại giữa các Process. Việc này tưởng như không quan trọng lắm nhưng thực ra nó rất cần thiết khi code các phần mềm liên quan tới quản lí máy tính như Antivirus....

I. Vấn đề
Chắc hẳn các bạn đã dùng nhiều phần mềm diệt virus và thấy luôn có 1 exe riêng cho Tray (chạy dưới khay taskbar). Hãy tự hỏi tại sao lại phải tách riêng ra như vậy mà không code gộp vào 1 exe cho dễ quản lí ???
Đơn giản thôi, vì cái Tray đó làm nhiệm vụ quản lí Runtime (thời gian thực -- chạy liên tục cùng máy tính) và nếu gộp vào thì sẽ rất ngốn RAM (Ram sẽ phải load cả phần giao diện ...) nên để hệ thống chạy "êm và không nặng nề" người ta đã làm Tray ra 1 exe riêng biệt . ^^ và bây giờ việc truyền dữ liệu giữa Process là vấn đề quan trọng

II. Giải quyết
Thời còn .NET Framework 3.0 trở xuống người ta vẫn phải truyền dữ liệu qua lại giữa Process thông qua File. Nhưng tới .NET 3.5 , đã có 1 công nghệ xuất hiện để giải quyết vấn đề này.

Hôm nay mình sẽ giới thiệu vs các bạn công nghệ Pipes - công nghệ này chạy theo mô hình Server/Client
(using System.IO.Pipes) tức là 1 process sẽ đóng vai trò như 1 máy chủ, các process khác gửi nhận dữ liệu thông qua Server.

Xem 1 ví dụ đơn giản nhé (Ví dụ vẫn là cách học dễ nhất nhỉ ^^)

* Server :
Form server của mình có 1 textbox và 1 nút
(ấn vào button sẽ gửi data trong textbox cho Client)
 
// Biến Server
private NamedPipeServerStream sv;

        public Server()
        {
            InitializeComponent(); 
        }

        private void Server_Load(object sender, EventArgs e)
        {
                   // Tạo server có tên "ServerTest"
            sv = new NamedPipeServerStream("ServerTest", PipeDirection.InOut);
                   // Đợi 1 client khác kết nối
            sv.WaitForConnection();
        }

        private void button1_Click(object sender, EventArgs e)
        {
              // Khi ấn Button1 - Gửi dữ liệu cho client (phải gửi dạng byte nhé)
            var data = Encoding.Unicode.GetBytes(this.textBox1.Text);
            sv.Write(data, 0, data.Length);
 
        }

* Client



Form Client chỉ có 1 ricktexbox để cập nhật


// Client
NamedPipeClientStream stream;

        public Client()
        {
            InitializeComponent();
            
        }

        private void Client_Load(object sender, EventArgs e)
        {
                 // Kết nối tới "ServerTest"
            stream = new NamedPipeClientStream("ServerTest");
            stream.Connect();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            // Timer này cập nhật dữ liệu liên tục dưa vào RickTextbox mình đã tạo
            var re = new byte[1000];

            stream.Read(re, 0, 1000);
            string data = Encoding.Unicode.GetString(re);

            if (data != "")
                richTextBox1.Text += "\n" + data;
        }

Chạy server trước, sau đó chạy client và thử nhé ^^!

Ô xong rồi ^^!
Vậy đã truyền được dữ liệu giữa các process ^^
5/06/2014
Đăng bởi :
Nhãn :

[Code] Xử lí sự kiện cho nhiều Control

thuvienwinform - Chào ! Khi tạo form chắc hẳn bạn sẽ gặp rất nhiều control mà sẽ dùng chung một sự kiện. Nhất là đối với các hiệu ứng cho các control (Ví dụ như sự kiện MouseMove và MouseLeave...) Hôm nay chúng ta sẽ giải quyết vấn đề này. Cũng dễ thôi ^^

 I. VẤN ĐỀ 
Đối với một Form có rất nhiều Control ... và bạn muốn Form "Lung linh" hơn thì cần thêm hiệu ứng cho các Control trong Form. Ví dụ như khi trỏ chuột vào Lable thì chữ nó đậm lên - khi ngừng trỏ thì quay lại như ban đầu. >> Bình thường bạn phải tạo từng sự kiện cho từng Lable (mỗi Lable 2 sự kiện lận đó .. điều này tương đương với 2 procedure nhỏ) Mà ví dụ như có 100 Label thì sao nhỉ --> 200 sự kiện OMG ... Đủ chết rồi đấy ^^

II. GIẢI QUYẾT 
Đơn giản thôi, ở đây chúng ta sẽ tạo ra một lớp có đầy đủ các sự kiện ... và sau đó chỉ cần truyền Control vào lớp này là xong ^^! Bắt đầu nhé : Ở đây mình sẽ tạo lớp XULIHIEUUNG như sau :
 
public class XULIHIEUUNG
    {
        Control g_Control;

        public void TAOHIEUUNG(Control c)
        {
            g_Control = c;
            btn.MouseMove += new System.Windows.Forms.MouseEventHandler(MouseMoveEvent);
            btn.MouseLeave += new System.EventHandler(MouseLeaveEvent);
        }
        public void MouseMoveEvent(object sender, EventArgs e)
        {
            g_Control.Text = "Ô bắt được con chuột";
        }
        public void MouseLeaveEvent(object sender, EventArgs e)
        {
            g_Control.Text = "Chuột chạy mất rồi";
        }
    }

Trong hàm khởi tạo form chỉ cần thêm code sau bạn chỉ cần thêm code sau đây :

 new XULIHIEUUNG().TAOHIEUUNG(button1); 

 Bây giờ thử mở Form ra coi... Khi bạn trỏ chuột vào button1 và khi di chuyển chuột ra khỏi chỗ đó .. Xem thế nào :)) (1 dòng này = 6 dòng code tay đấy, chưa kể phải mở Properties của từng Control mà chọn sự kiện)

 OK, vậy là xong rồi. Đơn giản đúng không :D
5/04/2014
Đăng bởi :
Nhãn :

Thêm thuộc tính, sự kiện cho các điểu khiển trong winform

thuvienwinform - Apply Attributes in Windows Forms Controls (áp dụng các thuộc tính vào các điều khiển trong winform) sẽ giúp chúng ta thêm những sự kiện, thuộc tính chúng ta cần vào các control này. Ví dụ như thêm tính năng chuẩn hóa cho textBox, hoặc giới hạn độ dài cho textBox. Rất tiện trong quá trình code và sau này, tức là dùng cho được nhiều sản phẩm. Chính vì sự hữu ích này, hôm nay mình xin được chia sẻ cách thêm thuộc tính và sự kiện cho các điều khiển trong winform.


Tải về project demo: https://www.dropbox.com/s/6ih1d0oephk97r2/thuvienwinform-ThemThuocTinhChoControl.rar (46KB)

Bài viết này sẽ giới thiệu việc thêm tính năng chuẩn hóa và giới hạn độ dài cho TextBox. Gồm 2 phần
- Phần I: Thêm thuộc tính, sự kiện cho 1 điều khiển dựa trên lớp kế thừa
- Phần II: Tạo 1 điều khiển chứa nhiều điều khiển (từ các điều khiển đã có)

Chú ý: nếu tải về mở ra lỗi thì ấn F5 cho nó chạy sẽ hết lỗi (Do nó chưa nạp các điều khiển tự tạo vào)
- Để đọc code dễ ấn chuột phải vào code -> Outlining -> Collapse to Definitions (Ctrl + M,O).
- Để xem code của cotrol không có Design: ấn F7 hoặc ấn vào Switch to code...

I. Thêm thuộc tính, sự kiện cho 1 điều khiển

1. Thêm thuộc tính


- Rất đơn giản thôi. Đầu tiên thêm 1 class với tên: MyTextBox

- Class này kế thừa của TextBox


- Sau đó ta thêm các thuộc tính cho MyTextBox như sau:

[Category("Thuộc tính xây dựng thêm")]
[Description("Chuẩn hóa văn bản nhập vào. Viết hoa kí tự sau dấu cách")]
[DefaultValue(true)]
public bool ChuanHoa
{
    get;
    set;
}

private DoDai _doDai;//Cái này phục vụ cho việc thêm sự kiện sau này
[Category("Thuộc tính xây dựng thêm")]
[Description("Định độ dài cho văn bản \nNgắn: 30 kí tự\nBình thường: 60 kí tự\nDài:255 kí tự")]
public DoDai ĐộDài
{
    get { return _doDai; }
    set{_doDai = value;}
}

Với DoDai là 1 enum

public enum DoDai
{
    Ngắn,
    BìnhThường,
    Dài,
    TốiĐa
}

Trở lại phần thiết kế ta đã có được như này


2. Xây dựng chức năng chuẩn hóa, giới hạn độ dài

a. Chuẩn hóa
- Chúng ta sẽ chuẩn hóa sau khi nhập chữ vào MyTextBox xong. Sử dụng sự kiện LostFocus và ấn nút Enter để thực hiện chuẩn hóa. this.Text = ChuanHoaXau(this.Text);

protected override void OnLostFocus(EventArgs e)
{
    base.OnLostFocus(e);
    ThucHienChuanHoa();
}

protected override void OnKeyDown(System.Windows.Forms.KeyEventArgs e)
{
    base.OnKeyDown(e);
    //Ấn enter
    if (e.KeyCode == System.Windows.Forms.Keys.Enter)
        ThucHienChuanHoa();
}

private void ThucHienChuanHoa()
{
    //Chuẩn hóa xâu trong textBox
    this.Text = ChuanHoaXau(this.Text);//Các hàm còn lại xem trong project demo nha
    //Đưa con trỏ nhấp nháy về cuối dòng
    this.Select(this.Text.Length, this.Text.Length);
}

Kết quả:


b. Giới hạn độ dài
- Để giới hạn độ dài ta sử dụng sự kiện TextChanged
protected override void OnTextChanged(EventArgs e)
{
    base.OnTextChanged(e);
    int doDaiToiDa = 0;
    switch (ĐộDài)
    {
        case DoDai.Ngắn         : doDaiToiDa = 30; break;
        case DoDai.BìnhThường   : doDaiToiDa = 60; break;
        case DoDai.Dài          : doDaiToiDa = 255; break;
        default: break;
    };
    if (ĐộDài != DoDai.TốiĐa)
        if (this.Text.Length > doDaiToiDa)
            ThietLapDoDai(doDaiToiDa);
}

/// <summary>
/// Thiết lập độ dài kí tự trong textBox
/// </summary>
/// <param name="ddtd">Độ dài tối đa cho phép</param>
private void ThietLapDoDai(int ddtd)
{
    //Dữ lại đoạn văn bản cho phép
    this.Text = this.Text.Substring(0, ddtd);
    //Đưa con trỏ nhấp nháy về cuối dòng
    this.Select(ddtd, ddtd);
}

- Cách này khá thủ công như có lẽ như vậy sẽ dễ hiểu hơn. Để tối ưu thì ta sửa luôn việc set get biến Text của TextBox. Chuẩn hóa luôn khi set get

3. Bắt sự kiện thay đổi giá trị ĐộDài

a. Sử dụng delegate EventHandler
- Tạo sự kiện
public event EventHandler ThayDoiDoDai;//Khai báo sự kiện

- Code cho sự kiện
protected virtual void OnThayDoiDoDai()
{
    EventHandler handler = this.ThayDoiDoDai;
    if (handler != null)
    {
        handler(this, EventArgs.Empty);
    }
}

- OK. Đã có sự kiện! Bây giờ đặt vào chỗ cần thực hiện sự kiện. Đó là khi giá trị ĐộDài thay đổi. Là lúc nào nhỉ?? Chính là lúc set get giá trị cho nó
public DoDai ĐộDài
{
    get { return _doDai; }
    set
    {
        _doDai = value;
        //Mỗi khi thay đổi giá trị -> set, get 1 lần => chính là sự kiện thay đổi giá trị
        OnThayDoiDoDai();
    }
}


b. Tạo lớp kế thừa của EventHandler để tạo thêm các giá trị cho sự kiện
- Ví như sự kiện CellClick của DataGridView có thể lấy giá trị hàng (e.RowIndex). Vậy làm như thế nào để thêm các thuộc tính cho sự kiện. Ta cần tạo 1 lớp kế thừa của thằng EventHandler như sau:
//Tạo class bằng file mới hoặc trong cùng class MyTextBox đều được. Xem thêm trong project demo
public class ThayDoiGiaTriDoDai : EventArgs
{
    public DoDai GiaTriDoDai { get; set; }
    public bool DuocChuanHoa { get; set; }
    public string ThongTinChoSuKien
    {
        get { return "Sự kiện thay đổi giá trị độ dài của MyTextBox"; }
    }
}

- Thêm sự kiện sử dụng lớp kế thừa này
[Category("Sự kiện Xây dựng thêm")]
[Description("Bắt sự kiện thay đổi độ dài. Dùng class kế thừa")]
public event EventHandler<ThayDoiGiaTriDoDai> ThayDoiDoDaiDungClass;//Khai báo sự kiện
/// <summary>
/// Code cho sự kiện
/// </summary>
/// <param name="s">Nạp giá trị đầu vào để hiển thị ra khi sử dụng sự kiện</param>
protected virtual void OnThayDoiDoDai(ThayDoiGiaTriDoDai s)
{
    EventHandler<ThayDoiGiaTriDoDai> handler = this.ThayDoiDoDaiDungClass;
    if (handler != null)
    {
        handler(this, s);
    }
}

- OK bây giờ sửa lại lúc set get là được
public DoDai ĐộDài
{
    get { return _doDai; }
    set
    {
        _doDai = value;
        //Mỗi khi thay đổi giá trị -> set, get 1 lần => chính là sự kiện thay đổi giá trị
        SuKien = new ThemThuocTinhChoControl.ThayDoiGiaTriDoDai();
        SuKien.GiaTriDoDai = this.ĐộDài;
        SuKien.DuocChuanHoa = this.ChuanHoa;
        OnThayDoiDoDai(SuKien);
    }
}

- Kết quả:



II. Tạo UserControl từ các control khác

- Trong thực tế có nhiều form ta có các kiểu bố trí giống nhau, có sự kết hợp của nhiều control giống nhau. Ví dụ như tập hợp các textBox để nhập thông tin họ tên ngày sinh,...thì ta chỉ cần tạo 1 lần vào sử dụng cho các form khác nhau. Để thực hiện việc này ta làm như sau:

- Tạo 1 UserControl

- Sau đó thì kéo các điều khiển khác vào

- Ok có thể nói là xong rùi nhưng ta muốn thêm các thuộc tính, sự kiện cho thằng này thì làm tương tự phần I là OK.
- Ví dụ thêm thuộc tính tự động Anchor:
public bool TuDongDanCachCacPhanTu
{
    get { return _tuDongDanCachCacPhanTu; }
    set 
    { 
        _tuDongDanCachCacPhanTu = value;
        if (_tuDongDanCachCacPhanTu)
        {
            this.Anchor = AnchorStyles.Bottom | AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;//This ở đây là UserCOntrol
            this.myTextBox1.Anchor = AnchorStyles.Bottom | AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
            this.myTextBox2.Anchor = AnchorStyles.Bottom | AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
        }
        else
        {
            this.Anchor = AnchorStyles.Top | AnchorStyles.Left;
            this.myTextBox1.Anchor = AnchorStyles.Top | AnchorStyles.Left;
            this.myTextBox2.Anchor = AnchorStyles.Top | AnchorStyles.Left;
        }
    }
}
- Sau khi đã thêm tạo được các file cs chỉ cần thêm vào các project khác là ok.

Nếu thấy hữu ích hãy để lại bình luận hoặc ấn G+. Cảm ơn các bạn đã đọc bài viết
4/25/2014
Đăng bởi :

Nhận ngay 100$ cho VPS

Mua hàng ủng hộ page

Ủng hộ page

Nhãn

Code (45) Team Foundation Server (17) Database (14) News (14) product (13) toolbox (10) Linq (9) SoftDesign (8) XNA (6) API (5) Project (5) item (4)

- Bản quyền thuộc về Thư Viện WinForm - Giao diện: Metrominimalist - Thiết kế: Johanes Djogan -