Hiển thị các bài đăng có nhãn Lập trình C#. Hiển thị tất cả bài đăng
Hiển thị các bài đăng có nhãn Lập trình C#. Hiển thị tất cả bài đăng

Thứ Sáu, 17 tháng 3, 2017



Chào các bạn!

Hôm nay mình xin trở lại với chuỗi bài hướng dẫn về Lập trình hướng đối tượng OOP.  Trong C#, một class con có thể chứa các hàm cùng tên với các hàm trong class mà nó kế thừa. Điều đó là tốt đối với lập trình viên bởi họ có thể tận dụng điều đó để cài đặt mã nguồn của mình theo OOP, tuy nhiên nó đôi khi sẽ gây nhầm lẫn.
Bạn có thể định rõ ra cách mà hàm đó tương tác, hoạt động như thế nào bằng cách sử dụng từ khóa new hoặc override. 



Sự khác nhau được mô tả trong bài dưới đây:

Trong một chương trình Console, khai báo hai class: BaseClass và DerivedClass kế thừa từ BaseClass.


Trong hàm Main, khai báo các biến bc, dc, bcdc tương tướng với:
  • bc là đối tượng kiểu BaseClass, và mang giá trị kiểu BaseClass
  • dc là đối tượng kiểu DerivedClass, và mang giá trị kiểu DerivedClass
  • bcdc là đối tượng kiểu BaseClass và mang giá trị kiểu DerivedClass: Đây là biến cần chú ý tới nhiều nhất!
Bởi vì bc và bcdc điều có kiểu dữ liệu là BaseClass, nó chỉ nó thể truy cập trực tiếp đến Method1() (ngoại trừ khi bạn dùng casting ép kiểu nó về DerivedClass - việc này là có thể được).  Biến dc có thể truy cập đến cả Method1() và Method2(). Những mối quan hệ trên được thể hiện như hình bên dưới:


Ta thấy kết quả là những gì có thể đoán trước được. Tiếp tục ta thêm một hàm Method2() vào BaseClass. Bây giờ ta đã có hai hàm trùng tên, một nằm ở class cha và một nằm ở class con.


Bởi vì BaseClass bây giờ đã có Method2(), ta sẽ gọi được hàm Method2() ở các biến mạng kiểu là BaseClass là bc và bcdc:


Khi bạn build project, bạn sẽ thấy một thông báo cảnh cáo. Dòng warning nói rằng Method2() ở DerivedClass "che" đi Method2() ở BaseClass. Bạn cũng được khuyên nên sử dụng từ khóa new ở phần cài đặt/định nghĩa của Method2() nếu bạn muốn tạo ra kết quả tượng tự như vậy. Hoặc bạn có thể đổi tên Method2() để resolve warning đó, nhưng nó không phải lúc nào cũng tốt.

Trước khi thêm từ khóa new, chạy chương trình và xem output tạo ra bởi những hàm đã gọi, bạn sẽ nhận được như sau:


Hãy chú ý đến những dòng được mình highlight, dòng thứ 2 được bc mang kiểu BaseClass nên việc nó chỉ gọi hàm Method2() của lớp cha cũng không có gì là lạ. Ở hai dòng cuối, hành vi mặc định của nó được giữ nguyên, nên nó ưu tiên gọi hàm từ lớp cha dù ở lớp con cũng có một hàm Method2() cùng tên.
Từ khóa new "bảo tồn" mối quan hệ mà tạo ra kết quả ban đầu, nhưng nó vô hiệu hóa đi các cảnh bảo từ IDE. Các biến có kiểu là BaseClass vẫn giữ nguyên hành vi của nó và tiếp tục truy cập các hàm/thuộc tính của BaseClass, và các biến có kiểu là DerivedClass tiếp tục tuy cập vào các hàm/thuộc tính của DerivedClass đầu tiên, sau đó mới suy xét đến những thành phần mà nó kế thừa từ BaseClass.

Ví dụ: 
Ta có thể thêm từ khóa new trước hoặc sau public

Chạy lại chương trình để chắc rằng output không thay đổi. Cũng để thấy rằng những warnings từ IDE không còn xuất hiện nữa.
Bằng cách sử dụng từ khóa new, bạn thầm khẳng định rằng bạn biết hàm/thuộc tính đó "che" đi hàm/thuộc tính mà nó kế thừa từ chính lớp cha của nó. Để biết thêm thông tin về ẩn tên (name hiding) trong kế thừa, xem new Modifier

Mặc khác, để tạo ra 1 hành vi tương phản lại ở trên, ta sử dụng từ khóa override. Thêm hàm sau kèm từ khóa override vào DerivedClass và từ khóa virtual vào tên hàm ở BaseClass
Từ khóa override có thể đặt trước hoặc sau public


Chạy lại chương trình, ta chú ý sự khác nhau giữa 2 dòng cuối của output với nhau, và so với output của lần test trước. Qua đó thấy rõ sự khác nhau của override và new.


