MỚI NHẤT

Thứ Ba, 19 tháng 7, 2016

[EXE + APK] Mời dùng thử: MyChat cập nhật phiên bản mới cho Windows và Android


Nghỉ hè, trong khi người khác đi chơi cùng bạn bè thì mình chỉ có suốt ngày vùi đầu vào cái máy tính :))
Sau mấy ngày "ngâm cứu" thì cũng ra ít sản phẩm.
MyChat nay đã có trên nền tảng Android (rất tiếc là chưa thể lên AppStore)
Các tính năng chính của ứng dụng này cũng tương tự như trên phiên bản Windows

  • Nhắn tin thông qua mạng LAN
  • Truyền file với dung lượng lớn, tốc độ cao

Để có thể kết nối ứng dụng Android với phần mềm trên máy tính yêu cầu điện thoại và máy tính của bạn phải kết nối vào cùng 1 mạng, và đảm bảo mạng đó phải thông giữa 2 máy.
Một vài hình ảnh của ứng dụng
MyChat cập nhật phiên bản mới cho Windows và Android
Giao diện khởi động, có thể nhập địa chỉ của server rồi KẾT NỐI, hoặc dùng quét mã QR để scan địa chỉ từ máy server

MyChat cập nhật phiên bản mới cho Windows và Android
Quét mã QR từ server
MyChat cập nhật phiên bản mới cho Windows và Android
Giao diện chính của chương trình

MyChat cập nhật phiên bản mới cho Windows và Android
Có thể chuyển file với dung lượng lớn

Thông tin và cài đặt

MyChat trên windows cũng được cập nhật phù hợp
  • Chỉnh lại giao diện
  • Thêm cài đặt
  • Thêm phần tạo mã QR 
Một vài hình ảnh của phiên bản mới
MyChat cập nhật phiên bản mới cho Windows và Android
Màn hình khởi động

MyChat cập nhật phiên bản mới cho Windows và Android
Giao diện chính (của server)

MyChat cập nhật phiên bản mới cho Windows và Android
Tạo mã QR cho ứng dụng trên điện thoại

>> DOWNLOAD <<

Thứ Năm, 2 tháng 6, 2016

[EXE + APK] Phần mềm ĐẾM GIỜ

Code ngày code đêm, code quên cả ăn và hậu quả là... bụng 1 múi.
Lướt facebook vô tình đọc được tit "Chỉ cần tập các động tác này trong 20s bạn sẽ có cơ bụng 6 múi", ô thật bất ngờ, không thể tin nổi.
Bình thường cũng muốn tập tành lắm đấy nhưng do yêu cái máy tính quá nên nhiều lúc không dứt ra được, đọc được cái tit này nghĩ ngay đến "ờ thì chẳng nhẽ lại không bỏ ra 20s được"  :))
Click vào xem hóa ra đó là các động tác tập bụng, mỗi động tác thực hiện trong 20s, thực hiện hết động tác này đến tư thế kia, và quan trọng mỗi cái chỉ cần 20 giây



=> Trong đầu lóe ra ý tưởng: tại sao không dùng phần mềm đếm ngược để thông báo cho ta sau mỗi 20s ấy? Những phần mềm hiện tại chỉ cho phép đếm 1 lần rồi dừng, thế là lại có ý tưởng ngay để code :))
Phần mềm Đếm giờ đã ra đời  :D

Chức năng của phần mềm chỉ là: đếm ngược thời gian 1 số lần nhất định, sau khi hết mỗi 1 khoảng thì có thông báo bằng âm thanh.

Mình viết trên C# đã khá lâu rồi. Trong phần mềm có sử dụng:
- Dùng timer để đếm giờ
- Phát nhạc, file âm thanh
- User Control để vẽ hình vành khăn thể hiện tiến trình
- Giao diện tùy chỉnh...

dem-gio-window
Giao diện khi đếm giờ
dem-gio-window
Giao diện khởi động

Tự dưng có hứng học lập trình android, vọc vạch trong gần 1 tuần, Đếm giờ trên android đã hoàn chỉnh, chức năng cũng tương tự như trên window.
Giao diện ứng dụng:

dem-gio-android

Trong ứng dụng có các tính năng:

  • EditText, Button cơ bản (drawable, ripple...)
  • Activity single top: Activity chỉ khởi tạo 1 lần
  • Navigation bar: Navigation View và chuyển qua lại giữa các thẻ
  • Itent: Mở ứng dụng khác, mở ứng dụng từ thanh thông báo
  • Fragment, hiệu ứng chuyển cảnh (animation)
  • Notification: Hiển thị thông tin trên thanh thông báo, bắt sự kiện khi click thông báo (new Intent)
  • Press Back: Xử lý sự kiện ấn Back
  • Press twice to exit: ấn back 2 lần để thoát
  • Progressbar: hình dạng tùy chỉnh
  • Shared preferences... Lưu cấu hình chương trình: Sáng màn hình, show notification
  • Phát âm thanh
  • Luôn sáng màn hình: KeepScreenOn


==>> DOWNLOAD phần mềm:

Bạn nào cần mã nguồn, comment ở dưới để mình gửi cho.

Thứ Tư, 6 tháng 4, 2016

[Show] C# - MYCHAT Nhắn tin, gửi file qua LAN

Bọn mình vừa mới học xong môn Lập trình mạng. Nói thẳng ra là lúc học trên lớp không để ý mấy, bị hổng nhiều quá, nên học xong mới quyết định viết 1 cái app nho nhỏ. Chẳng biết đặt tên là gì nên cứ đặt đại là MYCHAT  :D
Về cơ bản my chat có những tính năng sau:

  • Nhắn tin qua lại trong mạng (LAN)
  • Gửi file, hỗ trợ file dung lượng lớn (chưa test max, nhưng theo lý thuyết thì khoảng 2TB :) ). Nếu file là ảnh thì sẽ hiển thị trực tiếp
  • Hỗ trợ nhiều client, server gửi đồng loạt cho các client nhưng client chỉ gửi cho server thôi, tùy chỉnh nickname, giao diện màu sắc cho từng client
  • Giao diện phẳng
  • Sau khi đóng chương trình, các file vừa nhận sẽ bị xóa, vì vậy nếu muốn giữ lại file thì phải copy ra thư mục khác trước khi đóng chương trình…

Trong chương trình đã sử dụng
  • Truyền tin qua socket TCP, sử dụng StreamWriter, StreamReader
  • Đa tiểu trình, đồng bộ hóa, delegate
  • FileStream, FlashWindow
  • HTML, JS, Uri,…
Giao diện chương trình
Giao diện khởi chạy, sẽ có lựa chọn là server hoặc client, nếu chạy là client thì bạn phải nhập địa chỉ IP của server vào ô
Giao diện phía client
Giao diện phía server, cột bên phải là danh sách các client đã kết nối

=> DOWNLOAD <=

Thứ Năm, 10 tháng 7, 2014

[Show] WindowForm - Duyệt phim - phần mềm quản lý thông tin phim

Mình xin giới thiệu tới các bạn sản phẩm mới hoàn thành: Phần mềm Duyệt Phim - phần mềm quản lý các thư viện phim, lấy thông tin phim từ IMDb.
Duyệt phim - phần mềm quản lý thông tin phim

Hầu hết các phim chất lượng cao (Bluray, DVD) có tên tuổi hiện nay đều có trên IMDb, và đây là 1 kênh có tiếng về đánh giá chất lượng phim.

Chức năng chính:

- Duyệt các phim trong thư mục, đưa chúng vào các thư viện. Phần mềm chỉ quét các file *.mkv, *.mp4, *.avi định dạng thường thấy với các phim chất lượng cao và mỗi thư mục con chỉ quét 1 phim.
Duyệt phim - phần mềm quản lý thông tin phim


- Cập nhật thư viện: Khi thư mục trên ổ cứng có thay đổi về phim (thêm bớt 1 số phim) => Thêm những phim mới được đưa vào thư mục, xóa những phim đã bị loại bỏ khỏi thư mục, những phim khác không bị thay đổi.
- Hiển thị trang tìm kiếm IMDb, cho người dùng chọn trang thông tin và dùng RegularExpressions để get các thông tin về lưu vào SQLite. Riêng phần hình ảnh dùng WebClient để download thông tin về rồi lưu vào SQLite dạng byte[].
- Phần Poster có ContextMenuStrip để: Chọn hình ảnh, lưu hình ảnh, xóa hình.
Duyệt phim - phần mềm quản lý thông tin phim


- Và các chức năng phụ khác.

Hướng dẫn sử dụng:

- Sau khi down phần mềm về các bạn chạy bình thường. Không nên để trong ổ cài win. Phần mềm sẽ sinh ra file Database - là nơi lưu CSDL, không được xóa nó và các file kèm theo.
- Lần đầu sử dụng chương trình chọn Library chọn Add => đặt tên và đặt đường dẫn cho thư viện.
Duyệt phim - phần mềm quản lý thông tin phim


Lưu ý về cách bố trí thư mục trên ổ cứng:
Phần mềm sẽ duyệt các thư mục con trong thư mục đã chọn. Với mỗi thư mục con chỉ chọn ra 1 file mkv/mp4/avi và tên của thư mục con sẽ là tên của phim phục vụ cho tìm kiếm sau này (còn tên file thì không quan trọng). Trong các thư mục con lại duyệt đệ quy tới các thư mục con nữa... (tên thư mục con có thể bắt đầu bằng '#')
=> Vì vậy cấu trúc thư mục nên như sau: Thư mục chính "Films", có các thư mục con: "Clash", "#Bad boys", "Trilogy - Transformer" -> { "Transformer 1", "Transformer 2", "Transformer 3" }... Trong thư mục con nên để duy nhất 1 file phim và các file phụ đề.

- Tìm và get thông tin từ IMDb: Chọn 1 phim click vào "Cập nhật thông tin từ IMDb", trang tìm kiếm hiện ra, bạn click vào link phim phù hợp, đợi một lúc hiện ra "Lấy từ trang này".
Duyệt phim - phần mềm quản lý thông tin phim


=> DOWNLOAD (MF) <=
(Download về, giải nén, sử dụng ngay. Gồm 2 phiên bản: một là phiên bản thường với giao diện mặc định của Window, một phiên bản sử dụng giao diện của DevExpress 13.1 - yêu cầu máy phải cài sẵn Dev)

Thứ Ba, 24 tháng 6, 2014

[WindowForm] Sử dụng Timer và một số chức năng với Timer

"Timer" là một điều khiển khá hữu ích trong C# - Winform. Timer tương tự như "setInterval" hay "setTimeOut" trong JavaScript đều có chức năng thực hiện một số chức năng nhất định trong các khoảng thời gian lặp lại. Một đoạn chương trình sẽ được lặp đi lặp lại với khoảng nhất định mà không ảnh hưởng đến các tiến trình khác.
Có nhiều loại Timer: System.Windows.Forms.Timer, System.Timers.Timer, System.Threading.Timer. Nhưng để đơn giản bây giờ chúng ta sẽ sử dụng điều khiển Timer của Windows.Forms.
Sử dụng Timer và một số chức năng với Timer