Ta thấy khi gọi hàm Method1() trùng tên giữa 2 lớp, mang từ khóa override từ biến bcdc lần này nó không gọi hàm của lớp cha nữa, mà chuyển sang gọi hàm của lớp con. Tuy nhiên cũng là gọi hàm trùng tên Method2(), không có từ khóa override thì nó sẽ trở lại hành vi mặc định là gọi hàm từ lớp cha.

Việc sử dụng từ khóa override làm cho biến bcdc có thể truy cập đến Method1() của lớp con DerivedClass. Thông thường, đây mới là hành vi được các lập trình viên chúng ta mong muốn khi sử dụng OOP và kế thừa. Bạn luôn muốn những object được khởi tạo như một thể hiện của lớp con sử dụng các hàm từ chính lớp con đó chứ không phải những hàm cùng tên, được cài đặt từ trước ở lớp cha. 

Tuy nhiên hành động mặc định của C# lại ưu tiên lớp cha hơn :D. Vậy nên bạn có thể đạt được mong muốn của mình bằng cách phải dùng từ khóa override để extend và ghi đè những hàm của lớp cha bằng những hàm mới cùng tện trong lớp con.

Full source code:


Đến đây các bạn đã hiểu về sự khác nhau giữa new và override trong C# chưa nào? 
Bạn có thể tham khảo thêm ví dụ sau đây để biết rõ hơn về chúng. Mọi thắc mắc xin để lại bình luận bên dưới nhé.

Chào các bạn, chúc các bạn học tốt!

Thứ Hai, 19 tháng 12, 2016


Chào các bạn,

Đã lâu rồi mình không viết bài về C# nhỉ :D, hôm nay nhân lúc đang làm đồ án môn Thiết kế phần mềm, cần sử dụng OOP, inheritance,.. khá nhiều, mình xin viết một article nho nhỏ về hàm dựng (constructor) trong tính kế thừa của C#.



Theo nguyên tắc, khi khởi tạo đối tượng của lớp con, thì hàm dựng (constructor) của lớp cha sẽ được gọi trước, sau đó mới tới đổi tượng của lớp con.

Ví dụ mình có class Base và Child kế thừa từ lớp Base như sau:


Thì khi Run, chương trình sẽ cho kết quả như sau:


Rõ ràng constructor của lớp Base đã được gọi trước! 

Chúng ta có thể kiểm tra các trường hợp khác:
 - Cho lớp Base thành abstract.
 - Sửa lại hàm Main, khởi tạo đối tượng bằng Child c = new Child();

Tất cả đều cho kết quả tương tự.

Chúng ta tiếp tục thử một trường hợp đặc biệt khác, thêm một constructor mới chứa tham số vào class Base và Child như sau:


Run chương trình, chúng ta được kết quả sau:


Ở đây bạn thấy, dù chúng ta tạo đối tượng với constructor có tham số, thì constructor cơ bản của lớp Base luôn được gọi.
Bây giờ nếu bạn xóa đi constructor cơ bản (không tham số) của lớp Base và Run chương trình thì sẽ bị lỗi ngay lập tức.


Từ đó ta rút ra các kết luận sau:

Về vấn đề lỗi khi xóa constructor cơ bản của lớp Base: Khi một class được tạo ra, nếu class đó chưa có constructor, Visual C# sẽ tự động generate một constructor mặc định (không tham số) cho chúng ta, vì nếu không làm vậy chúng ta sẽ không thể tạo một object mới thuộc class đó rồi :D. Tuy nhiên nếu bạn tạo thêm một constructor khác có tham số, và xóa constructor mặc định cơ bản đi, thì Visual C# sẽ cho rằng class của bạn đã có thể tự tạo một object mới và sẽ không generate constructor mặc định. Điều đó đồng nghĩa với việc các object được tạo bằng cách gọi "new Base()" sẽ không thể khởi tạo.

Về vấn đề chính về constructor trong kế thừa mình muốn nói là khi bạn khởi tạo một đối tượng lớp con Child, thì C# sẽ automatically gọi constructor mặc định-không tham số của lớp cha Base trước, sau đó mới gọi constructor của lớp con (constructor nào của lớp con thì còn tùy mình new đối tượng với tham số gì :D).


Tại sao lại như vậy?

Theo ý kiến chủ quan của cá nhân mình, thì bạn cứ tưởng tượng lớp con Child là một "cụ thể hóa" của một lớp cha, giống như một chiếc xe, trước khi thành một chiếc xe nó phải qua công đoạn lắp ráp khung xe, thì KhungXe đó chính là lớp cha. Mà để tạo khung xe thì phải dùng constructor của KhungXe, trong đó sẽ gọi các hàm ráp, hàn, bắt ốc,... Sau khi đã xong phần khung xe, ta gọi constructor của XeMay gọi các hàm gắn bánh, gắn yên xe,.. giúp tạo thành một chiếc xe hoàn chỉnh.
Vậy thứ tự gọi thực sự logic và thực tế đúng không nào?

Nếu bạn muốn gọi constructor có tham số cụ thể của lớp cha theo ý của mình thì sử dụng tự khóa "base" như sau:



Trên là một số kiến thức tổng quát về Lập trình hướng đối tượng (OOP) cho các bạn nào lỡ quên :D.
Minh xin nói luôn một cách tổng quát, trong Java thì hàm dựng của lớp cha cũng sẽ tự động được gọi khi khởi tạo đối tượng của lớp con. Các bạn có thể tham khảo tại đây.



Cuối cùng, mình có một câu hỏi cho các bạn, có cách nào để tạo một đối tượng thuộc lớp con mà không cần gọi hàm dựng (constructor) của lớp cha không? 

Chào các bạn, chúc các bạn học tốt!


Thứ Ba, 5 tháng 4, 2016


Chào các bạn!

Nhiều bạn thắc mắc muốn thao tác với ảnh bằng C# Winform thì làm như thế nào, hôm nay mình sẽ hướng dẫn các bạn cách kết hợp hai control cơ bản là PictureBox và OpenFileDialog để làm một chương trình "Picture Viewer" trong C#
Đầu tiên các bạn tìm hiểu sơ lược về hai control này nhé.




PICTURE BOX TRONG C#

PictureBox là một control khá hữu dụng của C# .NET. Nó cung cấp một vùng hình chữ nhật để chèn ảnh bất kỳ và kích cỡ có thể tùy chỉnh bằng nhiều cách khác nhau.
Picturebox hỗ trợ nhiều định dạng ảnh: BMP, GIF, JPEG, EXIF, PNG và TIFF, ICO... (các định dạng được GDI+ hỗ trợ)
PictureBox có thể lấy ảnh từ ổ cứng của bạn hoặc từ Internet

Đầu tiên mình sẽ hướng dẫn các bạn chèn ảnh từ ổ cứng:
Mình sẽ dùng ảnh PNG trong ví dụ bên dưới, các định dạng khác cũng làm tương tự.

Tại sao chúng ta lại phải thiết lập thuộc tính Width và Height? Vì ảnh của chúng ta và kích cỡ của PictureBox có thể khác nhau rất nhiều, nếu như không thiết lập thì ảnh có thể sẽ bị crop. Ngược lại muốn crop ảnh theo kích cỡ mong muốn thì cứ thiết lập thuộc tính Width, Height của PictureBox

Picturebox cũng có các thuộc tính tương tự như các control cơ bản khác, tuy nhiên có một số thuộc tính mới cần nói như SizeMode.
Thay vì thiết lập thuộc tính Width và Height của PictureBox, hoặc hình ảnh. Chúng ta có thể thiết lập nhanh bằng một số tùy chọn .NET cung cấp sẵn:

Chúng ta còn các SizeMode khác như (Normal, Zoom: căng ảnh nhưng duy trì tỉ lệ aspect ratio, AutoSize: tự thiết lập size của pictureBox bằng với size của ảnh, CenterImage: Center ảnh vào trung tâm PictureBox, StretchImage: căng ảnh lên theo 2 chiều cho vừa với khung pictureBox)

Tiếp theo là chèn ảnh từ Internet. Ví dụ trên mình đã dùng thuộc tính ImageLocation để chèn ảnh bằng địa chỉ của nó. Vậy thì địa chỉ hình ảnh trên Internet thì sao nhỉ?
Chúng ta thử gán nhanh cho thuộc tính ImageLocation trong cửa sổ properties với giá trị: https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_4AjKZmor_E-j353JRuB0l1GGX47HwNwZLHCzfjmwP9QpvTLE80Z-c9D5nmhcmaRP3O1Z_dNYmEyC2DY8Zw3VUZ8yFtrs50LGOG1lgLXnSugYDxLeKlb3Mt0h0s4YD7EKGmgH3Rr9mpg/s1600/cooltext125983511023412.png. Sau đó chạy thử chương trình lên và kết quả sẽ là:


Về phần sự kiện của PictureBox thì chúng ta cũng có các sự kiện cơ bản như các control khác (Click, Mouse Hover,...). Vậy là xong phần PictureBox, chúng ta cùng sang control thứ hai cần thiết để hoàn thành chương trình này.


OPEN FILE DIALOG TRONG C#

OpenFileDialog (OFD) cho phép người dùng browse một thư mục hoặc tệp tin. Là control thường thấy trong rất nhiều ứng dụng. Nhất là các gói cài đặt thường cho bạn chọn thư mục để cài.

Để cài đặt một OFD các bạn kéo nó ra từ thanh Toolbox, nhóm Dialogs.
Thường thì chúng ta sẽ thiết lập các thuộc tính cho OFD ở ngay trong khung Properties. OFD cũng có thuộc tính Name, Title, Tag,.. như các control khác. Tuy nhiên một số thuộc tính mới như:
- FileName: Tên mặc định của File. Nếu các bạn gõ vào đây "fileName1" thì khi mở hộp thoại "fileName1" sẽ đặt mặc định trong ô FileName. Vậy nên các bạn nên xóa và để trống thuộc tính này
- Filter: Bộ lọc file. Thông thường ta chỉ cần một số loại file nhất định, nhưng nếu thư mục có quá nhiều file khác nhau thì việc tìm kiếm sẽ mất nhiều thời gian. Nên chúng ta có thể thiết lập thuộc tính Filter để lọc ra các loại file mong muốn.
Ví dụ: ofd.Filter = "Windows Bitmaps|*.bmp|JPEG Files|*.jpg"
Cứ theo định dạng mô tả | *.đuôi tệp tin. Giữa những loại tệp tin với nhau cũng là một dấu gạch đứng |.
- CheckFileExist, CheckPathExist: Các bạn để mặc định là true để OFD kiểm tra file và đường dẫn có hợp lệ, tồn tại không.
- InitialDirectory: Thư mục mặc định mà khi OFD được show ra sẽ nằm ở đó.
- MultiSelect: Nếu các bạn muốn chọn nhiều file một lúc thì cho bằng true.
- ...