Để khai báo 1 đối tượng Timer cách đơn giản là vào Toolbox tìm "Timer" rồi kéo vào form
Sử dụng Timer và một số chức năng với Timer

Đặt các thuộc tính cho Timer
Sử dụng Timer và một số chức năng với Timer

Trong đó Interval là khoảng thời gian sẽ lặp lại, đơn vị tính miliseconds. Ở ví dụ ta đã bật cho Timer chạy và đặt khoảng thời gian cho nó là 1 giây (1000 miliseconds).

Sự kiện duy nhất của Timer là Timer_Tick cho phép ta thay đổi sự kiện mỗi khi timer lặp lại thời gian. Tức là khi timer lặp lại thì code trong hàm Timer_Tick sẽ được thực hiện.

Bây giờ, tôi sẽ hướng dẫn một vài công dụng với Timer:

- Đồng hồ chạy số trong Window Form

Ta có 2 label để hiển thị thời gian và ngày tháng, 2 label sẽ được thay đổi nội dung sau từng giây. Vậy chúng ta cần 1 điều khiển timer với khoảng lặp là 1000, nội dung Timer_Tick tương tự như sau:
private void timer1_Tick(object sender, EventArgs e)
{
    lblTime.Text = (DateTime.Now.Hour < 10 ? "0" + DateTime.Now.Hour.ToString() : DateTime.Now.Hour.ToString()) + ":" + (DateTime.Now.Minute < 10 ? "0" + DateTime.Now.Minute.ToString() : DateTime.Now.Minute.ToString()) + ":" + (DateTime.Now.Second < 10 ? "0" + DateTime.Now.Second.ToString() : DateTime.Now.Second.ToString());
    lblDate.Text = DateTime.Now.DayOfWeek.ToString() + ", " + (DateTime.Now.Day < 10 ? "0" + DateTime.Now.Day.ToString() : DateTime.Now.Day.ToString()) + "/" + (DateTime.Now.Month < 10 ? "0" + DateTime.Now.Month.ToString() : DateTime.Now.Month.ToString()) + "/" + DateTime.Now.Year;
}

- Ảnh động trong Window Form

Ta đã biết ảnh động thực sự là tập hợp các ảnh tĩnh được hiển thị lần lượt, lặp đi lặp lại sau 1 khoảng thời gian nhất định. Và ở đây ta dùng Timer để đặt cái khoảng thời gian nhất định đó. Mỗi khi đến điểm Tick thì thay đổi ảnh ở trong PictureBox.
/// <summary>
/// Biến kiểm tra ảnh động
/// Không hiểu sao phải dùng thêm 1 biến ngoài để kiểm tra
/// </summary>
private int _img = 1;
private void timer1_Tick(object sender, EventArgs e)
{
    if (_img == 1)
    {
        // Thay đổi ảnh
        pictureBox1.Image = NhacViec.Properties.Resources.Alarm2;
        _img = 2;
    }
    else
    {
        pictureBox1.Image = NhacViec.Properties.Resources.Alarm1;
        _img = 1;
    }
}


Demo về 2 ví dụ này có tại phần mềm Nhắc việc.
Nếu có hứng thú các bạn có thể xem thêm các phần Timer khác và sự khác nhau giữa chúng tại đây.

Chủ Nhật, 22 tháng 6, 2014

[Show] Nhắc việc - Phần mềm hữu ích cho những người bận rộn

Bạn quá bận rộn trong công việc với máy tính hay bạn đang chìm đắm trong những trận đấu kinh điển, những trận combat không dứt ra được!?! Đôi khi bạn có việc gì đấy đã lên lịch từ trước nhưng rồi lại quên béng đi!? Bạn thỉnh thoảng có đặt báo thức ở máy điện thoại nhưng rồi cũng quên mất sự xuất hiện của nó vì lúc nào cũng dán mắt vào màn hình máy tính, thậm chí còn đeo tai nghe, "quên hết sự đời".

Rất đơn giản vì giờ đây đã có "Nhắc Việc" - phần mềm nhỏ gọn sẽ nhắc bạn, không bỏ lỡ những sự kiện quan trọng.
Nhắc việc - Phần mềm hữu ích cho những người bận rộn

Link download: tại đây.

- Tính năng

Thêm các tùy chọn: Tiêu đề, nhạc chuông, thời gian nhắc, lặp lại tương tự như báo thức ở điện thoại
Chạy tự động cùng window
Form nhắc việc ở trên "Top" để người dùng để ý
Chạy ẩn dưới khay hệ thống

- Thông tin

Phần mềm do mình tự tìm tòi + viết hoàn chỉnh
Dùng SQLite => Không được xóa các file trong thư mục cài đặt

- Nhược điểm

Tiêu tốn tài nguyên RAM khá lớn

Thứ Bảy, 21 tháng 6, 2014

[WindowForm] Sử dụng NotifyIcon - Cách ẩn chương trình xuống khay hệ thống

Nhiều chương trình như UniKey, KasperSky, SkyDrive, DropBox... đều có 1 phần chương trình chạy ngầm trong hệ thống và có 1 biểu tượng icon nhỏ ở khay hệ thống - system tray. Bạn có 1 chương trình yêu cầu phải chạy liên tục và chạy ẩn (không hiện ở taskbar), có 1 biểu tượng ở khay hệ thống để người dùng có thể tương tác với chương trình. Rất đơn giản chúng ta sẽ sử dụng NotifyIcon cho việc này.
Sử dụng NotifyIcon - Cách ẩn chương trình xuống khay hệ thống

1. Sử dụng NotifyIcon

- Các bạn search ở ToolBox "NotifyIcon" và kéo vào trong form của mình.

- Các thuộc tính của NotifyIcon:
Sử dụng NotifyIcon - Cách ẩn chương trình xuống khay hệ thống

BaloonTipIcon, BaloonTipText, BaloonTipTitle hiện ra như 1 thông báo nhỏ ở khay hệ thống (nếu chúng ta cho hiện).
Sử dụng NotifyIcon - Cách ẩn chương trình xuống khay hệ thống

ContextMenuStrip là lựa chọn menu khi ấn chuột phải vào notifyIcon.
Text là phần hiện lên khi ta di chuột vào notifyIcon.
Đặt mặc định cho notifyIcon có Visible hay không!?

- Thiết lập các menu chuột phải cho NotifyIcon
Trong ToolBox ta tìm vào kéo 1 đối tượng ContextMenuStrip.
Thêm các MenuItem cho contextmenu đấy. Ở đây hỗ trợ nhiều loại như MenuItem (giống 1 button), ComboBox, TextBox, Separator (vạch ngăn cách).
Sử dụng NotifyIcon - Cách ẩn chương trình xuống khay hệ thống

Thêm sự kiện click cho các MenuItem này.

Để sử dụng ContextMenuStrip này cho NotifyIcon đừng quên thiết lập ở phần NotifyIcon như trên.

2. Ẩn chương trình xuống khay hệ thống

Việc này thực sự chỉ là ẩn chương trình đang chạy và cho hiện 1 cái NotifyIcon lên. NotifyIcon có các MenuItem để tương tác với chương trình đang chạy, như mở chương trình, thoát chương trình..., các chức năng do ta đặt ở phần ContextMenuStrip phía trên. Vì ẩn chương trình và chương trình luôn chạy ngầm nên ta phải tính làm sao để giảm thiểu tài nguyên sử dụng, form chúng ta cho chạy ngầm phải ít tốn tài nguyên, chỉ để thực hiện các chức năng cơ bản (như để gọi các form to hơn) hoặc chỉ là 1 service.

Để thực hiện ẩn chương trình ta thêm 1 button, hoặc gán vào các sự kiện khác (minimize form chẳng hạn)
Sự kiện click của button này như sau
private void btnExit_Click(object sender, EventArgs e)
{
 // Cho hiện notifyIcon
    notifyIcon1.Visible = true;
 // Hiện BaloonTip hoặc không
    notifyIcon1.ShowBalloonTip(10);
 
 // Chọn ẩn
    this.Hide();
 // Hoặc
    this.ShowInTaskbar = false;
 WindowState = FormWindowState.Minimized;
 // Hoặc cả 2 để ẩn form
}

Phần việc còn lại là do NotifyIcon phụ trách. Chẳng hạn ta muốn click chuột phải để hiện menu context, click chuột trái để mở form: Ta thêm 1 sự kiện Click hoặc MouseClick cho NotifyIcon
private void notifyIcon1_MouseClick(object sender, MouseEventArgs e)
{
    if(e.Button == System.Windows.Forms.MouseButtons.Left)
 {
  // Ẩn notifyIcon đi
  notifyIcon1.Visible = false;
  // Cách này
  WindowState = FormWindowState.Normal;
  this.ShowInTaskbar = true;
  // Hoặc
  this.Show();
  // Hoặc cả 2 miễn là phải tương ứng với lúc ẩn
 }
}

Thứ Sáu, 20 tháng 6, 2014

[WindowForm] Customize Form - Tùy chỉnh form, tạo form có hình dạng bất kỳ

Bạn thấy nhiều phần mềm có những form có hình dạng rất lạ (không phải hình chữ nhật, có border thông thường). Bạn hoàn toàn có thể tạo những form mang hình dạng đặc biệt tùy ý một cách đơn giản.
Customize Form - Tùy chỉnh form, tạo form có hình dạng bất kỳ
Như Photoshop chẳng hạn

Sau đây tôi sẽ hướng dẫn các bạn cách tạo 1 form tùy ý và các thao tác liên quan.

1. Tạo form với hình dạng tùy ý

Thực chất việc này là đặt 1 hình ảnh làm nền cho form rồi cho những phần còn lại "biến mất".
Customize Form - Tùy chỉnh form, tạo form có hình dạng bất kỳ

- Đầu tiên bạn thiết kế 1 cái hình ảnh làm nền cho form. Những phần không cần thiết thì bạn nên để trong suốt, rồi xuất ra ảnh .PNG

- Tiếp theo đặt "BackColor" của form là White, "BackgroundImage" là hình ảnh vừa tạo, FormBorderStyle None

- Đây là phần quan trọng nhất: Cuộn xuống chọn "TransparencyKey" là White => Nó sẽ tìm tất cả phần nào của background form màu trắng để làm trong suốt phần đó. 
Cách này vô cùng đơn giản, để có thể tạo được 1 form tùy ý. Chính vì thế mà nó có nhiều chỗ không trong suốt cho lắm, đặc biệt là những đường giao nhau giữa 2 màu, đoạn đường chéo... Những điểm này khá nhỏ vẫn có thể chấp nhận được. Nếu bạn muốn có nó một cách hoàn hảo + opacity của từng phần trong form thì phải dùng đến phần xử lý đồ họa.

2. Di chuyển cho form tùy chỉnh