Để mở hộp thoại OFD, chúng ta cần một button và thiết lập cho nó sự kiện Click để chạy code show OFD.

DIALOG RESULT

DialogResult là một biến kiểu Enum, dùng để nhận giá trị trả về của var.ShowDialog(). Để kiểm tra xem người dùng vừa click nút nào, dự định làm gì.
DialogResult chứa các giá trị như: OK, Cancle, Ignore, Try, Yes, No,...

Vậy thì tiếp theo làm sao để ta lấy được hình ảnh từ OFD? Chung ta sẽ lấy đường dẫn của ảnh vừa chọn bằng thuộc tính FileName của OFD.

 Image img = Image.FromFile(openFileDialog1.FileName); 

Vậy là chúng ta đã học xong được tất cả các chức năng chính của PictureBox và OpenFileDialog rồi. Giờ chỉ còn kết hợp nó để làm chương trình xem ảnh thôi :D

Mình sẽ cung cấp code mẫu ở đây luôn. Ai có gì không hiểu thì bình luận hoặc pm trực tiếp mình qua facebook/email nhé

Chúc các bạn học tốt! Chào và hẹn gặp lại


Thứ Sáu, 1 tháng 4, 2016


Chào các bạn!

Chắc hẳn qua một thời gian dài học C# cùng với blog các bạn cũng đã từng nhiều lần sử dụng event trong chương trình của mình nhỉ?
Ví dụ cơ bản với một sự kiện nhận biết chuột vừa được click xuống
private void btn_MouseDown(object sender, MouseEventArgs e)
{
//Do something...
}

Các bạn có bao giờ thắc mắc các tham số object sender và MouseEventArgs e là gì không?
Đó là những tham số của event, được tạo và gán giá trị bởi Visual C#. 

THAM SỐ ĐẦU TIÊN: object sender
Sender mang kiểu dữ liệu object dùng chung, tổng quát.
Sender chứa một tham chiếu tới control/object đã gây ra event. Chúng ta có thể ép kiểu sender lại trở thành control/object để xử lý
Ví dụ: 
//Thay đổi text của button được click

protected void btn_Click (object sender, EventArgs ea)
{

Button btn = sender as Button;
if(btn != null)
{
btn.Text = "I was clicked!";
}
}

THAM SỐ THỨ HAI: MouseEventArgs e
Tham số này là nơi hành động thực sự xảy ra, tham số e cũng chứa một đối tượng, nhưng là kiểu cụ thể của một loại các tham số của mouse event, chứa các dữ liệu của event
Vậy thì MouseEventArgs sẽ chứa gì?
Bạn có thể tham khảo EventArgs Class từ MSDN hoặc các nguồn khác để xem thông tin, hoặc gọi biến e ra, rồi ấn dấu chấm "." để xem các thuộc tính/phương thức của e.





Trong đó:
 - Clicks: trả về số lần người dùng đã click chuột vào control đó
 - Button: trả về nút đã được nhấp (trái, giữa, phải)
 - X, Y: trả về tọa độ x,y mà con trỏ đang ở lúc sự kiện khởi chạy
 - ...

Mỗi event handler đều có các tham số riêng cho nó. Ví dụ btn_Click và btn_MouseClick sẽ có hai tham số EventArgs và MouseEventArgs khác nhau. Nên tùy theo nhu cầu sử dụng mà ta sẽ gọi sự kiện cho hợp lý

Trên là những gì cơ bản về tham số của event, các bạn có thắc mắc thì bình luận mình sẽ giải đáp. 
Chào và chúc các bạn học tốt!!


Thứ Sáu, 18 tháng 3, 2016


Chào các bạn!

Đã lâu mình không viết bài trở lại, chắc cũng 3 tháng rồi :D nhưng traffic của blog vẫn đều đều ~400 bạn truy cập/ngày. Cảm ơn các bạn đã tin tưởng và ủng hộ blog, mình hứa sẽ cho ra thêm nhiều bài viết hay và bổ ích.

Gần đây mình có nhận được một yêu cầu của một bạn theo dõi blog, bạn ấy muốn làm một chương trình C# để thay đổi giờ hệ thống.
Hôm nay mình sẽ hướng dẫn các bạn viết ra chương trình đó. Nghe có vẻ rất dễ đúng ko?