Với 1 form đã tạo được như trên vấn đề là khi ta loại bỏ border của form thì làm sao để di chuyển form đây??? Chỉ còn cách code!!!  :)
Việc code còn đem lại cho ta những tùy chọn về di chuyển form do ta tự quyết định: chẳng hạn có cho form "chui ra phía ngoài màn hình" không hoặc là bị bó hẹp trong khuôn khổ của màn hình, cho phép người dùng click chuột ở đâu để di chuyển form???

Trong phần global ta khai báo các biến toàn cục như sau:
/// <summary>
/// Di chuyển form
/// </summary>
private bool drag = false;
private Point dragCursor, dragForm;

Quay lại phần thiết kế để double click và thêm 3 sự kiện: MouseDown, MouseMove, MouseUp cho form.
Chỉnh sửa các sự kiện đấy như sau:
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
    drag = true;
    dragCursor = Cursor.Position;
    dragForm = this.Location;
}

private void Form1_MouseMove(object sender, MouseEventArgs e)
{
    int wid = SystemInformation.VirtualScreen.Width;
    int hei = SystemInformation.VirtualScreen.Height;
    if (drag)
    {
        // Phải using System.Drawing;
        Point change = Point.Subtract(Cursor.Position, new Size(dragCursor));
        Point newpos = Point.Add(dragForm, new Size(change));
        // QUyết định có cho form chui ra ngoài màn hình không
        if (newpos.X < 0) newpos.X = 0;
        if (newpos.Y < 0) newpos.Y = 0;
        if (newpos.X + this.Width > wid) newpos.X = wid - this.Width;
        if (newpos.Y + this.Height > hei) newpos.Y = hei - this.Height;
        this.Location = newpos;
    }
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
    drag = false;
}

Như vậy hiện tại bạn có thể click vào bất cứ phần nào không trong suốt của form để di chuyển form.

3. Thêm một số phần khác

Khi loại bỏ border thì đồng nghĩa với việc không còn các nút Minimize, Maximize, Exit và box-shadow của form. Vậy ta phải thêm thủ công như sau

Thêm các nút điều khiển

Tự thiết kế hình ảnh cho các nút hoặc đơn giản chỉ là các button thông thường. Sau đó thêm sự kiện click như sau
private void btnMini_Click(object sender, EventArgs e)
{
    this.WindowState = FormWindowState.Minimized;
}

private void btnExit_Click(object sender, EventArgs e)
{
    Application.Exit();
} 

Thêm box shadow cho form 

Chúng ta phải override 1 thủ tục của form như sau:
/// <summary>
///  Drop Shadow cho form
/// </summary>
protected override CreateParams CreateParams
{
    get
    {
        CreateParams cp = base.CreateParams;
        // Bóng đổ
        cp.ClassStyle |= 0x20000;
        // Load các control cùng lúc
        cp.ExStyle |= 0x02000000; // Turn on WS_EX_COMPOSITED
        return cp;
    }
}

Phần load các control 1 lúc có thể áp dụng cho các form khác, form có nhiều control. Chẳng hạn form bạn có rất nhiều control và thường xuyên phải Visible/Invisible chúng lần lượt. Như vậy khi các control hiện lên sẽ bị trễ nhìn rất mất mỹ quan. Khi thêm phần này vào thì các control sẽ hiển thị ra cùng 1 lúc, không có hiện tượng trễ.

Thứ Tư, 18 tháng 6, 2014

[WindowForm] Các cách lưu thông tin cài đặt cho ứng dụng C# - Apps setting

Đôi khi chúng ta cần lưu trữ thông tin nào đó liên quan đến người dùng, do người dùng cài đặt. Những thông tin này phải được lưu trữ một cách lâu dài, xuyên suốt từ phiên làm việc này đến phiên làm việc khác. Tức là ta phải có cách để lưu thông tin cài đặt của người dùng

Có nhiều cách để lưu thông tin cài đặt chương trình, sau đây là một số cách phổ biến, dễ sử dụng

1. Lưu thông tin cài đặt vào Registry

Registry là bộ nhớ lưu trữ các thông tin cài đặt của hệ điều hành cũng như của các phần mềm trên nó. Do vậy ta có hoàn toàn có thể lưu trữ và lấy các thông tin trên Registry.

Ưu điểm của cách này là truy xuất nhanh, ít bị thay đổi bởi người không hiểu biết, người dùng và chỉ có lập trình viên mới có thể biết được cấu trúc, vị trí lưu trên Registry.

Nhược điểm là khi muốn lưu, đọc dữ liệu trên Registry đều phải thực thi nhiều code và yêu cầu lập trình viên phải nắm vững cấu trúc của Registry. Các thông tin cài đặt này chỉ có tác dụng với máy đã tạo ra, khi copy ứng dụng sang máy khác thì thông tin cài đặt bị mất.

2. Lưu trực tiếp trên phần mềm

Nền tảng .NET FrameWork cho phép người dùng phần mềm chỉnh sửa và lưu các thông tin cài đặt ngay trên ứng dụng. Cách lưu thông tin cài đặt này rất dễ sử dụng, lập trình. Khi thêm 1 đối tượng setting thì .NET tự động sinh ra 1 class để quản lý các thông tin setting đó.

Để bắt đầu với cách này bạn click đúp vào "Properties" trong tab "Solution Explorer". Sau đó trong tab "Settings" hãy thêm những trường cài đặt mong muốn. Ở đây .NET hỗ trợ nhiều kiểu dữ liệu: bool, string, int, datetime...
Các cách lưu thông tin cài đặt cho ứng dụng C# - Apps setting

Sau khi đã lưu các thông số này, chúng ta đọc, lưu thông tin vào như sau:
// Đọc thông tin
string MySetting = ShowGridView.Properties.Settings.Default.MySetting;

// Ghi thông tin
ShowGridView.Properties.Settings.Default.CheckBox = true;
// Lưu lại
ShowGridView.Properties.Settings.Default.Save();

3. Lưu trên file bên ngoài

Một cách lưu trữ thông tin cài đặt nữa là lưu chúng ra một file text thông thường hoặc một file được mã hóa. Với cách này cũng có nhiều kiểu lưu trữ, tùy vào cách xử lý của lập trình viên:
  • Lưu vào 1 file text thông thường đặt cùng thư mục của ứng dụng. Các thông tin sẽ được lưu trữ theo tiêu chuẩn của lập trình viên. Sau đó lập trình viên phải đọc nội dung của file và xử lý chuỗi để lấy được các thông tin đã ghi trước đó.
  • Lưu vào 1 file XML với quy cách nhất định. Với cách này khi dùng các thủ tục đọc, ghi xml thì công việc đọc, lưu thông tin cài đặt sẽ dễ dàng hơn.
  • Lưu file vào thư mục AppData của từng User. Khi đó với các User khác nhau cùng sử dụng máy tính sẽ có những thông tin cài đặt khác nhau.
  • Lưu thông tin ra file .INI. Cách này bạn có thể tham khảo tại đây.
Vì các thông tin được lưu trên một file riêng biệt nên người dùng có thể dễ dàng thay đổi, hoán chuyển các thông tin cài đặt khi cần thiết (chỉ cần việc cut/paste file ra 1 chỗ khác).

Thứ Ba, 17 tháng 6, 2014

[WindowForm] Việt hóa giao diện GridView của DevExpress

Trong các bài trước tôi đã giới thiệu tới các bạn cách làm việc với GridView, cách fill dữ liệu, Binding với GridView - Grid Control của DevExpress. GridView trở thành 1 đối tượng khá quan trọng với các dự án quản lý danh mục, và ta chắc hẳn phải sử dụng đến nó vì công dụng cũng như sự tiện lợi của DevExpress mang lại.

DevExpress thực sự là một bộ thư viện tuyệt vời với nhiều chức năng cũng như giao diện hoàn hảo. Đối với GridView, DevExpress không chỉ cung cấp khả năng làm việc tùy biến linh động nhiều chế độ mà chúng ta còn có thể tùy biến giao diện, tùy chỉnh ngôn ngữ của từng menu item trong GridView. Sau đây tôi sẽ hướng dẫn các bạn cách Việt hóa ngôn ngữ của GridView
Việt hóa giao diện GridView của DevExpress

Trong thư mục Project add một class với nội dung như sau:
class MyGridLocalizer : GridLocalizer
{
    public override string GetLocalizedString(GridStringId id)
    {
        if (id == GridStringId.FindControlFindButton)
            return "Tìm";
        if (id == GridStringId.FindControlClearButton)
            return "Bỏ";
        if (id == GridStringId.GridGroupPanelText)
            return "Kéo thả cột vào đây để gom nhóm";
        if (id == GridStringId.MenuColumnSortAscending)
            return "Sắp xếp tăng dần";
        if (id == GridStringId.MenuColumnSortDescending)
            return "Sắp xếp giảm dần";
        if (id == GridStringId.MenuColumnClearSorting)
            return "Bỏ sắp xếp";
        if (id == GridStringId.MenuColumnGroup)
            return "Gom nhóm theo cột này";
        if (id == GridStringId.MenuGroupPanelShow)
            return "Hiện hộp gom nhóm";
        if (id == GridStringId.MenuGroupPanelHide)
            return "Ẩn hộp gom nhóm";
        if (id == GridStringId.MenuGroupPanelFullExpand)
            return "Mở tất cả các nhóm";
        if (id == GridStringId.MenuGroupPanelFullCollapse)
            return "Thu tất cả các nhóm";
        if (id == GridStringId.MenuColumnUnGroup)
            return "Bỏ gom nhóm";
        if (id == GridStringId.MenuColumnRemoveColumn)
            return "Ẩn cột này";
        if (id == GridStringId.MenuColumnShowColumn)
            return "Hiện cột này";
        if (id == GridStringId.MenuColumnColumnCustomization)
            return "Tùy chỉnh cột";
        if (id == GridStringId.CustomizationCaption)
            return "Tùy chỉnh cột";
        //if (id == GridStringId.CustomizationColumns)
        //    return "Kéo và thả cột vào đây để tùy chỉnh";
        //if (id == GridStringId.CustomizationBands)
        //    return "Kéo và thả cột vào đây để tùy chỉnh";
        //if (id == GridStringId.CustomizationFormBandHint)
        //    return "Kéo và thả cột vào đây để tùy chỉnh";
        if (id == GridStringId.CustomizationFormColumnHint)
            return "Kéo và thả cột vào đây để tùy chỉnh";
        if (id == GridStringId.MenuColumnBestFit)
            return "Căn chỉnh";
        if (id == GridStringId.MenuColumnBestFitAllColumns)
            return "Căn chỉnh tất cả";
        if (id == GridStringId.MenuColumnFilterEditor)
            return "Cài đặt lọc";
        //if (id == GridStringId.MenuColumnFilter)
        //    return "menu filter";
        if (id == GridStringId.PopupFilterCustom)
            return "(Tùy chọn)";
        if (id == GridStringId.PopupFilterAll)
            return "(Tất cả)";
        if (id == GridStringId.FilterPanelCustomizeButton)
            return "Sửa lọc";
        if (id == GridStringId.FilterBuilderCaption)
            return "Cài đặt lọc";
        if (id == GridStringId.FilterBuilderOkButton)
            return "Đồng ý";
        if (id == GridStringId.FilterBuilderApplyButton)
            return "Áp dụng";
        if (id == GridStringId.FilterBuilderCancelButton)
            return "Hủy bỏ";
        if (id == GridStringId.MenuColumnAutoFilterRowShow)
            return "Hiện hàng lọc tự động";
        if (id == GridStringId.MenuColumnAutoFilterRowHide)
            return "Ẩn hàng lọc tự động";
        if (id == GridStringId.MenuColumnFilterMode)
            return "Chế độ lọc";
        if (id == GridStringId.MenuColumnFilterModeDisplayText)
            return "Văn bản";
        if (id == GridStringId.MenuColumnFilterModeValue)
            return "Giá trị";
        if (id == GridStringId.CustomFilterDialogCancelButton)
            return "Hủy bỏ";
        //if (id == GridStringId.CustomFilterDialog2FieldCheck)
        //    return "2FieldCheck";
        if (id == GridStringId.CustomFilterDialogCaption)
            return "Hiển thị những hàng có:";
        //if (id == GridStringId.CustomFilterDialogClearFilter)
        //    return "Clear";
        if (id == GridStringId.CustomFilterDialogEmptyOperator)
            return "(Chọn phép toán)";
        if (id == GridStringId.CustomFilterDialogEmptyValue)
            return "(Điền giá trị)";
        if (id == GridStringId.CustomFilterDialogFormCaption)
            return "Tùy chọn lọc tự động";
        //if (id == GridStringId.CustomFilterDialogHint)
        //    return "fil hint";
        if (id == GridStringId.CustomFilterDialogOkButton)
            return "Đồng ý";
        if (id == GridStringId.CustomFilterDialogRadioAnd)
            return "Và";
        if (id == GridStringId.CustomFilterDialogRadioOr)
            return "Hoặc";
        return base.GetLocalizedString(id);
    }
}