Để thay đổi System Time bạn phải can thiệp vào hệ thống, trong C# bạn có thể dùng cách P/Invoke hàm SetSystemTime() theo WIN32 API có sẵn.
Đầu tiên bạn chuẩn bị cho mình một struct như sau:
private struct SYSTEMTIME
{
public ushort Year;
public ushort Month;
public ushort DayOfWeek;
public ushort Day;
public ushort Hour;
public ushort Minute;
public ushort Second;
public ushort Milliseconds;
}

Struct này tương tự theo cấu hình của class DateTime mà giờ hệ thống đang sử dụng :D
Sau đó các bạn thêm extern method này vào:
//Method set giờ hệ thống

[DllImport("kernel32.dll", SetLastError = true)]
private extern static uint SetSystemTime(ref SYSTEMTIME lpSystemTime);

//


Đây là method sử dụng thư viện động "lõi hệ thống 32" (kernel32.dll) của windows, và gây những tác động lên nó. Lưu ý để sử dụng DllImport thì bạn cần thêm namespace sau:
using System.Runtime.InteropServices; 

Namespace này dùng để chứa class DllImport - dùng chỉ ra rằng những phương thức này được tiếp cận bởi những DLL không được chương trình quản lý với dạng 1 điểm đầu vào tĩnh (static entry point)

Sau khi using namespace, thêm method, các bạn bắt đầu gọi method đó. Các bạn có thể tạo 1 button để xử lý sự kiện onClick cho button đó để gọi hàm :D
private void submit_btn_Click(object sender, EventArgs e)
{
//Tạo instance
SYSTEMTIME s = new SYSTEMTIME();

//Gán các giá trị (ở đây mình gán ngẫu nhiên)
s.Year = (ushort)2009;
s.Month = (ushort)12;
s.DayOfWeek = (ushort)3;
s.Day = (ushort)4;
s.Hour = (ushort)5;
s.Minute = (ushort)6;
s.Second = (ushort)7;
s.Milliseconds = (ushort)8;

//Gọi extern method đã thêm ở trên và xem kết quả :D
SetSystemTime(ref s);
}

Các bạn có thể dùng 1 Control DateTimePicker để lấy số liệu nhập vào, phân tích ra và gán cho giờ hệ thống
//Lấy dữ liệu của control DateTimePicker xuống lưu vào biến
DateTime result = dateTimePicker1.Value;

SYSTEMTIME s = new SYSTEMTIME();

//Phân tích ra và lưu vào struct
s.Year = (ushort)result.Year;
s.Month = (ushort)result.Month;
s.DayOfWeek = (ushort)result.DayOfWeek;
//v.v...

Cuối cùng các bạn build chương trình ra, tìm đến thư mục */obj/Debug. Chạy file thực thi *.exe với quyền admin (Run as administrator). Lưu ý phải chạy với quyền admin thì mới thành công, vì các hàm của WIN32 API cần quyền admin để thay đổi/can thiệp vào dll hệ thống


LƯU Ý

Một số bạn khi thay đổi ngày thì chương trình chạy ok, nhưng khi thay đổi giờ thì chương trình chạy sai. Đó là do hàm SetSystemTime() của Win32 API nhận vào giá trị UTC, rồi tự convert lên Local Time (+7). Nên chương trình mình sẽ sai. Các bạn tham khảo giải pháp Work around của mình. Các bạn nào có ý hay hơn hay inbox cho page mình nhé :D 


_______________________________________________________________________

Đừng nên làm những chương trình thay đổi giờ hệ thống như thế này, bởi vì nó sẽ:

1) Làm phiền người sử dụng, nếu 1 chương trình mình dùng mà làm thay đổi giờ hệ thống máy tính thì cực kì khó chịu
2) Có thể làm break các ứng dụng khác, làm thay đổi thông tin trial của một số phần mềm.

Chúc các bạn thành công!

Thứ Bảy, 9 tháng 1, 2016


Chào các bạn!

Hôm nay mình xin chia sẻ một số từ khóa để các bạn có thể học lập trình C# từ cơ bản đến nâng cao.




  • C# - Overview
  • C# - Environment
  • C# - Program Structure
  • C# - Basic Syntax
  • C# - Data Types
  • C# - Type Conversion
  • C# - Variables
  • C# - Constants
  • C# - Operators
  • C# - Decision Making
  • C# - Loops
  • C# - Encapsulation
  • C# - Methods
  • C# - Nullables
  • C# - Arrays
  • C# - Strings
  • C# - Struct
  • C# - Enums
  • C# - Classes
  • C# - Inheritance
  • C# - Polymorphism
  • C# - Operator Overloading
  • C# - Interfaces
  • C# - Namespaces
  • C# - Preprocessor Directives
  • C# - Regular Expressions
  • C# - Exception Handling
  • C# - File I/O
  • C# - Advanced Tutorial
  • C# - Attributes
  • C# - Reflection
  • C# - Properties
  • C# - Indexers
  • C# - Delegates
  • C# - Events
  • C# - Collections
  • C# - Generics
  • C# - Anonymous Methods
  • C# - Unsafe Codes
  • C# - Multithreading