Trong form chính (cần Việt hóa) ta thêm đoạn sau vào hàm khởi tạo class:
// Tùy biến giao diện Grid
GridLocalizer.Active = new MyGridLocalizer();

Lưu ý trong cả class và form đều phải:
using DevExpress.XtraGrid.Localization;

Với cách làm tương tự các bạn có thể Việt hóa các string khác của Dev.

Ví dụ: XtraMessageBox - một điều khiển khá quen thuộc các bạn có thể tham khảo tại đây

Chúc thành công.

Thứ Sáu, 13 tháng 6, 2014

[WindowForm] Làm việc với GridView - Grid Control của DevExpress

Trong bài "[LINQ] LinQ là gì và tại sao nên dùng LinQ?" tôi đã giới thiệu đến các bạn sơ qua về LINQ và Binding, trong đó có 1 thành phần quan trọng đó là GridView của DevExpress. GridView có vai trò rất quan trọng trong việc hiển thị các dữ liệu dạng bảng, danh sách trong các phần mềm quản lý danh mục... và là thành phần không thể thiếu trong Binding dữ liệu.
Ở lần trước tôi chỉ giới thiệu các bạn về cách kéo thành phần GridView tự động từ cửa sổ "Data Source" phục vụ việc Binding, trong bài này tôi sẽ hướng dẫn cách làm việc với GridView thủ công, tùy chỉnh giao diện của nó - một trong những tính năng vượt trội, thành công lớn của DevExpress.

I. Tạo và thiết lập nguồn dữ liệu cho GridView

Tạo đối tượng GridView - Grid Control

Để tạo 1 đối tượng các bạn search trong toolbox "GridControl" và kéo vào form
Làm việc với GridView - Grid Control của DevExpress

Thiết lập nguồn dữ liệu cho GridView

Bây giờ chúng ta sẽ khai báo nguồn dữ liệu (data source) cho GridView, để gridview tự động lấy các giá trị và fill vào. Đây là tiện ích lớn nhất của việc Binding: có thể tự động lấy các dữ liệu điền vào grid và liên kết với phần detail
Để chọn data source cho gridView ta click vào hình tam giác ở góc trên cùng bên phải GridView. Trong phần "Choose Data Source" ta chọn data source đã có sẵn hoặc click chọn "Add Project Data Source" nếu chưa có.
Làm việc với GridView - Grid Control của DevExpress

Khi chọn Add Project Data Source các bạn có thể chọn thêm 1 database, service, object, sharepoint nhưng bạn nên chọn object để nó có thể kết nối tới file ".dbml" đã tạo trong phần giới thiệu LINQ.
Làm việc với GridView - Grid Control của DevExpress

Sau khi chọn object ta sẽ chọn bảng/view/đối tượng làm datasource cho GridView. GridView sẽ tạo ra các cột tương tự như các trường của bảng/view/đối tượng đã chọn.
Làm việc với GridView - Grid Control của DevExpress

Bây giờ chỉ cần thêm một vài câu lệnh để set nguồn dữ liệu thực cho datasource này. Việc này đã được giới thiệu trong bài giới thiệu LINQ.

Lưu ý:

  • Data Source cho GridView không chỉ là 1 table/view thực trong database mà có thể là 1 object ảo các bạn tạo ra trong file ".dbml" hoặc 1 đối tượng của Dataset... Với những object ảo này các bạn có thể tùy chỉnh, xử lý dữ liệu cho GridView.

II. Phần giao diện của GridView

Để tùy chỉnh giao diện, dữ liệu trong các hàng/ô của GridView ta có thể xem trong cửa sổ "Properties" tương ứng của GridView hoặc đơn giản hơn có thể mở giao diện tùy chỉnh của DevExpress:
Làm việc với GridView - Grid Control của DevExpress