Các bạn cứ học theo từng mức độ, search các từ khóa này mà học thì sẽ dễ học và tiện nắm bắt các kiến thức hơn
Tham khảo các từ khóa tương tự với ngôn ngữ Java tại: Trình tự học Java Core từ cơ bản đến nâng cao

Chúc các bạn thành công!



Thứ Tư, 2 tháng 12, 2015


Chào các bạn!
Hôm nay mình xin giới thiệu với các bạn cách thêm control động hay còn gọi là dynamic control trong C# windows form.


GIỚI THIỆU

Trong nhiều chương trình, đôi khi bạn cần tạo thêm một control mới ngay trong lúc chương trình đang thực thi, hoặc xóa một control hiện có sẵn.
Vậy thì làm thế nào? Lấy đâu ra giao diện thiết kế của Visual Studio để thêm?
Khi đó ta phải sử dụng control động (Dynamic controls)

Dynamic control trong lập trình C#

Visual Studio .NET không có mảng chứa control như Visual Basic 6.0. Nhưng tin vui là bạn vẫn có thể tự thiết lập để làm những điều tương tự. Các ưu điểm của C# Dynamic controls là chúng có thể được tạo ra để phản hồi với cách mà người dùng tương tác với các ứng dụng. Các control được thêm vào trong lúc chương trình thực thi thường là textbox hoặc button. Nhưng tất nhiên, hầu như tất cả các C# control đều có thể được tạo ra như là một dynamic control


LÀM THẾ NÀO ĐỂ TẠO CONTROL ĐỘNG TRONG C#

  • Đầu tiên các bạn cần khai báo một đối tượng Control (nhớ using các namespace cần thiết cho control cần dùng)
  • Thiết lập các thuộc tính cần thiết cho đối tượng vừa khai báo như: Vị trí (top, left, bottom, right), Text, Font, Color,....
  • Thêm control vào danh sách controls của form chứa nó.

Ta thực hành thôi :D 
Đầu tiên trong trình thiết kế, ta thêm một button, và cài đặt sự kiện click cho nó, mục đích khi bấm vào nút nó sẽ tự thêm một textbox mới như hình ở đầu bài.
Sau đó sử dụng đoạn code sau, và xem kết quả xảy ra nhé :) 

using System;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
int count = 1;

public Form1()
{
InitializeComponent();
}

private void button1_Click(object sender, EventArgs e)
{
AddNewTextBox();
}

public System.Windows.Forms.TextBox AddNewTextBox()
{
System.Windows.Forms.TextBox txt = new System.Windows.Forms.TextBox();
this.Controls.Add(txt);
txt.Top = count * 25;
txt.Left = 100;
txt.Text = "Icetea Viet TextBox " + this.count.ToString();
count = count + 1;
return txt;
}
}
}

   - Vậy là xong phần tạo.Tiếp theo là thao tác hoặc xóa controls. Để xóa control xác định thì bạn cần biết được một trong các thông tin sau (thứ tự của control đó trong list Controls của form, Key của control, Name hoặc Text của control...)
   - Bạn hãy tham khảo các method sau: this.Controls.RemoveAt(int index), this.Controls.RemoveByKey(string key),...

Hoặc các bạn có thể sử dụng vòng lặp foreach, duyệt qua tất cả các control trong list Controls và xét điều kiện
foreach (TextBox txtBox in this.Controls.OfType< TextBox >())
{
if(txtBox.Text == "IceTea Viet")
{
//Do something
}

//other condition
}
Như vậy là ta đã biết cách tạo và sử dụng một dynamic control cho mình rồi.
Chúc các bạn học tốt, và nhớ để lại bình luận của mình bên dưới nhé :)


Thứ Năm, 5 tháng 11, 2015


   Chào các bạn! 

    Đã lâu không trở lại với blog mình nhỉ :D dạo này mình lười quá, đồ án và deadline cũng nhiều. Thôi không dài dòng nữa, mình sẽ đi vào vấn đề chính.

   GIỚI THIỆU
   Đã bao giờ bạn nghĩ một phần mềm khi có quá nhiều control thì làm sao để quản lý nhanh các control đó. Hoặc khi có những "nhóm" các control phục vụ các chức năng liên quan đến nhau, khi cần show, hide chúng đồng loại lại phải gọi từng control??? 
   Panel đã ra đời để giải quyết vấn đề đó
   Panel dùng để tạo nhóm các control. Là một container với dạng một khung đơn giản để chưa các sub-control (button, textbox, ...) ở trong nó.