Trong phần "Run Designer" này các bạn có thể tùy chỉnh một số thuộc tính của header, phần hiển thị của các ô, việc sửa đổi dữ liệu trong ô, sắp xếp theo cột, thay đổi màu sắc, font chữ... và cả các kiểu hiển thị dữ liệu trong từng ô. Chẳng hạn:

1. Tùy chỉnh giao diện

Thêm/bớt, thay đổi thứ tự các cột

Làm việc với GridView - Grid Control của DevExpress

Với "gridView1" ta vẫn có các sự kiện như ở GridView thông thường như: RowClick, RowCellClick...
Làm việc với GridView - Grid Control của DevExpress


Tùy chỉnh Layout

Làm việc với GridView - Grid Control của DevExpress

Thay đổi font chữ, căn lề của header, ô trong từng cột


Ấn giữ Ctrl để chọn nhiều cột 1 lúc. Các thuộc tính trong phần AppearanceCell & AppearanceHeader như font, Col Name, Text Options, Filter, Allow Edit, Visible... 

Phân biệt hàng chẵn, lẻ

Trong tab Views, phần Appearance > EvenRow, OddRow ta có thể thay đổi một số thuộc tính như màu nền, font chữ, text options... như ở phần header:
Làm việc với GridView - Grid Control của DevExpress

Kéo xuống phần OptionsView, chọn EnableApearanceEvenRow hoặc EnableApearanceOddRow bằng true
Làm việc với GridView - Grid Control của DevExpress

2. Kiểu dữ liệu hiển thị trong ô

Mặc định khi ta chọn Data Source cho GridView thì các cột trong GridView sẽ có 1 kiểu hiển thị dữ liệu tương ứng với kiểu dữ liệu của data source. Chẳng hạn nếu ở kiểu dữ liệu data là nvarchar thì control edit dữ liệu là textEdit (của Dev)... 
Giả sử bây giờ ta có 1 cột là idNhanVien nhưng ta muốn nó hiển thị là Họ tên của Nhân viên thì phải làm thế nào??!

Bằng cách dùng bảng NhanVien để tham chiếu từng idNhanVien với HoTen tương ứng ta sẽ lấy được họ tên của nhân viên ứng với id. Chắc hẳn việc này là rất khó khăn nếu ta dùng code thông thường, không dùng Binding vì phải tương tác qua lại giữa idNhanVien và HoTen trong tất cả các công việc sau này. Khi đã có Binding + DevExpress thì việc đó trở lên tương đối easy.

Ở Run Desinger, tab Columns, với cột tương ứng ta  chỉ cần thêm 1 đối tượng "ColumnEdit" tương ứng với kiểu dữ liệu, trường thông tin muốn hiển thị. Chẳng hạn muốn hiển thị họ tên của nhân viên, vì đây là trường có sẵn (chỉ việc select), số lượng có thể rất nhiều nên ta chọn ColumnEdit là một đối tượng SearchLookupEdit (giống kiểu ComboBox nhưng có tìm kiếm của Dev). Hay như với cột ghi thông tin ghi chú (độ dài nhỏ) thì ta có thể chọn là TextEdit để sau này có thể sử dụng các thuộc tính của TextEdit như MaxLength, Mask...

Quay trở lại với bài toán của chúng ta, sau khi đã thêm đối tượng SearchLoopupEdit cho cột idNhanVien thì ta có 1 đối tượng SearchLookupEdit thông thường, có thể đặt Data Source cho nó, trường hiển thị (DisplayMember), trường giá trị tương ứng (ValueMember). Ở đây ta đặt Data Source là 1 đối tượng trong file ".dbml" tham chiếu đến bảng NhanVien, DisplayMember là HoTen, ValueMember là idNhanVien.
Làm việc với GridView - Grid Control của DevExpress

Sau khi đặt ...bindingSource.DataSource = bla bla; thì kết quả được như này
Làm việc với GridView - Grid Control của DevExpress

Như vậy đã hiển thị được họ tên nhân viên và chức vụ tương ứng mà không cần dùng quá nhiều code, trong khi đó khi cần thiết vẫn có thể lấy được các giá trị id một cách dễ dàng.

Bây giờ nảy sinh một vấn đề nữa là khi ta edit cái SearchLookUp vừa tạo ở trên nó có giao diện không đẹp lắm, đặc biệt phiền phức nếu cái bảng nhân viên có vài chục trường mà ta chỉ muốn hiển thị một vài trường như họ tên, quê quán...
Như này chẳng hạn
Làm việc với GridView - Grid Control của DevExpress

Tất nhiên các kiểu hiển thị này chỉ cần quan tâm khi ta để dữ liệu ở cột dạng AllowEdit.

Để tùy chỉnh cũng không có gì quá phức tạp, chỉ là trên cái giao diện rối rắm vì quá nhiều chức năng của DevExpress khiến ta bối rối. Trong phần Columns > cột cần thay đổi > ColumnEdit (vừa tạo ở trên) > View
Làm việc với GridView - Grid Control của DevExpress

Để đơn giản ta click vào biểu tượng dấu 3 chấm "...". Nó sẽ ra một cửa số mới để tùy chỉnh cái SearchLookupEdit này tương tự với cái tùy chỉnh GridView ta làm việc từ đầu đến giờ.
Ta cũng có thể tùy chỉnh Layout, thêm/bớt cột, đặt caption, thay đồi font chữ header, phân biệt hàng chẵn/lẻ...
Làm việc với GridView - Grid Control của DevExpress

Và kết quả cuối cùng:
Làm việc với GridView - Grid Control của DevExpress

Enjoy!!!