THUỘC TÍNH CỦA PANEL

   Cũng tương tự như các control khác Panel có những thuộc tính rất cơ bản.
   Lưu ý: Các sub-control nằm trong panel, thì sẽ bị ảnh hưởng bởi thuộc tính Enable và Visible của panel. Cả hai thuộc tính này đều phụ thuộc vào thuộc tính của panel chứa nó. Đây cũng là lý do dùng panel để show/hide một cụm các control

   Có lẽ các bạn đang thắc mắc khi panel có những chức năng tương tự như Groupbox, vậy thi nó khác gì với groupbox mà chúng ta đã tìm hiểu qua các bài trước. Bạn hãy mở Properties của panel, xem và kiểm tra thử nhé


   Điểm khác nhau giữa Panel và Groupbox:
 - Panel có khả năng Scrollable trong khi groupbox thì không. Panel khi chứa nhiều control có kích thước quá lớn thì thanh cuộn sẽ hỗ trợ việc hiển thị các control đó.
 - Panel còn có hỗ trợ khung viền (borders) đa dạng hơn groupbox
 - Groupbox có thuộc tính Text, dùng làm Caption hiển thị trên đầu khung, trong khi Panel không có


THÊM CONTROL VÀO PANEL

   Để thêm control vào panel bạn có thể kéo thả control đó trực tiếp vào panel chứa nó. Hoặc sử dụng code để thêm
   Ví dụ: Với hàm sau
private void btnCreate_Click(object sender, EventArgs e)
{
Panel dynamicPanel = new Panel();
dynamicPanel.Location = new System.Drawing.Point(26, 12);
dynamicPanel.Name = "Panel123";
dynamicPanel.Size = new System.Drawing.Size(228, 200);
dynamicPanel.BackColor = Color.LightBlue;
dynamicPanel.BorderStyle = BorderStyle.Fixed3D;

TextBox textBox1 = new TextBox();
textBox1.Location = new Point(10, 10);
textBox1.Text = "Học lập trình cùng IceTea Việt";
textBox1.Size = new Size(200, 30);

CheckBox checkBox1 = new CheckBox();
checkBox1.Location = new Point(10, 50);
checkBox1.Text = "Check Me";
checkBox1.Size = new Size(200, 30);

dynamicPanel.Controls.Add(textBox1);
dynamicPanel.Controls.Add(checkBox1);

Controls.Add(dynamicPanel);
}
   Kết quả trước và sau click button sẽ là:





TỔNG KẾT

Panel control là một container hay hay là một cơ chế nhóm control trong C# WinForms, và phù hợp cho cả mục đích hình ảnh giao diện và logic chương trình. Với nhiều phong các border, bạn có thể  tổ chức giao diện các sub-control trong panel. Và vì khả năng điều khiển các thuộc tính của các sub-control bạn có thể làm giảm độ phức tạp của code cho chương trình.

Chào các bạn và chúc các bạn học tập tốt!!!


Thứ Hai, 31 tháng 8, 2015

   Chào các bạn! 
   Hôm nay mình lại tiếp tục Series lập trình C# winform căn bản kèm theo ví dụ thực tế


GIỚI THIỆU
   Một phần mềm hoàn chỉnh không phải lúc nào cũng đưa ra các thông báo cho người dùng bằng MessageBox được, vì khi đó người dùng cần phải ấn vào OK, hoặc tắt MessageBox đi, rất phiền phức. Có một cách khác để thông báo mà các phần mềm khác hay dùng đó chính là dùng control mà mình sẽ giới thiệu hôm nay - NotifyIcon.



   NotifyIcon thường thông báo khi ta đóng phần mềm xuống thanh Taskbar, hoặc thông báo thông tin về update phần mềm, hoặc thông báo thời gian thực thi của một lệnh (-shutdown -s -t chẳng hạn :D ). Cũng như các Control khác, NotifyIcon có các thuộc tính và sự kiện cơ bản.


THUỘC TÍNH CỦA NOTIFYICON



   Icon mình có thể thêm Icon tùy biến ở ngoài vào theo ý thích. Vì mình dùng Win10 nên tạm thời các demo đều là hình ảnh của Win 10 nên các bạn thông cảm.
   Ví dụ: Với đoạn code sau
//Icon trên khay hệ thống
notifyIcon1.Icon = SystemIcons.WinLogo;

//Biểu tượng xuất hiện trên thông báo
notifyIcon1.BalloonTipIcon = ToolTipIcon.Info;

notifyIcon1.BalloonTipText = "IceTea Việt!";
notifyIcon1.BalloonTipTitle = "Thông báo!";

notifyIcon1.ShowBalloonTip(1000);
Thì kết quả sẽ là:

SỰ KIỆN CỦA NOTIFYICON
   
   NotifyIcon có các sự kiện hay dùng như sự kiện Click, DoubleClick. Và thường được dùng kèm với các sự kiện khác của Form.   Ví dụ: Ta muốn làm một thông báo khi đóng (Minimize) chương trình xuống, và khi hiện chương trình lại lại thông báo thêm lần nữa, ta thực hiện với đoạn code sau, với ShowBalloonTip(int_value) là lệnh hiển thị thông báo của NotifyIcon
private void YourForm_SizeChanged(object sender, EventArgs e)
{
if(this.WindowState == FormWindowState.Minimized)
{
notifyIcon1.Icon = SystemIcons.WinLogo;
notifyIcon1.BalloonTipIcon = ToolTipIcon.Info;

notifyIcon1.BalloonTipText = "IceTea Việt!";
notifyIcon1.BalloonTipTitle = "Thông báo!";

//Lệnh gọi thông báo ra màn hình với 1000 là thời gian hiển thị
notifyIcon1.ShowBalloonTip(1000);
}
else if(this.WindowState == FormWindowState.Normal)
{
notifyIcon1.BalloonTipText = "Ứng dụng đã được mở lại";

notifyIcon1.ShowBalloonTip(1000);
}

}
   Thì khi đóng chương trình xuống Taskbar sẽ hiển thị thông báo Notification với tiêu đề là "Thông báo", nội dung là "IceTea Việt". Với thời gian hiển thị là 10 giây. Và tương tự  khi mở lại.
   Trên là những thông tin cơ bản về Control NotifyIcon của C#. Các bạn tham khảo nếu thiếu hay không hiểu gì cứ viêc pm hỏi mình, hoặc comment mình sẽ trả lời ngay.
   Như thường lệ là đoạn code để đoán kết quả:
using System;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
// When the program begins, show the balloon on the icon for one second.
notifyIcon1.ShowBalloonTip(1000);
}

private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
{
// When icon is double-clicked, show this message.
MessageBox.Show("Doing something important on double-click...");
// Then, hide the icon.
notifyIcon1.Visible = false;
}
}
}

TỔNG KẾT
   Đối với chương trình yêu cầu thông báo liên tục, NotifyIcon có thể giúp tích hợp vào hệ điều hành chức năng này. Bằng cách kết hợp các NotifyIcon với các balloonTip, bạn có thể đưa ra những cảnh báo, attention-grabbing hoặc tin nhắn.

Chào các bạn và hẹn gặp lại vào các bài sau!



Chủ Nhật, 26 tháng 7, 2015



GIỚI THIỆU

   Chào các bạn!
   Hôm nay mình xin giới thiệu với các bạn GroupBox, một Container dùng để "chứa" các Control khác. GroupBox có dạng hình chữ nhật, dùng gom nhóm các Control có liên quan lại với nhau.


   Chúng ta sẽ bắt đầu vào việc tạo một GroupBox, một GroupBox có thể được tạo từ thanh công cụ ToolBox -> Container


THUỘC TÍNH CỦA GROUPBOX

   Cũng tương tự như một số Control cơ bản khác, ở đây mình xin giới thiệu thuộc tính Dock hay dùng với GroupBox. Bạn có thể scroll chuột và tự tìm hiểu vì nó cũng rất đơn giản: 
- Top, Bottom, Left, Right: Nó sẽ đưa Groupbox của bạn lên từng góc cụ thể.
- Center: Mở rộng Groupbox, sao cho lấp đầy hết form.
- None: Mặc định, tắt chức năng Docking



SỰ KIỆN CỦA GROUPBOX

Sự kiện mặc định của groupBox là groupBox_Enter, sự kiện này được chạy khi Control chứa trong groupBox trở thành active control của Form. Ví dụ ta có Form như sau.
   Con trỏ ban đầu ở khung textBox, Khi ta tab nó chuyển sang các Control khác, và khi chuyển đến Button1 thì sự kiện Enter sẽ chạy, và mình đã xuất ra thông báo bằng MessageBox   
   Ngoài sự kiện này ra thì Groupbox còn nhiều sự kiện khác nhưng theo mình là không đáng để bận tâm tới

   Trên là những thứ cơ bản về Groupbox, mọi thắc mắc cứ liên hệ trực tiếp với mình. Như thường lệ là đoạn code đơn giản từ cái proj của mình cho các bạn đoán kết quả
public void ShowSearchForm(MainForm mainfrm)
{
PopupForm search = new PopupForm(mainfrm);

search.label.Text = "TÌM KIẾM HỌC SINH";

search.groupBoxAdd.Visible = false;
search.groupBoxEdit.Visible = false;
search.groupBoxSearch.Visible = true;

search.Show();
}


public void ShowAddForm(MainForm mainfrm)
{
PopupForm add = new PopupForm(mainfrm);

add.label.Text = "THÊM HỌC SINH";

add.groupBoxAdd.Visible = true;
add.groupBoxEdit.Visible = false;
add.groupBoxSearch.Visible = false;

add.Show();
}

public void ShowEditForm(MainForm mainfrm)
{
if(SelectedStudentId != "0")
{
PopupForm edit = new PopupForm(mainfrm);

edit.label.Text = "SỬA HỌC SINH";

edit.groupBoxAdd.Visible = false;
edit.groupBoxEdit.Visible = true;
edit.groupBoxSearch.Visible = false;

edit.Show();
}
else
MessageBox.Show("Chọn sinh viên cần sửa!", "Thông báo");

}

TỔNG  KẾT

Groupbox không phải là một control thú vị trong lập trình C# Winform, nhưng chắc chắn nó là một control rất hữu dụng. Nó có thể giúp tạo một giao diện rõ ràng và dễ sử dụng cho chương trình của bạn
Chào các bạn, chúc các bạn học tốt!


Categories

Sample Text

Được tạo bởi Blogger.

Must Read

Biểu mẫu liên hệ

Tên

Email *

Thông báo *

Popular Posts

Video

Popular Posts

Our Facebook Page