Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

Chương 2: Lập trình hướng đối tượng trong C++

2.1 Lớp và đối tượng

2.1.1 Khái niệm, cú pháp khai báo

 Lớp: Lớp là thành phần cơ bản của chương trình hướng đối tượng, dùng để định

nghĩa đối tượng.

 Đối tượng - Đối tượng là sự thể hiện của lớp. - Mỗi đối tượng được xác định bởi thuộc tính (dữ liệu, biến) và hành vi (phương thức). Thuộc tính để xác định tính chất riêng của đối tượng, hành vi là hành động

tác động lên đối tượng.

 Cú pháp:

//Cú pháp khai báo lớp

class tên_lớp{

[mức_độ_truy_cập:] Các_thuộc_tính

[mức_độ_truy_cập:] Các_phương_thức

}[tên_đối_tượng];

//Cú pháp khai báo đối tượng

tên_lớp tên_đối tượng;

- Thuộc tính: như khai báo biến - Phương thức: như khai báo hàm

 Cách truy xuất:

Tên_đối_tượng. Tên_thuộc_tính

Tên_đối_tượng. Tên_phương_thức

2.1.2 Mức độ truy cập

- Private: chỉ cho phép các hàm trong lớp truy cập đến thành phần này, các lớp khác

không thể truy cập.

- Public: được phép truy cập từ mọi lớp. - Protected: cho phép các thành viên của cùng một lớp hoặc từ một lớp dẫn xuất của

nó.

- Khi không có từ khóa truy cập thì toàn bộ các thành viên của lớp được hiểu mặc

định là có thuộc tính private.

class A

class B

{ //mac dinh la private

{ void h()

int x;

{

38 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

void g() {

A a; a.x++;//sai vì x là private của A

/*g() trong cùng lớp A với x nên g() truy xuất đươc x*/

} };

x++; }

int main() {

public: int f()

A a; a.g(); //sai vì g là private của A

{

x=1; //truy xuat tp private

cout<

}

g(); return x;

} };

 Ví dụ: Viết chương trình tính điểm trung bình bằng cách thiết kế lớp sinh viên có các thuộc tính là hoten, điểm lý thuyết, điểm thực hành và các phương thức là

nhập, xuất, tính điểm trung bình.

using namespace std;

class sinhvien {

private: char hoten[30];

//cac thuoc tinh

float dlt,dth;

public:

//phuong thuc nhap

void nhap() {

cout<<"Nhap ho ten:"; cin>>hoten; cout<<"Nhap dlt:"; cin>>dlt;

cout<<"Nhap dth:"; cin>>dth;

}

float tinhdtb() {

return (dlt+dth)/2;

}

void xuat(float dtb) {

cout<<"\n"<<"Ho ten: "<

39 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

cout<<"\n"<<"Dtb: "<

}

};

void main() {

sinhvien sv; sv.nhap();

float dtb=sv.tinhdtb(); sv.xuat(dtb);

system("pause");

}

 Có thể bổ sung các phương thức vào trong lớp theo 2 cách: bổ sung trực tiếp (ví dụ

trên) hoặc khai báo prototype (sử dụng toán tử phạm vi :: theo sau tên lớp).

using namespace std; class sinhvien {

private: char hoten[30];

float dlt,dth; //cac thuoc tinh public:

void nhap(); void xuat(float);

float tinhdtb();

};

void sinhvien::nhap() //phuong thuc nhap {

cout<<"Nhap ho ten:"; cin>>hoten; cout<<"Nhap dlt:"; cin>>dlt;

cout<<"Nhap dth:"; cin>>dth;

}

float sinhvien::tinhdtb()

{

return (dlt+dth)/2;

}

void sinhvien::xuat(float dtb) {

cout<<"\n"<<"Ho ten: "<

cout<<"\n"<<"Dth: "<

40 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

cout<<"\n"<<"Dtb: "<

}

2.1.3 Hàm tạo (Constructor), Hàm hủy (Destructor)

Hàm tạo

- Khởi tạo giá trị ban đầu cho các thành viên của class - Được gọi tự động mỗi khi đối tượng được tạo ra - Hàm tạo không có kiểu dữ liệu trả về - Trùng với tên lớp và là hàm thành viên của lớp - Có thể có tham số hoặc không.

using namespace std;

class VD{ private:

int a,b;

public: VD() {

a=18; b=27;

} VD(int x, int y)

{

a=x;

b=y;

}

void show()

{

cout<<"a= " <

}; int main(){

VD o1; o1.show();

VD o2(2,3); o2.show();

system("pause");

}

Hàm hủy

41 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

- Giải phóng bộ nhớ trước khi kết thúc công việc với đối tượng đó. - Có tên trùng với hàm khởi tạo nhưng thêm dấu ~ trước tên hàm. - Không có tham số. - Trong chương trình chính ta không gọi hàm giải phóng nhưng hàm này vẫn được

~VD()

thực hiện.

{

cout <<"Giai phong doi tuong \n" ;

} 2.1.4 Sử dụng lớp, đối tượng

Mảng, biến đối tượng

Một lớp (sau khi định nghĩa) có thể xem như một kiểu dữ liệu và có thể dùng để khai báo các biến, mảng đối tượng. Cách khai báo biến và mảng đối tượng cũng như

những kiểu dữ liệu chuẩn của C++.

 Khai báo:

- Tên_lớp danh_sách_biến; - Tên lớp danh_sách_mảng; Ví dụ: Sinhvien sv1, sv2, sv3; // khai báo 3 biến đối tượng sv1, sv2, sv3

Sinhvien sv[20]; // khai báo mảng đối tượng sv gồm 20 sinh viên

Mỗi đối tượng sau khi khai báo sẽ được cấp phát một vùng nhớ riêng để chứa các

thuộc tính của chúng. Chú ý rằng sẽ không có vùng nhớ riêng để chứa các phương

thức cho mỗi đối tượng.

 Truy xuất:

- Thuộc tính: tên_đối_tượng.tên_thuộc_tính - Phương thức: tên_đối_tượng.tên_phương_thức

Tạo mảng các đối tượng từ ví dụ trên: VD o[MAX];

for (int i=0; i

{

o[i].input(); cout<<"\n";

}

for (int i=0; i

o[i].show();

42 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

Đối tượng làm tham số hàm, hàm trả về kiểu đối tượng

Ví dụ:

using namespace std;

class VD{ private:

int a,b;

public:

VD() {

a=18; b=27;

} VD(int x, int y)

a=x;

{

b=y; }

void show()

{

cout<<"a= " <

}

void mul(VD &t) {

a=a*a; b=b*b*b;

} VD add(VD d)

{

VD temp;

temp.a = a + d.a; temp.b= b + d.b;

return temp; }

};

int main(){ VD o1(3,3); o1.show(); VD o2(2,3);

o2.show();

43 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

VD o3;

o3 = o1.add(o2); //o2.mul(o2);

o3.show();

system("pause");

}

2.2 Nâng cao về lớp và đối tượng 2.2.1 Con trỏ đối tượng

Chúng ta đã làm quen với mảng đối tượng và chúng ta cũng đã biết rằng có sự

tương ứng 1-1 giữa mảng và con trỏ. Trong phần này, chúng ta sẽ thảo luận về con trỏ

đối tượng. Việc khai báo con trỏ đối tượng hoàn toàn tương tự như khai báo con trỏ dữ

liệu.

Humans *man;

Để truy cập đến các phương thức thành viên bên ngoài lớp (hàm thành viên), ta

sử dụng dấu ->. Khi gọi phương thức khởi tạo, ta có thể gọi theo cách mà ta đã sử

dụng cho con trỏ dữ liệu. Hoặc bạn có thể sử dụng toán tử new.

Kết quả Chương trình

Andy, 22 Jack, 21 … int main()

{

Humans man(“Andy”, 22);

Humans *man0 = &man;

//Hoặc

Humans *man1 = new Humans(“Jack”, 21);

cout<getName()<<”, ”<getAge();

cout<getName()<getAge();

return 0;

}

Ngay sau toán tử new, chúng ta gọi phương thức khởi tạo của nó, khác với toán tử new dùng trong việc cung cấp bộ nhớ cho con trỏ. Khi liên đới đến con trỏ, có nhiều vấn đề liên quan đến cách đọc. Chúng ta có thể tổng kết theo bảng bên dưới đây

Biểu thức *x &x Cách đọc trỏ bởi x địa chỉ của x

44 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

x.y x->y (*x).y x[i] thành viên y của đối tượng x thành viên y của đối tượng trỏ bởi x thành viên y của đối tượng trỏ bởi x đối tượng thứ i trỏ bởi x

2.2.2 Con trỏ this

Từ khoá this ở bên trong một lớp đại diện cho đối tượng của lớp đó đang được thực hiện trong bộ nhớ. Nó là một con trỏ luôn có giá trị là địa chỉ của đối tượng. Nó có thể được dùng để kiểm tra xem tham số được truyền cho một hàm thành viên có phải chính bản thân đối tượng hay không.

Ví dụ: class myClass {

this.a=a;//a là tham số của phương thức, this.a là thành viên lớp this.b=b;

int a,b; int add(int a, int b) { return this.a+this.b; }

}

2.2.3 Thành viên tĩnh

Một lớp có thể chứa các thành viên tĩnh, cả dữ liệu và các hàm. Các dữ liệu tĩnh còn được gọi là "biến của lớp" vì nội dung của chúng không phụ thuộc vào một đối tượng nào. Chỉ có một giá trị duy nhất cho tất cả các đối tượng trong cùng một lớp.

Ví dụ, nó có thể được trong trường hợp bạn muốn có một biến chứa số đối tượng thuộc

lớp đã được khai báo:

45 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

2.3 Nạp chồng

Nạp chồng là một đặc tính quan trọng của C++ đó là cơ chế giúp bạn thực hiện tính đa hình trong lập trình hướng đối tượng. Có hai kiểu nạp chồng được cung cấp trong C++ đó là nạp chồng hàm và nạp chồng toán tử. Vậy thì hai kiểu nạp chồng này là gì, hoạt động như thế nào hôm nay chúng ta sẽ đi tìm hiểu về 2 hình thức nạp chồng này.

2.3.1 Nạp chồng phương thức

Là một cơ chế của C++ cho phép chúng ta định nghĩa và sử dụng các hàm cùng tên, miễn là khác kiểu tham số hoặc là số lượng tham số khác nhau. Các hàm sử dụng cùng tên gọi là hàm chồng.

Nạp chồng với kiểu tham số khác nhau

Trong trường hợp này, các hàm có cùng số lượng tham số nhưng kiểu của tham số là khác nhau. Trình biên dịch sẽ dựa trên kiểu đối số của hàm để xác định hàm tương ứng.

Ví dụ:

class myClass

{

void hello(int a) // hàm này với tham số truyền vào là kiểu nguyên

46 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

{

cout <<”Hello world ”<<”ham nay co tham so la so nguyen”<

}

void hello(float a)// hàm này với tham số truyền vào là kiểu số thực

{

cout<<”Xin chao ban”<<”ham nay co tham so la mot so thuc”<

}

};

Nạp chồng với số lượng tham số khác nhau

C++ cũng cho phép sử dụng các hàm trùng tên với danh sách tham số có số

lượng khác nhau.

class myClass

{

void hello(int a) // hàm này có 1 tham số

{

cout <<”Hello world ”<<”ham nay co tham so la so nguyen”<

}

void hello(float a, int b)// hàm này có 2 tham số

{

cout<<”Xin chao ban”<<”ham nay co 2 tham so”<

}

};

Tham số mặc định

Tham số mặc định là đặc tính của C++ cho phép hoàn tất việc chồng hàm. Cơ chế tham số mặc định cho phép bạn đưa ra một giá trị mặc định của tham số khi hàm được gọi không kèm theo giá trị của đối số.

Ví dụ:

#include "stdafx.h"

#include

using namespace std;

47 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

class myClass

{

public:int add(int a=0, int b=0, int c=0)

{return a+b+c;}

};

int main()

{

myClass obj1;

cout<<"Gia tri ham khi khong truyen tham so la: "<

cout<<"Gia tri ham khi truyen 1 tham so la: "<

cout<<"Gia tri ham khi truyen 2 tham so la: "<

cout<<"Gia tri ham khi truyen 3 tham so la: "<

system("pause");

}

Kết quả:

Gia tri ham khi khong truyen tham so la: 0

Gia tri ham khi truyen 1 tham so la: 1

Gia tri ham khi truyen 2 tham so la: 3

Gia tri ham khi truyen 3 tham so la: 8

2.3.2 Nạp chồng toán tử

Như chúng ta đã biết các phép toán +,-,*,/,<…có thể được thực hiện trên các kiểu dữ liệu đơn giản. Tuy nhiên mặc định sẽ không thể thực hiện được trên các kiểu dữ liệu tự định nghĩa như lớp, nhưng C++ lại có cơ chế cho phép ta định nghĩa việc thực hiện các toán tử đó thông qua việc nạp chồng toán tử. Trong c++ có thể nạp chồng được hầu hết các toán tử ngoại trừ toán tử (.), (::) và (:?).

//Nội dung nạp chồng

Hình thức chung cho nạp chồng toán tử: kieuTraVe tenLop :: operator kyHieuToanTu (tham so) { } Một số chú ý khi nạp chồng toán tử:

1. Kiểu trả về của toán tử so sánh và toán tử logic phải khác tên lớp

48 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

2. Không thể thay đổi thứ tự ưu tiên của các toán tử

3. Không thể thay đổi số lượng toán hạng

4. Toán tử << và >> đã được nạp chồng rồi để thực hiện nhập/xuất

5. Hàm toán tử không được chứa tham số mặc định

Nạp chồng toán tử hai ngôi

Khi nạp chồng toán tử hai ngôi hàm toán tử sẽ chỉ có một tham số duy nhất.

Tham số này sẽ nhận một đối tượng là toán hạng nằm bên phải của toán tử (phép

toán).

Ví dụ:

// vidu.cpp : main project file.

#include "stdafx.h"

#include

using namespace std;

class phanso

{

public:int tu,mau;

public: phanso(){};

public: phanso(int a, int b)

{ tu=a;mau=b;}

void show()

{

cout<<"Mau

so

la:

"<

tu

so

la:

"<

}

phanso operator + (phanso ps1)

{

phanso temp(0,0);

temp.mau=mau+ps1.mau;

temp.tu=tu+ps1.tu;

return temp;

}

};

int main()

{

49 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

phanso p1(1,2),p2(3,4),p3;

p3=p1+p2;

p3.show();

system("pause");

}

Nạp chồng toán tử một ngôi

Nạp chồng toán tử một ngôi cũng giống như đối với toán tử hai ngôi. Tuy nhiên

toán tử một ngôi chỉ có một toán hạng và do đó hàm toán tử không có tham số.

Ví dụ:

// vidu.cpp : main project file.

#include "stdafx.h"

#include

using namespace std;

class phanso

{

public:int tu,mau;

public: phanso(){};

public: phanso(int a, int b)

{

tu=a;mau=b;

}

void show()

{

cout<<"Mau so la: "<

}

phanso operator + (phanso ps1)

{

phanso temp(0,0);

temp.mau=mau+ps1.mau;

temp.tu=tu+ps1.tu;

return temp;

}

phanso operator ++()

{

50 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

tu++;

mau++;

return *this;

}

};

int main()

{

phanso p1(1,2),p2(3,4),p3;

p3=p1+p2;// Nạp chồng toán tử 2 ngôi

p3.show();

//

p3++;//Nạp chồng toán tử 1 ngôi

p3.show();

system("pause");

}

Nạp chồng toán tử so sánh và toán tử logic

Như bạn đã biết biểu thức a>b trả về true nếu a lớn hơn b, false nếu a nhỏ hơn

b. Trong C++ giá trị false tương ứng với 0, giá trị true tương ứng với một số nguyên

khác 0. Do đó người ta thường sử dụng kiểu giá trị trả về của các hàm toán tử (khi

chồng toán tử so sánh và toán tử logic) là kiểu số nguyên.

Ví dụ:

#include "stdafx.h"

#include

using namespace std;

class phanso

{

public:int tu,mau;

public: phanso(){};

public: phanso(int a, int b)

{

tu=a;mau=b;

}

void show()

51 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

{

cout<<"Mau so la: "<

}

phanso operator + (phanso ps1)

{

phanso temp(0,0);

temp.mau=mau+ps1.mau;

temp.tu=tu+ps1.tu;

return temp;

}

phanso operator + (int a)

{

phanso temp(0,0);

temp.mau=mau+a;

temp.tu=tu+a;

return temp;

}

phanso operator ++()

{

tu++;

mau++;

return *this;

}

int operator >(phanso ps)//Nạp chồng toán tử so sánh

{

if(mau>ps.mau&&tu>ps.tu) return 1;

if(mau==ps.mau&&tu>ps.tu) return 1;

if(tu*ps.mau>mau*ps.tu) return 1;

return 0;

}

};

int main()

{

phanso p1(1,4),p2(3,4),p3;

52 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

p3=p1+p2;

p3.show();

//

p3++;

p3.show();

//

if(p1>p2){cout<<"\np1 lon hon p2";}else cout<<"p2 lon hon p1"<<"\n";

system("pause");

}

2.4 Tính kế thừa

2.4.1 Khái niệm kế thừa

Kế thừa là một cách trong lập trình hướng đối tượng để có thể thực hiện được

khả năng “sử dụng lại mã chương trình”. Sử dụng lại mã chương trình có nghĩa là xây

dựng một lớp mới dựa trên một lớp đã có sẵn. Bằng cách sử dụng lại các lớp đã có

chúng ta có thể giảm bớt được thời gian và công sức cần thiết để phát triển chương

trình đồng thời làm cho chương trình phần mềm có khả năng có quy mô lớn, rõ ràng

hơn về mặt logic và tin cậy hơn.

Cú pháp khai báo một lớp kế thừa một lớp khác:

class ten_lop_con: mức độ truy cập ten_lop_cha

{

// thân lớp con

}

Trong đó “mức độ truy cập” sẽ quyết định xem đó là một sự kế thừa thuộc loại

nào và tùy vào mức độ truy cập của các thành phần thuộc lớp cha mà lớp con có được

phép sử dụng các thành phần của lớp cha hay không.

2.4.2 Các kiểu kế thừa

Kiểu kế thừa sẽ quyết định xem các thành phần của lớp cha được lớp con sử

dụng với mức độ truy cập như thế nào. Trong C++ có 3 kiểu kế thừa tương ứng với 3

“mức độ truy cập” được khai báo trong cú pháp khai báo kế thừa.

53 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

Kế thừa kiểu public: class lop_con: public lop_cha{ }

Đây là kiểu kế thừa chúng ta hay dùng nhất. Với kiểu kế thừa này, các đối tượng

của lớp con có thể truy cập vào các thành viên public và protected của lớp cha. Các

thành viên protected của lớp cha sẽ trở thành thành viên protected của lớp con và các

thành viên public của lớp cha trở thành thành viên public của lớp con.

Kế thừa kiểu private: class lop_con: private lop_cha{ }

Đối với kiểu kế thừa này, tất cả các thành viên của lớp cha (trừ các thành viên có

mức độ truy cập private) sẽ trở thành các thành viên private của lớp con và chỉ có thể

được sử dụng bởi các phương thức trong lớp con.

Kế thừa kiểu protected: class lop_con: protected lop_cha{ }

Đối với kiểu kế thừa này, tất cả các thành viên của lớp cha (trừ các thành viên có

mức độ truy cập private) sẽ trở thành các thành viên protected của lớp con và có thể

được sử dụng bởi các phương thức trong lớp con và các đối tượng của nó.

Có thể tóm tắt lại các kiểu kế thừa như sau:

- Cột: các kiểu kế thừa

- Hàng: phạm vi các biến/phương thức thành phần trong lớp cha

- Kết quả: phạm vi các biến/phương thức trong lớp con

2.4.3 Kế thừa với hàm tạo và hàm hủy

Tất cả các lớp cha và lớp con đều có thể có hàm tạo và hàm hủy. Nếu cả lớp cha

và lớp con đều có hàm tạo, hàm hủy thì hàm tạo của lớp cha sẽ được thực hiện trước

hàm tạo của lớp con khi một đối tượng của lớp con được tạo ra. Điều này ngược lại

54 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

với hàm hủy. Tức là, hàm hủy của lớp con sẽ được thực hiện trước hàm hủy của lớp

cha.

Ví du:

#include "stdafx.h"

#include

using namespace System;

using namespace std;

class cha

{

int a,b;

public: cha()

{

cout<<"Day la phuong thuc khoi tao cua lop cha\n";

}

public: ~cha()

{

cout<<"ham huy cua lop cha\n";

}

};

class con:public cha{

public:con()

{

cout<<"Day la phuong thuc khoi tao cua lop con\n";

}

public:~con()

{

cout<<"Ham huy cua lop con\n";

}

};

int main()

{

con obj;//Tạo ra một đối tượng thuộc lớp con

system("pause");

}

Kết quả:

55 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Day la phuong thuc khoi tao cua lop cha Day la phuong thuc khoi tao cua lop con Ham huy cua lop con ham huy cua lop cha

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

2.4.4 Phương thức ảo

Phương thức ảo cũng giống như một phương thức thành viên khác của lớp. Trên

thực tế, phương thức ảo là một phương thức thành viên được khai báo trong lớp cha và

sẽ được định nghĩa lại trong các lớp con kế thừa nó. Khi một lớp chứa phương thức ảo

được kế thừa bởi một lớp khác, nói chung phương thức này phải được định nghĩa lại

cho mục đích riêng của lớp kế thừa.

Phương thức ảo được tạo bằng cách đặt từ khóa virtual ngay trước khai báo

phương thức. Khi hàm ảo được định nghĩa lại trong lớp con, ta không cần sử dụng từ

khóa virtual. Ta có cú pháp khai báo hàm ảo như sau:

56 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

class lop_cha

{

//các thành phần của lớp

//Khai báo hàm ảo có tên là ham_ao, có kiểu trả về là int và không có tham số

Public: virtual int ham_ao()

{

}

};

class lop_con : public lop_cha

{

//các thành phần khác của lớp

//định nghĩa lại hàm ảo được kế thừa ở lớp cha

Public: int ham_ao()

{

//nội dung định nghĩa lại hàm ảo

}

};

2.4.5 Lớp trừu tượng

Một lớp cơ sở trừu tượng là một lớp chỉ được dùng làm cơ sở cho các lớp khác.

Không hề có đối tượng nào của một lớp trừu tượng được tạo ra cả, bởi vì nó chỉ được

dùng để định nghĩa một số khái niệm tổng quát, chung cho các lớp khác. Một ví dụ về

lớp trừu tượng là lớp CON_VAT (con vật), nó sẽ dùng làm cơ sở để xây dựng

các lớp con vật cụ thể như lớp CON_CHO (con chó), CON_MEO (con mèo),...

(xem ví dụ bên dưới)

Trong C++ , thuật ngữ “Lớp trừu tượng” đặc biệt áp dụng cho các lớp có chứa

các phương thức ảo thuần tuý. Phương thức ảo thuần tuý là một phương thức ảo mà

nội dung của nó không có gì. Cách thức định nghĩa một phương thức ảo thuần tuý như

sau:

virtual void tên_phương_thức() = 0 ;

Ví dụ:

class A {

57 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

public:

virtual void nhap() = 0 ;

virtual void xuat() = 0 ;

void chuong();

} ;

Trong ví dụ trên, thì A là lớp cơ sở trừu tượng. Các phương thức nhap và xuat

được khai báo là các lớp ảo thuần tuý (bằng cách gán số 0 cho chúng thay cho việc cài

đặt các phương thức này). Phương thức chuong() là một phương thức bình thường và

sẽ phải có một định nghĩa ở đâu đó cho phương thức này.

Không có đối tượng nào của một lớp trừu tượng lại có thể được phát sinh. Tuy

nhiên các con trỏ và các biến tham chiếu đến các đối tượng của lớp trừu tượng thì vẫn

hợp lệ. Bất kỳ lớp nào dẫn xuất từ một lớp cớ sở trừu tượng phải định nghĩa lại tất cả

các phương thức thuần ảo mà nó thừa hưởng, hoặc bằng các phương thức ảo thuần tuý,

hoặc bằng những định nghĩa thực sự. Ví dụ:

class B : public A

{

public:

virtual void nhap() = 0 ;

virtual void xuat()

{

// Các câu lệnh

}

} ;

Theo ý nghĩa về hướng đối tượng, ta vẫn có thể có một lớp trừu tượng mà không

nhất thiết phải chứa đựng những phương thức thuần tuý ảo.

Một cách tổng quát mà nói thì bất kỳ lớp nào mà nó chỉ được dùng làm cơ sở cho

những lớp khác đều có thể được gọi là “lớp trừu tượng”. Một cách dễ dàng để nhận

58 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

biết một lớp trừu tượng là xem có dùng lớp đó để khai báo các đối tượng hay không? .

Nếu không thì đó là lớp cơ sở trừu tượng.

2.4.6 Đa kế thừa

Đa kế thừa là cơ chế, trong đó lớp dẫn xuất có thể kế thừa từ hai hay nhiều lớp cơ

sở.

Khai báo đa kế thừa

class : ,

cập>,…

{

// nội dung lớp dẫn xuất

}

Ví dụ: Lớp Bus kế thừa từ 2 lớp: Car và PublicTransport

class Bus: public Car, protected PublicTransport{

..//nội dung lớp Bus

};

Chú ý:

- Trong đa kế thừa, mỗi lớp cơ sở được phân cách nhau bởi dấu “,”

- Mỗi lớp cơ sở có thế có từ khóa mức độ truy cập khác nhau

- Nguyên tắc truy cập vào các thành phần của lớp cơ sở cũng hoàn toàn tương tự như

trong kế thừa đơn.

Vấn đề trùng tên trong đa kế thừa

class Legged { public: void move() { ... } }; class Winged { public: void move() { ... } }; class Pigeon: public Legged, public Winged {

59 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

... }; Pigeon p1; p1.move(); // lỗi p1.Legged::move(); // Legged p1.Winged::move(); // Winged

trong ví dụ trên ta thấy một đối tượng p1 thuộc lớp Pigeon kế thừa từ 2 lớp Legged và Winged, cả 2 lớp đó đều có phương thức move() nên khi gọi p1.move() sẽ báo lỗi nên chúng ta phải truy cập thông qua cú pháp:

tên_đối_tượng.Tên_lớp_cơ_sở::tên_thành_phần

2.5 Sử dụng một số lớp hữu ích có sẵn

2.5.1 Lớp Container

Lớp vật chứa (Container) bao gồm nhiều lớp cơ bản của C++: lớp Vector, lớp

danh sách (List) và các kiểu hàng đợi (Stack và Queue), lớp tập hợp (Set) và lớp ánh

xạ(Map). Trong chương này sẽ trình bày một số lớp cơ bản của Container là: Set,

Stack, Queue và List.

a. Giao diện của lớp Container

Các lớp cơ bản của Container có một số toán tử và phương thức có chức năng

giống nhau, bao gồm:

• ==: Toán tử so sánh bằng

• <: Toán tử so sánh nhỏ hơn

• begin(): Giá trị khởi đầu của con chạy iterator

• end(): Giá trị kết thúc của con chạy iterator

• size(): Số lượng phần tử đối tượng của vật chứa

• empty(): Vật chứa là rỗng

• front(): Phần tử thứ nhất của vật chứa

• back(): Phần tử cuối của vật chứa

• []: Toán tử truy nhập đến phần tử của vật chứa

• insert(): Thêm vào vật chứa một (hoặc một số) phần tử

60 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

• push_back(): Thêm một phần tử vào cuối vật chứa

• push_front(): Thêm một phần tử vào đầu vật chứa

• erase(): Loại bỏ một (hoặc một số) phần tử khỏi vật chứa

• pop_back(): Loại bỏ phần tử cuối của vật chứa

• pop_front(): Loại bỏ phần tử đầu của vật chứa.

Ngoài ra, tuỳ vào các lớp cụ thể mà có một số toán tửvà phương thức đặc trưng của

lớp đó. Các toán tử và phương thức này sẽ được trình bày chi tiết trong nội dung từng

lớp tiếp theo.

b. Con chạy Iterator

Iterator là một con trỏ trỏ đến các phần tử của vật chứa. Nó đóng vai trò là một

con chạy cho phép người dùng di chuyển qua từng phần tử có mặt trong vật chứa. Mỗi

phép tăng giảm một đơn vị của con chạy này tương ứng với một phép dịch đến phần tử

tiếp theo hay phần tử trước của phần tử hiện tại mà con chạy đang trỏ tới.

Khai báo con chạy

Cú pháp chung để khai báo một biến con chạy iterator như sau:

Tên_lớp::iterator Tên_con_chạy;

Trong đó:

• Tên lớp: là tên của lớp cơ bản ta đang dùng, ví dụ lớp Set, lớp List…

• T: là tên kiểu lớp của các phần tử chứa trong vật chứa. Kiểu có thể là các kiểu cơ

bản trong C++, cũng có thể là các kiểu phức tạp do người dùng tự định nghĩa.

• Tên con chạy: là tên biến sẽ được sử dụng làm biến chạy trong vật chứa.

Ví dụ:

Set::iterator iter;

là khai báo một biến con chạy iter cho lớp tập hợp (Set), trong đó, các phần tử của lớp

vật chứa có kiểu cơ bản int. Hoặc:

List::iterator iter;

61 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

là khai báo một biến con chạy iter cho lớp danh sách (List), trong đó, các phần tử có

kiểu lớp do người dùng tự định nghĩa là Person.

Sử dụng con chạy

Con chạy được sử dụng khi cần duyệt lần lượt các phần tử có mặt trong vật chứa. Ví

dụ sau sẽ in ra các phần tử có kiểu int của một tập hợp:

Set mySet; // Khai báo một đối tượng của lớp Set

// các phần tửcó kiểu int

Set::iterator i; // Khai báo con chạy của lớp Set,

// các phần tử có kiểu int

… // Thêm phần tửvào

for(i=mySet.begin(); i

cout << mySet[i] << “ ”;

Lưu ý:

• Biến con chạy phải được khởi đầu bằng phương thức begin() và kết thúc bằng

phương thức end() của đối tượng cần duyệt tương ứng.

• Một con chạy có thể được sử dụng nhiều lần cho nhiều đối tượng nếu chúng có cùng

kiểu lớp vật chứa và các phần tử của chúng cũng cùng kiểu.

2.5.2 Lớp tập hợp (set)

Lớp tập hợp (Set) chứa các phần tử có cùng kiểu, không phân biệt thứ tự giữa các

phần tử nhưng lại phân biệt giữa các phần tử: các phần tử là khác nhau từng đôi một.

Muốn sử dụng lớp tập hợp, phải có chị thị đầu tệp:

#include // Thưviện riêng của lớp tập hợp

hoặc:

#include // Thưviện chung cho các lớp vật chứa

a. Hàm khởi tạo

62 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

Lớp tập hợp có ba kiểu khởi tạo chính:

• Khởi tạo không tham số:

Set Tên_đối_tượng;

• Khởi tạo bằng một mảng các đối tượng phần tử:

Set Tên_đối_tượng(T*, chiều_dài_mảng);

• Khởi tạo bằng một đối tượng thuộc lớp tập hợp khác:

Set Tên_đối_tượng(Set);

Trong đó:

• T: là tên kiểu của các phần tử của tập hợp. Kiểu này có thể là kiểu cơ bản của

C++, cũng có thể là các kiểu cấu trúc (struct) hoặc lớp (class) do người dùng tự định

nghĩa.

Ví dụ:

Set mySet;

là khai báo một đối tượng mySet của lớp tập hợp, mySet khởi đầu chưa có phần tử

nào, các phần tử của đối tượng này có kiểu cơ bản int. Hoặc:

Person *myPerson = new Person[10]; // Khởi tạo mảng đối tượng

Set mySet(myPerson, 10); // Khai báo tập hợp

là khai báo một đối tượng mySet của lớp tập hợp, có 10 phần tử tương ứng với các

phần tử trong mảng động myPerson, các phần tử có kiểu lớp Person.

b. Toán tử

Các toán tửtrên lớp tập hợp là tương ứng với các toán tửsốhọc trên tập hợp thông

thường: OR “|”, AND “&”, XOR “^” và phép trừ“-”.

Phép toán “|” và “|=”

Phép toán này trả vềp hép hợp (OR) của hai đối tượng của lớp tập hợp, kết quả cũng là

một đối tượng của lớp tập hợp:

<Đối_tượng_1> = <Đối_tượng_2> | <Đối_tượng_3>;

63 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

<Đối_tượng_1> |= <Đối_tượng_2>;

Ví dụ, mySet1 chứa hai phần tử kiểu int {1,2}, mySet2 chứa ba phần tử kiểu int

{2,3,4}, và: mySet3 = mySet1 | mySet2; thì mySet3 sẽ chứa các phần tử kiểu int là

{1,2,3,4}.

Phép toán “&” và “&=”

Phép toán này trả về phép giao (AND) giữa hai đối tượng tập hợp, kết quả cũng là một

đối tượng tập hợp:

<Đối_tượng_1> = <Đối_tượng_2> & <Đối_tượng_3>;

<Đối_tượng_1> &= <Đối_tượng_2>;

Ví dụ, mySet1 chứa hai phần tử kiểu int {1,2}, mySet2 chứa ba phần tử kiểu int

{2,3,4}, và:

mySet3 = mySet1 & mySet2;

thì mySet3 sẽ chứa các phần tử có kiểu int là {2}.

Phép toán “^” và “^=”

Phép toán này trả về phép hợp ngoại (XOR) giữa hai đối tượng tập hợp, kết quả cũng

là một đối tượng tập hợp:

<Đối_tượng_1> = <Đối_tượng _2> ^ <Đối_tượng_3>;

<Đối_tượng_1> ^= <Đối_tượng_2>;

Ví dụ, mySet1 chứa hai phần tử kiểu int {1,2}, mySet2 chứa ba phần tử kiểu int

{2,3,4}, và:

mySet3 = mySet1 ^ mySet2;

thì mySet3 sẽ chứa các phần tử có kiểu int là {1,3,4}.

Phép toán “-” và “-=”

Phép toán này trả về phép hiệu (loại trừ) giữa hai đối tượng tập hợp, kết quả cũng là

một đối tượng tập hợp:

<Đối_tượng_1> = <Đối_tượng_2> - <Đối_tượng_3>;

<Đối_tượng_1> -= <Đối_tượng_2>; 64 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

Ví dụ, mySet1 chứa hai phần tử kiểu int {1,2}, mySet2 chứa ba phần tử kiểu int

{2,3,4}, và:

mySet3 = mySet1 - mySet2;

thì mySet3 sẽ chứa các phần tử có kiểu int là {1}.

c. Phương thức

Lớp tập hợp có một số phương thức cơ bản sau:

• Thêm một phần tử vào tập hợp

• Loại một phần tử khỏi tập hợp

• Tìm kiếm một phần tử trong tập hợp

Thêm một phần tử vào tập hợp

Có hai cú pháp để thêm một phần tử vào tập hợp:

pair insert(T&);

iterator insert(, T&);

Trong đó:

• Phương thức thứ nhất thêm một phần tử vào tập hợp, nếu phần tử đã có mặt

trong tập hợp, trả về false và vị trí con chạy của phần tử đó. Nếu phần tử chưa

tồn tại, trả về true và vị trí con chạy của phần tử mới thêm vào.

• Phương thức thứ hai cũng thêm vào một phần tử, nhưng chỉ kiểm tra xem phần

tử đã tồn tại hay chưa bắt đầu từ vị trí con chạy được chỉ ra trong biến

chạy>. Phương thức này trả về vị trí con chạy của phần tử mới thêm vào (nếu

thành công) hoặc vị trí của phần tử đã có mặt.

Ví dụ, mySet là một tập hợp kiểu int:

mySet.insert(10);

sẽ thêm một phần tử có giá trị 10 vào tập hợp.

Lưu ý:

65 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

• Do tuân thủ theo lí thuyết tập hợp, nên khi chèn vào tập hợp nhiều lần với cùng

một giá trị phần tử. Trong tập hợp ch ỉtồn tại duy nhất một giá trị phần tử đó,

không được trùng lặp.

Loại một phần tử khỏi tập hợp

Có ba cú pháp để loại bỏ phần tử khỏi tập hợp:

int erase(T&);

void erase();

void erase(, );

Trong đó:

• T: là tên kiểu các phần tử của tập hợp.

• Phương thức thứ nhất xoá phần tử có giá trị được chỉ rõ trong tham số đầu vào.

• Phương thức thứ hai loại bỏ phần tử ở vị trí của con chạy được xác định bởi

tham số đầu vào.

• Phương thức thứ ba loại bỏ một số phần tử nằm trong phạm vi từ

đầu> cho đến của con chạy.

Ví dụ, mySet là một tập hợp các phần tử có kiểu int:

mySet.erase(10);

sẽ xoá phần tử có giá trị 10, hoặc:

mySet.erase((Set::iterator)10);

sẽ xoá phần tử ở vị trí thứ 10 trong tập hợp, hoặc:

mySet.erase(mySet.begin(), mySet.end());

sẽ xoá toàn bộ các phần tử hiện có của tập hợp mySet.

Tìm kiếm một phần tử trong tập hợp

Có hai cú pháp để tìm kiếm một phần tử trong tập hợp:

iterator find(T&);

int count(T&);

66 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

Trong đó:

• Phương thức thứ nhất tìm phần tử có giá trị xác định bởi tham số đầu vào, kết

quả là vị trí con chạy của phần tử đó.

• Phương thứ thứ hai chỉ để kiểm tra xem phần tử có xuất hiện trong tập hợp hay

không: trả về1 nếu có mặt, trả về 0 nếu không có mặt.

Ví dụ, mySet là một tập hợp các phần tử có kiểu int:

Set::iterator index = mySet.find(10);

cout << index;

sẽ hiển thị vị trí con chạy của phần tử có giá trị 10 trong tập hợp mySet.

Ví dụ áp dụng:

#include

#include

#include

void main(){

clrscr();

Set mySet;

int function;

do{

clrscr();

cout << “CAC CHUC NANG:” << endl;

cout << “1: Them mot phan tu vao tap hop” << endl;

cout << “2: Loai bo mot phan tu khoi tap hop” << endl;

cout << “3: Xem tat ca cac phan tu cua tap hop” << endl;

cout << “5: Thoat!” << endl;

cout << “=====================================” <<

endl;

67 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

cout << “Chon chuc nang: ” << endl;

cin >> function;

switch(function){

case ‘1’: // Thêm vào

char phantu;

cout << “Ki tu them vao: ”;

cin >> phantu;

mySet.insert(phantu);

break;

case ‘2’: // Loại ra

char phantu;

cout << “Loai bo ki tu: ” << endl;

cin >> phantu;

mySet.erase(phantu);

break;

case ‘3’: // Duyệt

cout<<“Cac phan tu cua tap hop la:”<

Set::iterator i;

for(i=mySet.begin(); i

cout << mySet[i] << “ ”;

break;

}while(function != ‘5’);

return;

}

2.5.3 Lớp chuỗi kí tự

68 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

Lớp chuỗi (String) cũng là một loại lớp chứa, nó chứa một tập các phần tử là một

dãy các kí tự có phân biệt thứ tự, các phần tử không nhất thiết phải phân biệt nhau.

Muốn sử dụng lớp String, cần thêm vào chỉ thị đầu tệp:

#include

a. Hàm khởi tạo

Lớp String có ba hàm khởi tạo chính:

• Hàm khởi tạo không tham số:

String ;

• Hàm khởi tạo từ một string khác:

String (const String &);

• Hàm khởi tạo từ một mảng các kí tự:

String (char*, );

Ví dụ:

String myStr;

là khai báo một chuỗi myStr chưa có phần tử nào (rỗng). Hoặc:

String myStr(“hello!”);

là khai báo một chuỗi myStr có các phần tử theo thứ tự là {‘h’, ’e’, ’l’, ’l’, ’o’, ’!’}.

Hoặc:

char* myChar = new char[10];

String myStr(myChar, 10);

là khai báo một chuỗi myStr có 10 phần tử tương ứng với các kí tự trong mảng

myChar.

Lưu ý:

• Trong trường hợp khởi tạo bằng một chuỗi khác, ta có thể truyền vào một đối

số có kiểu cơ bản khác, trình biên dịch sẽ tự động chuyển đối số đó sang dạng

string.

69 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

Ví dụ:

String myStr(12);

thì chuỗi myStr sẽ chứa hai phần tửkí tự{‘1’, ’2’}. Hoặc:

String myStr(15.55);

thì chuỗi myStr sẽchứa năm phần tửkí tự{‘1’, ’5’, ’.’, ’5’, ’5’}.

b. Toán tử

Lớp String có các toán tử cơ bản là:

• Phép gán chuỗi

• Phép cộng chuỗi

• Phép so sánh chuỗi

• Phép vào/ra

Phép gán chuỗi “=”

Cú pháp phép gán chuỗi là tương tự cú pháp gán các đối tượng cơ bản:

= ;

Ví dụ:

String s1(12), s2;

s2 = s1;

thì chuỗi s2 cũng chứa hai phần tử như s1 {‘1’, ‘2’}.

Lưu ý:

• Có thể gán trực tiếp các đối tượng cơ bản cho chuỗi:

String myStr = 12; // myStr có hai phần tử{‘1’, ‘2’}

• Nhưng phép gán lại có độ ưu tiên thấp hơn phép toán học:

String myStr = 12+1.5; // tương đương myStr = 13.5

Phép cộng chuỗi “+” và “+=”

70 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

Phép cộng chuỗi sẽ nối chuỗi thứ hai vào sau chuỗi thứ nhất, kết quả cũng là một

chuỗi:

= + ;

+= ;

Ví dụ:

String s1(12), s2(3);

s1+= s2;

thì s1 sẽ có ba phần tử kí tự{‘1’, ‘2’, ‘3’}.

Phép so sánh chuỗi

Các phép so sánh chuỗi đều là các phép toán hai ngôi, trả về kết quả ở dạng bool

(true/false):

• Phép so sánh lớn hơn “>”: chuỗi_1 > chuỗi_2;

• Phép so sánh lớn hơn hoặc bằng “>=”: chuỗi_1 >= chuỗi_2;

• Phép so sánh nhỏhơn “<”: chuỗi_1 < chuỗi_2;

• Phép so sánh nhỏhơn hoặc bằng “<=”: chuỗi_1 <= chuỗi_2;

• Phép so sánh bằng “==”: chuỗi_1 == chuỗi_2;

• Phép so sánh khác (không bằng) “!=”: chuỗi_1 != chuỗi_2;

Lưu ý:

• Phép so sánh chuỗi thực hiện so sánh mã ASCII của từng kí tự ởhai chuỗi theo

thứtự

tương ứng cho đến khi có sựkhác nhau đầu tiên giữa hai kí tự.

• Phép so sánh là phép so sánh dựa trên từ điển, có phân biệt chữhoa và

chữthường.

Ví dụ:

“12” < “a”; // có giá trị đúng

“a” <= “A”; // có giá trịsai

71 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

Phép vào/ra

• Phép xuất ra “<<”: cout << biến_chuỗi;

• Phép nhập vào “>>”: cin >> biến_chuỗi;

Ví dụ:

String s(“hello!”);

cout << s;

sẽ in ra màn hình dòng chữ“hello!”.

c. Phương thức

Lớp chuỗi có một số phương thức cơ bản:

• Lấy chiều dài chuỗi

• Tìm một chuỗi con

• Thêm một chuỗi con

• Xoá một chuỗi con

• Chuyển kiểu kí tự

Lấy chiều dài chuỗi

Cú pháp:

.length();

trả về chiều dài của chuỗi (số lượng phần tử kí tự trong chuỗi).

Ví dụ:

String s(“hello!”);

cout << s.length();

sẽ in ra màn hình độ dài chuỗi s là 6.

Tìm một chuỗi con

Cú pháp:

.find(, , );

72 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

Trong đó:

• Tham số thứ nhất là chuỗi con cần tìm.

• Tham số thứ hai là vị trí để bắt đầu tìm, mặc định là bắt đầu tìm từ phần tử có

chỉ số 0.

• Tham số thứ ba chỉ ra cách so khớp có phân biệt chữ hoa với chữ thường:

SM_IGNORE là không phân biệt, SM_SENSITIVE là có phân biệt.

• Phương thức này trả về kết quả dạng bool, tương ứng là có tìm thấy hay không.

Ví dụ:

s.find(“12”, 0, SM_IGNORE);

sẽ tìm trong chuỗi s xem có sự xuất hiện của chuỗi “12” hay không, vị trí bắt đầu tìm

là 0, với cách tìm không phân biệt chữ hoa chữ thường.

Thêm một chuỗi con

Cú pháp:

.insert(, );

Trong đó:

• Tham số thứ nhất là vịtrí chỉ số mà tại đó, chuỗi con sẽ được chèn vào

• Tham số thứ hai là chuỗi con cần chèn, chuỗi con này cũng có thể là một kí tự.

Ví dụ:

s.insert(0, “12”);

sẽ chèn vào đầu chuỗi s một chuỗi con có hai phần tử “12”.

Xoá một chuỗi con

Cú pháp:

.delete(, <độdài chuỗi xoá>);

Trong đó:

• Tham số thứ nhất là vị trí bắt đầu xoá chuỗi con

• Tham số thứ hai là độ dài chuỗi con bị xoá, giá trị mặc định là 1.

73 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

Ví dụ:

s.delete(0, 2);

sẽ xoá hai kí tự đầu của chuỗi s.

Chuyển kiểu kí tự

• Đổi chuỗi thành các kí tự hoa: .toUpper();

• Đổi chuỗi thành các kí tự thường: .toLower();

Ví dụ:

s.toUpper(); // chuyển chuỗi s thành kí tự hoa

s.toLower(); // chuyển chuỗi s thành kí tự thường

Ví dụ áp dụng

#include

#include

#include

void main(){

clrscr();

String myStr;

int function;

do{

clrscr();

cout << “CAC CHUC NANG:” << endl;

cout << “1: Cong them mot chuoi” << endl;

cout << “2: Chen them mot chuoi” << endl;

cout << “3: Xoa di mot chuoi” << endl;

cout << “4: Tim mot chuoi con” << endl;

cout << “5: Chuyen thanh chu hoa” << endl;

74 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

cout << “6: Chuyen thanh chu thuong” << endl;

cout << “7: Xem noi dung chuoi” << endl;

cout << “8: Xem chieu dai chuoi” << endl;

cout << “9: Thoat!” << endl;

cout << “=====================================” <<

endl;

cout << “Chon chuc nang: ” << endl;

cin >> function;

switch(function){

case ‘1’: // Thêm vào cuối

String subStr;

cout << “Chuoi them vao: ”;

cin >> subStr;

myStr += subStr;

break;

case ‘2’: // Chèn vào chuỗi

String subStr;

int position;

cout << “Chuoi them vao: ”;

cin >> subStr;

cout << “Vi tri chen:”;

cin >> position;

myStr.insert(position, subStr);

break;

case ‘3’: // Xoá đi một chuỗi con

75 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

int position, count;

cout << “Vi tri bat dau xoa:”;

cin >> position;

cout << “Do dai xoa:”;

cin >> count;

myStr.delete(position, count);

break;

case ‘4’: // Tìm chuỗi con

String subStr;

int position;

cout << “Chuoi con can tim:”;

cin >> subStr;

cout << “Vi tri bat dau tim:”;

cin >> position;

if(myStr.find(position, subStr))

cout << “Co xuat hien!” << endl;

else

cout << “Khong xuat hien!” << endl;

break;

case ‘5’: // Chuyển thành chữhoa

myStr.toUpper();

cout << myStr << endl;

break;

case ‘6’: // Chuyển thành chữthường

myStr.toLower();

76 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

cout << myStr << endl;

break;

case ‘7’: // Duyệt

cout << “Noi dung chuoi:” << endl;

cout << myStr << endl;

break;

case ‘8’: // Duyệt

cout << “Chieu dai chuoi:”

<< myStr.length() << endl;

break;

}while(function != ‘9’);

return;

}

2.5.4 Lớp ngăn xếp và hàng đợi

2.5.4.1 Lớp ngăn xếp

Lớp ngăn xếp (stack) cũng là một loại lớp vật chứa, nó chứa các phần tử cùng

kiểu, không bắt buộc phải phân biệt nhau nhưng có phân biệt về thứ tự: các thao tác

thêm phần tử và lấy phần tử ra đều được thực hiện ở một đầu ngăn xếp. Phần tử nào

được thêm vào trước thì sẽ bị lấy ra sau.

Muốn dùng lớp Stack phải dùng chỉ thị đầu tệp:

#include

a. Hàm khởi tạo

Lớp Stack có hai cách khởi tạo:

• Khởi tạo không tham số:

Stack biến_ngăn_xếp;

• Khởi tạo bằng một ngăn xếp khác, có cùng kiểu phần tử:

77 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

Stack biến_ngăn_xếp(Stack);

Trong đó:

• T: là kiểu của các phần tử chứa trong ngăn xếp. T có thể là các kiểu cơ bản, cũng có

thể là các kiểu phức tạp do người dùng tự định nghĩa.

Ví dụ:

Stack myStack;

là khai báo một biến myStack, chứa các phần tử có kiểu cơ bản int.

b. Toán tử

Lớp Stack chỉ dùng đến các toán tử gán “=” và toán tử so sánh bằng “==”:

• Phép gán “=”:

= ;

Dùng để gán hai đối tượng ngăn xếp.

• Phép so sánh bằng “==”:

== ;

Dùng để kiểm tra xem hai đối tượng ngăn xếp có bằng nhau hay không. Kết quả trả về

có kiểu bool (true/false).

c. Phương thức

Thêm một phần tử:

.push(T);

sẽ thêm một phần tử có kiểu T vào đỉnh ngăn xếp.

Lấy một phần tử:

.pop();

sẽ trả về phần tử đang nằm ở đỉnh ngăn xếp.

Kiểm tra tính rỗng:

.empty();

sẽ trả về kết quả kiểu bool, tương ứng với trạng thái của ngăn xếp có rỗng hay không. 78 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

Kích thước ngăn xếp:

.size();

sẽ trả về số lượng các phần tử hiện đang có mặt trong ngăn xếp.

Ví dụ áp dụng

#include

#include

#include

#include

void main(){

clrscr();

Stack myStack;

char strIn[250];

cout << “Nhap chuoi: ”;

cin >> strIn; // Nhập chuỗi kí tựtừbàn phím

for(int i=0; i

myStack.push(strIn[i]);

while(!myStack.empty()) // Lấy ra từngăn xếp

cout << myStack.pop();

return;

}

2.5.4.2 Lớp hàng đợi

Lớp hàng đợi (queue) cũng là một loại lớp vật chứa, nó chứa các phần tử cùng

kiểu, không bắt buộc phải phân biệt nhau nhưng có phân biệt về thứ tự: các thao tác

thêm phần tử được thực hiện ở một đầu, các thao tác lấy phần tử ra được thực hiện ở

một đầu còn lại của hàng đợi. Phần tử nào được thêm vào trước thì sẽ bị lấy ra trước.

Muốn dùng lớp Queue phải dùng chỉ thị đầu tệp:

79 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

#include

a. Hàm khởi tạo

Lớp Queue có hai cách khởi tạo:

• Khởi tạo không tham số:

Queue biến_hàng_đợi;

• Khởi tạo bằng một hàng đợi khác, có cùng kiểu phần tử:

Queue biến_hàng_đợi(Queue);

Trong đó:

• T: là kiểu của các phần tử chứa trong hàng đợi. T có thể là các kiểu cơ bản,

cũng có thể là các kiểu phức tạp do người dùng tự định nghĩa.

Ví dụ:

Queue myQueue;

là khai báo một biến myQueue, chứa các phần tử có kiểu cơ bản int.

b. Toán tử

Lớp Queue chỉ dùng đến các toán tử gán “=” và toán tử so sánh bằng “==”:

• Phép gán “=”:

= ;

Dùng để gán hai đối tượng hàng đợi.

• Phép so sánh bằng “==”:

== ;

Dùng để kiểm tra xem hai đối tượng hàng đợi có bằng nhau hay không. Kết quả trả về

có kiểu bool (true/false).

c. Phương thức

• Thêm một phần tử:

.push(T);

sẽ thêm một phần tử có kiểu T vào cuối hàng đợi.

80 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

• Loại một phần tử:

.pop();

sẽ trảvề phần tử đang nằm ở đỉnh đầu hàng đợi.

• Kiểm tra tính rỗng:

.empty();

sẽ trả về kết quả kiểu bool, tương ứng với trạng thái của hàng đợi có rỗng hay không.

• Kích thước hàng đợi:

.size();

sẽ trả về số lượng các phần tử hiện đang có mặt trong hàng đợi.

Ví dụ áp dụng

#include

#include

#include

void main(){

clrscr();

Queue myQueue;

int function;

do{

clrscr();

cout << “CAC CHUC NANG:” << endl;

cout << “1: Them mot tien trinh vao hang doi” << endl;

cout << “2: Dua mot tien trinh trinh vao thuc hien” << endl;

cout<<“3: Xem tat ca cac tien trinh trong hang doi”<< endl;

cout << “5: Thoat!” << endl;

81 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

cout << “========================================”

<< endl;

cout << “Chon chuc nang: ” << endl;

cin >> function;

switch(function){

case ‘1’: // Thêm vào hàng đợi

int maso;

cout << “Ma so tien trinh vao hang doi: ”;

cin >> maso;

myQueue.push(maso);

break;

case ‘2’: // Lấy ra khỏi hàng đợi

cout << “Tien trinh duoc thuc hien: ” << myQueue.pop() << endl;

break;

case ‘3’: // Duyệt hàng đợi

Queue::iterator i;

for(i=myQueue.begin(); i

cout << myQueue[i] << “ ”;

break;

}while(function != ‘5’);

return;

}

2.5.5 Lớp danh sách liên kết

Lớp danh sách liên kết (List) cũng là một kiểu lớp vật chứa, nó chứa các phần tử

cùng kiểu, có tính đến thứ tự. Muốn sử dụng lớp List của thư viện C++, phải khai báo

chỉ thị đầu tệp:

82 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

#include // Dành riêng cho lớp List

hoặc:

#include // Dùng chung cho các lớp vật chứa

a. Hàm khởi tạo

Lớp List có ba kiểu khởi tạo:

• Khởi tạo không tham số:

List biến_danh_sách;

• Khởi tạo tửmột danh sách cùng kiểu:

List biến_danh_sách(List);

• Khởi tạo từmột mảng các phần tử:

List biến_danh_sách(T* , int );

Trong đó:

• T: là kiểu của các phần tử chứa trong danh sách liên kết. T có thể là các kiểu cơ

bản, cũng có thể là các kiểu phức tạp do người dùng tự định nghĩa.

Ví dụ:

List myList;

sẽ khai báo một danh sách liên kết myList, các phần tử của nó có kiểu cơ bản int.

b. Toán tử

Toán tửgán “=”

Cú pháp:

= ;

sẽ copy toàn bộ các phần tử của vào .

Toán tử so sánh bằng “==”

Cú pháp:

= ;

83 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

sẽ trả về một giá trị kiểu bool, tương ứng với việc hai danh sách này có bằng nhau hay

không.

Việc so sánh được tiến hành trên từng phần tử ởvịtrí tương ứng nhau.

Lưu ý:

• Ngoài ra còn có các phép toán so sánh khác cũng có thểthực hiện trên danh sách: <,

>, <=, >=, !=.

c. Phương thức

Thêm một phần tử vào danh sách

Cú pháp:

.insert(, );

.push_front();

.push_back();

Trong đó:

• Phương thức thứ nhất chèn một phần tử vào một vị trí bất kì của danh sách, vị

trí chèn được chỉ ra bởi tham số thứ nhất.

• Phương thức thứ hai chèn một phần tử vào đầu danh sách

• Phương thức thứ ba chèn một phần tử vào cuối danh sách.

Ví dụ:

List myList;

myList.push_front(7);

sẽ chèn vào đầu danh sách myList một phần tử có giá trị là 7.

Xoá đi một phần tử

Cú pháp:

.erase();

.pop_front();

.pop_back();

84 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

Trong đó:

• Phương thức thứ nhất xóa một phần tử ở một vị trí bất kì của danh sách, vị trí

xoá được chỉ ra bởi tham số thứ nhất.

• Phương thức thứ hai xoá một phần tử ở đầu danh sách

• Phương thức thứ ba xoá một phần tử ở cuối danh sách.

Ví dụ:

List myList;

cout << myList.pop_front();

sẽ in ra màn hình phần tử đầu của danh sách myList.

Kiểm tra tính rỗng của danh sách

Cú pháp:

.empty();

trả về giá trị bool, tương ứng với trạng thái hiện tại của biến danh sách là rỗng hay

không.

Xem kích thước danh sách

Cú pháp:

.size();

Ví dụ:

cout << myList.size();

sẽ in ra màn hình kích cỡ (số lượng các phần tử) của danh dách.

Xem nội dung một phần tử

Cú pháp:

.get();

.next();

Trong đó:

• Phương thức thứ nhất trả về phần tử ở vị trí hiện tại của con chạy

85 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

• Phương thức thứ hai trả về phần tử tiếp theo, và con chạy cũng di chuyển sang

phần tử đó.

Ví dụ:

List myList;

cout << myList.get();

sẽ in ra màn hình nội dung phần tử thứ nhất của danh sách myList.

Ví dụ áp dụng – Quản lý nhân viên văn phòng.

#include

#include

#include

#include

typedef struct{

char name[25]; // Tên nhân viên

int age; // Tuổi nhân viên

float salary; // Lương nhân viên

} Employee;

void main(){

clrscr();

List myList;

int function;

do{

clrscr();

cout << “CAC CHUC NANG:” << endl;

cout << “1: Them mot nhan vien” << endl;

cout << “2: Xoa mot nhan vien” << endl;

86 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

cout << “3: Xem tat ca cac nhan vien trong phong” << endl;

cout << “5: Thoat!” << endl;

cout << “=======================================” <<

endl;

cout << “Chon chuc nang: ” << endl;

cin >> function;

switch(function){

case ‘1’: // Thêm vào ds

int position;

Employee employee;

cout << “Vi tri can chen: ”;

cin >> position;

cout << “Ten nhan vien: ”;

cin >> employee.name;

cout << “Tuoi nhan vien: ”;

cin >> employee.age;

cout << “Luong nhan vien: ”;

cin >> employee.salary;

myList.insert(position, employee);

break;

case ‘2’: // Lấy ra khỏi ds

int position;

cout << “Vi tri can xoa: ”;

cin >> position;

Employee result = myList.erase(position);

87 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

if(result != NULL){

cout << “Nhan vien bi loai: ” endl;

cout << “Ten: ” << result.name << endl;

cout << “Tuoi: ” << result.age << endl;

cout << “Luong: ” << result.salary << endl;

}

break;

case ‘3’: // Duyệt ds

cout << “Cac nhan vien cua phong:” << endl;

Employee result = myList.front();

do{

cout << result.name << “ ”

<< result.age << “ ”

<< result.salary << endl;

result = myList.next();

}while(result != NULL);

break;

}while(function != ‘5’);

return;

}

Chương 4: Xử lý đồ họa căn bản

4.1. Winform căn bản

4.1.1. Giới thiệu căn bản về ứng dụng winform với C++ .Net

Lập trình winform là một trong những cách phát triển ứng dụng phổ biến nhất hiện

nay. Ứng dụng winform có thể xem như là một tập hợp các form, mỗi form lại gồm

các control cần thiết (ô nhập văn bản, danh sách lựa chọn, nút bấm, tab…) nhằm tạo

88 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

một giao diện người dùng thân thiện nói cách khác là nơi hiển thị và tiếp nhận các

thông tin tương tác giữa người sử dụng và chương trình. Các form này có thể hoạt

động độc lập hoặc có quan hệ tương tác với nhau. Đa số các ứng dụng trên desktop

windows là các ứng dụng winform (phần mềm office, windows media player, các phần mềm quản lý…).

Form ví dụ gồm một số control (điều khiển) căn bản

Ngày nay việc phát triển một ứng ứng dụng winform trở lên cực kỳ dễ dàng thông

qua bộ công cụ Visual Studio cụ thể trong tài liệu này tôi đề cập tới bộ Visual Studio

2010, và tất nhiên đi kèm với nó là nền tảng .Net vô cùng mạnh mẽ, ngày càng được

nâng cấp, cải tiến qua từng phiên bản với sự hỗ trợ của gã khổng lồ Microsoft.

Như đã nói ở trên, một ứng dụng winform là tập hợp của các form. Mỗi form trong

ứng dụng lại chứa các control, form được chia làm 2 phần:

- Phần Designer: hiển thị form và các control hay nói cách khác đây chính là phần

giao diện của chương trình.

89 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

Form Designer đơn giản của form Đăng Nhập

- Phần Code Behind: phần code xử lý cho các sự kiện, các tương tác của người dùng.

Lập trình winform cũng có thể xem như là một hình thức của lập trình hướng sự kiện vì tất cả mọi hành động, tương tác của người dùng được chương trình tiếp nhận và xử lý thông qua các sự kiện. Form và các control đều được hỗ trợ rất nhiều sự kiện cho lập trình viên dễ dàng sử dụng, điều khiển chúng trong ứng dụng. Một form được chúng ta tạo ra là một lớp được kế thừa từ lớp Windows::Forms::Form chính vì vậy khi chúng ta tạo ra một form nó đã kế thừa rất nhiều thuộc tính và phương thức từ lớp Form, và tất nhiên đi kèm không thể thiếu với nó là các sự kiện. Một số sự kiện, thuộc tính này có thể được tìm thấy trong khung Properties (chọn form click chuột phải,

90 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

chọn properties hoặc chọn form nhấn F4). Bảng dưới đây liệt kê một số thuộc tính và

sự kiện thông dụng của form:

Thuộc tính Ý nghĩa

Name Tên form

Text Tiêu đề form

AcceptButton Thiết lập nút được nhấn khi ta nhấn phím Enter

CancelButton Tthiết lập nút được nhấn khi ta nhấn phím Esc

BackColor Thiết lập màu nền cho form

BackgroundImage Thiết lập hình nền cho form

Icon Thiết lập icon cho form

Opacity Thiết lập độ mờ của form

ShowIcon Có cho phép hiện icon của form hay không

ShowInTaskar Có hiện biểu tượng form tại thanh taskbar hay không

Size Thiết lập kích thước của form

StartPosition Thiết lập vị trí khi form khởi chạy

WindowState Thiết lập trạng thái của form khi khởi chạy

Sự kiện Ý nghĩa

Activited Định nghĩa phương thức sẽ được thực hiện khi form được

activited

Click Định nghĩa phương thức sẽ được thực hiện khi form được

click

KeyDown Định nghĩa phương thức sẽ được thực hiện khi ta nhấn một

phím

KeyPress Định nghĩa phương thức sẽ được thực hiện khi ta nhấn một

phím và nhả ra

KeyUp Định nghĩa phương thức sẽ được thực hiện khi ta nhả một

phím

Load

Định nghĩa phương thức sẽ được thực hiện khi người sử dụng gọi tới form, và form được hiện ra

Các bước cơ bản tạo một ứng dụng winform

- Tạo mới một Project

Bước 1: Vào menu File -> New->Project

91 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

Bước 2: Hộp thoại New Project xuất hiện, tại ô Recent Tamplate chọn Visaul C++, tiếp

theo chọn Windows Form Application, đặt tên cho Project tại ô Name và nhấn OK

Kết quả sẽ được một Project bao gồm 1 form mặc định tên là Form1 như hình dưới.

92 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

- Thêm một form mới vào Project

Bước 1: Tại khung Solution Explorer click chuột phải vào tên project → Add →

New Item

Hộp thoại Add New Item hiện ra click chọn Windows Form, đặt tên cho form và nhấn Add

93 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

- Chọn form chạy đầu tiên khi bắt đầu ứng dụng

Như ta đã biết, trong một ứng dụng sẽ có thể có nhiều form và chúng ta có thể

chọn một form bất kỳ trong số đó là form khởi động ứng dụng tức là form đó sẽ

chạy đầu tiên khi ứng dụng của ta được bắt đầu, để làm được điều đó chúng ta thực

hiện như sau:

Tại khung Solution Explorer, tìm đến thư mục Source Files, mở file

ten_project_.cpp, tìm tới dòng Application::Run(gcnew Form1()); thay Form1

bằng tên form muốn chạy đầu tiên.

94 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

95 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

4.1.2. Một số điều khiển cơ bản

- Button:

là điều khiển cho phép người dùng click để thực hiện một hành động, với điều khiển này ta thường quan tâm nhất tới sự kiện click và thuộc

tính text. Để viết hàm xử lý cho sự kiện click của button, tại cửa sổ desinger của

form ta click đúp vào button, Visual studio sẽ chuyển tới cửa sổ viết code xử lý cho

sự kiện click vào button, để viết cho các sự kiện khác của button ta tham khảo cửa sổ Properties.

- CheckBox: điều khiển cho phép người dùng tích chọn

một số điều kiện. Trong một nhóm các checkbox chúng ta có thể chọn cùng lúc

nhiều checkbox.

- ComboBox:

hiển thị một danh sách xổ xuống các dọng dữ liệu cho phép người dùng lựa chọn, chỉ được lựa chọn một dòng và có thể nhập liệu

như textbox

- Label: điều khiển dùng để hiển thị nhãn văn bản

- PictureBox: điều khiển cho phép người dùng hiển thị

hình ảnh trên form

- RadioButton: tương tự checkbox tuy nhiên trong một

nhóm chỉ có một radiobutton được lựa chọn

- TextBox: điều khiển cho người dùng nhập liệu văn bản, thuộc tính

cần quan tâm nhất là Name và Text.

- Panel: là một khung để chứa các điều khiển khác, hoặc có thể là một vùng để vẽ

- ColorDialog: hộp thoại cho phép người dùng chọn màu sắc

- FontDialog: hộp thoại cho phép người dùng chọn font chữ

- OpenFileDialog: hộp thoại hỗ trợ người dùng duyệt mở các file trong máy tính

- SaveFileDialog: hộp thoại hỗ trợ người dùng lưu một file từ ứng dụng vào máy

tính

96 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

4.2. Tổng quan về đồ họa trong winform

Trong phần 4.1 chúng ta đã được làm quen với winform và các điều khiển căn

bản trên winform. Trong phần này, chúng ta sẽ đi sâu hơn về đồ họa trong winform,

làm thế nào để vẽ được các đối tượng đồ họa (điểm, đoạn thẳng, hình tròn, hình chữ nhật...), hình ảnh, văn bản…lên form.

.Net framwork sử dụng một giao diện lập trình ứng dụng (API) được nâng cấp

lên từ Windows Graphics Device Interface (GDI) gọi à GDI+. GDI+ cung cấp một thư

viện các lớp cho phép chúng ta làm việc với các đối tượng đồ họa hai chiều như là các đối tượng hình học cơ bản, hiển thị văn bản, hình ảnh và in ấn. Tuy nhiên, mặc dù GDI

+ được cải thiện nhiều so với GDI ban đầu, nhưng nó vẫn chỉ là một thư viện đồ họa

hai chiều đơn giản, không có các tính năng cao cấp như diễn hoạt hay các hiệu ứng ba

chiều.

GDI+ cung cấp các chức năng xử lý các đối tượng đồ họa thông qua các

NameSpace sau:

1. System::Drawing cung cấp các chức năng vẽ căn bản 2. System::Drawing::Drawing2D cung cấp các chức năng cao cấp hơn cho việc

thao tác với các đối tượng đồ họa 2D

3. System::Drawing::Imaging cung cấp các phương thức làm việc với ảnh 4. System::Drawing::Text cung cấp các phương thức làm việc với văn bản 5. System::Drawing::Printing giúp xử lý in ấn

4.3. Làm quen với các đối tượng đồ họa

4.3.1. NameSpace System::Drawing

NameSpace System::Drawing cung cấp cách thức truy cập tới các chức năng

đồ họa căn bản trong GD+. Dưới đây là bảng liệt kê danh sách các lớp chính trong

namespace này:

Tên lớp Mô tả

Bitmap

Làm việc với một bitmap. Lớp này có thể làm việc với nhiều định dạng ảnh khác nhau như: BMP, GIF, và JPG

Lớp này được sử dụng để tô màu cho hình

Brush

Lớp màu sắc

Color

97 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

Thao tác với font chữ

Font

Đây sẽ là lớp thực hiện mọi thao tác đồ họa

Graphics

Làm việc với một biểu tượng (icon)

Icon

Sử dụng để vẽ hình ( hình rỗng chưa tô màu)

Pen

2 lớp được sử dụng để thao tác với điểm

Point

Thao tác với hình chữ nhật

Rectangle

Thao tác với một vùng

Region

Trình bày một kích thước

Size

Giúp làm việc với các thông tin trình bày văn bản

StringFormat

Tương tự lớp Brush tuy nhiên nó sử dụng hình ảnh để tô màu

TextureBrush

4.3.2. Lớp Graphics

Khi cần vẽ lên một form chúng ta cần phải xem xét tới rất nhiều vấn đề. Ví dụ

như, vẽ cái gì, vẽ màu như thế nào? Nó sẽ được hiển thị trên loại thiết bị nào? Màu

sắc, độ phân giải của thiết bị ra sao?... Tuy nhiên không cần quá lo lắng vì GD+ đã

giúp bạn giải quyết được các vấn đề đó thông qua lớp Graphics, lớp này sẽ đại diện

như một vùng vẽ lý tưởng cho chúng ta. Lớp Graphics cung cấp rất nhiều thao tác hỗ

trợ chúng ta trong việc vẽ (trình bày) và hiển thị các đối tượng đồ họa (điểm, đường,

đa giác...).

Tạo một đối tượng Graphics: Một đối tượng Graphics được tạo ra mà không sử dụng

bất kì phương thức khởi tạo nào của lớp Graphics, mà nó sẽ sử dụng phương thức tạo

hoặc thuộc tính của các đối tượng mà nó được gắn vào. Vì một đối tượng Graphics được tạo ra luôn phải được gắn với một đối tượng nào đó. Ví dụ như gắn với một form, một panel, picturebox…nghĩa là khi tạo ra một đối tượng Graphics thì chúng ta cần phải chỉ ra được rằng đối tượng này sẽ thực hiện việc vẽ của nó tại đâu.

Tạo một đối tượng gắn với form:

Graphics^ pg = myForm->CreateGraphics();

Tạo một đối tượng mà nó sẽ vẽ trên một panel:

Graphics^ pg = myPanel->CreateGraphics(); 98 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

4.3.3. Vẽ

Các thao tác vẽ cơ bản được thực hiện bằng cách sử dụng các đối tượng Pen (bút vẽ)

và đối tượng Brush (cọ tô màu). Trong khi các đối tượng Pen được sử dụng để vễ đường và các đường nét bao quay một hình thì các đối tượng Brush dùng để tô màu

cho phần trong của các hình đó.

Đối tượng Pen

Cách tạo một đối tượng Pen căn bản

// Tạo một bút màu đen với độ rộng nét vẽ là 1pixel (mặc định)

Pen^ pen1 = gcnew Pen(Color::Black);

// Tạo một bút màu đỏ với động rộng nét vẽ là 2pixel

Pen^ pen2 = gcnew Pen(Color::Red, 2.0);

Ta thấy việc tạo ra 2 bút ở ví dụ trên có sử dụng một tham số để định nghĩa màu vẽ

cho chúng, ở 2 ví dụ trên ta sử dụng thuộc tính tĩnh để thể hiện 2 màu đỏ và đen, bạn

có thể tùy chỉnh màu sắc của đối tượng này bằng cách sử dụng đối tượng thuộc lớp

Color.

Đối tượng Brush

Có rất nhiều loại cọ tô màu khác nhau, tất cả chúng đều kế thừa từ lớp Brush. Trong đó, loại cọ SolidBrush là loại cọ đơn giản nhất, nó sẽ tiến hành tô màu vùng

được tô với màu thuần nhất (soilid color).

// tạo một cọ tô màu xanh da trời

SolidBrush^ br1 = gcnew SolidBrush(Color::Blue);

Một đối tượng thuộc lớp TextureBrush lại sử dụng một ảnh như là chất liệu để tô lên

các đối tượng cần tô. Nếu ảnh nhỏ hơn hình cần tô thì nó sẽ tiến hành tô như kiểu lát

gạch.

// tạo một TextureBrush sẽ được tô theo kiểu lát gạch

TextureBrush^ br2 = gcnew TextureBrush(gcnew Bitmap("brush.bmp"), WrapMode::Tiled);

4.3.4. Các thao tác vẽ cơ bản

Chúng ta đã có bút vẽ, cọ tô màu, trong phần này chúng ta sẽ đi tìm hiểu về các thao

tác vẽ cơ bản. Lớp Graphics cung cấp cho chúng ta rất nhiều phương thức vẽ, bảng dưới đây là danh sách một số phương thức vẽ phổ biến, hay sử dụng nhất.

99 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

Phương thức Mô tả

Clear Tô màu kín toàn bộ vùng vẽ

DrawClosedCurve, FillClosedCurve Vẽ và tô màu một đường cong kín

DrawCurve Vẽ đường cong

DrawEllipse, FillEllipse Vẽ và tô màu hình elip

DrawIcon Vẽ một biểu tượng

DrawImage Vẽ một hình ảnh

DrawLine Vẽ đường thẳng

DrawPolygon, FillPolygon Vẽ và tô màu đa giác

DrawRectangle, FillRectangle Vẽ và tô màu hình chữ nhật

DrawString Vẽ một chuỗi văn bản

Ví dụ:

//tạo đối tượng đồ họa

Graphics^ gr=this->CreateGraphics(); //tạo bút vẽ

Pen^ p = gcnew Pen(Color::Black); //tạo cọ tô màu

SolidBrush^ br= gcnew SolidBrush(Color::Blue); //vẽ đường thẳng

gr->DrawLine(p,0,0,200,200); //vẽ hình elip

gr->DrawEllipse(p, 20, 20, 60, 80); //tô màu hình elip

gr->FillEllipse(br,20,20,60,80); //vẽ hình chữ nhật

gr->DrawRectangle(p,50,50,60,100); //tô màu hình chữ nhật

gr->FillRectangle(br,100,100,60,100);

100 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

//vẽ một đường cong kín

PointF point1 = PointF(50.0F,50.0F); PointF point2 = PointF(100.0F,25.0F);

PointF point3 = PointF(200.0F,5.0F); PointF point4 = PointF(250.0F,50.0F);

PointF point5 = PointF(300.0F,100.0F); PointF point6 = PointF(350.0F,200.0F);

PointF point7 = PointF(250.0F,250.0F); array^

curvePoints

=

{point1,point2,point3,point4,point5,point6,point7};

float tension = 1.0F;

FillMode aFillMode = FillMode::Alternate; gr->DrawClosedCurve( p, curvePoints,tension, aFillMode);

//vẽ tập đường thẳng //gr->DrawLines(p, curvePoints );

//vẽ đa giác

Pen^ blackPen = gcnew Pen( Color::Black,3.0f ); // Draw polygon to screen.

gr->DrawPolygon( blackPen, curvePoints );

4.4. Vẽ theo sự kiện

Trong lập trình Winform cung cấp cho chúng ta rất nhiều control khác nhau,

các control này lại được định nghĩa sẵn rất nhiều sự kiện. Vẽ theo sự kiện có thể được

hiểu là chúng ta lập trình sao cho việc vẽ gắn với một sự kiện nào đó xảy ra khi người

dùng tương tác với form và các control thông qua một hành động nào đó (bấm nút,

click chuột, nhấn phím, chọn một danh sách…).

Vẽ theo sự kiện tương tác với một control (nhấn nút)

Với một nút bấm thì sự kiện thường dùng nhất là sự kiện click, ví dụ sau đây

sẽ trình bày cách vẽ theo sự kiện click của một nút bấm

Ví dụ vẽ theo sự kiện nhấn một nút bấm trên form:

Bước 1. Tạo một project C++ Windows Forms Application mới đặt tên là CppDraw.

101 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

Bước 2. Sử dụng khung Properties đổi tiêu đề form thành Drawing hoặc bất kỳ cái gì

bạn muốn, đặt kích thước form khoảng 300x300 pixels.

Bước 3. Từ khung toolbox kéo thả một button vào form, tùy chỉnh các thuộc tính cần

thiết (Name, Text, Location…) cho button.

102 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

Để viết mã lệnh thực thi cho sự kiện click chuột vào nút ta chọn nút, di chuyển sang

khung Properties chọn tab event (biểu tượng hình tia sét), tại đây sẽ hiện ra một danh

sách rất nhiều các event gắn với button này, tìm tới Click và kích đúp vào đó hoặc

cách đơn giản nhất là click đúp vào nút trong form. Sau khi tiến hành thao tác như trên VS sẽ tự sinh ra cho chúng ta một hàm (trong ví dụ này là hàm drawBtn_Click) và tất

cả những gì chúng ta viết trong hàm đó sẽ được thực thi khi nút được bấm.

private: System::Void drawBtn_Click(System::Object^ sender, System::EventArgs^

e) {

// Tạo một đối tượng Graphics Graphics^ pg = CreateGraphics();

// Tạo một bút vẽ Pen^ pen1 = gcnew Pen(Color::Red);

// Vẽ một đường thẳng pg->DrawLine(pen1, 20, 20, 100, 250);

// Hủy đối tượng Graphics delete pg;

}

Vậy kết quả sau khi viết xong code, thực thi chương trình, ta bấm nút thì chương trình

sẽ vẽ cho chúng ta một đường thẳng màu đỏ từ tọa độ (20,20) đến (100,250)

103 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

Chúng ta có thể thay đổi code thực thi trong hàm thành như sau:

// Tạo bút vẽ màu Blue, kích thước 3 pixel Pen^ pen2 = gcnew Pen(Color::Blue, 3.0);

//Tạo nét vẽ kiểu nét đứt pen2->DashStyle = Drawing2D::DashStyle::DashDotDot;

//Vẽ một đoạn thẳng với bút vừa tạo từ (10,120) đến (250,60) pg->DrawLine(pen2, 10, 120, 250, 60);

// Tạo một cọ vẽ màu đỏ SolidBrush^ sb1 = gcnew SolidBrush(Color::Red);

//Vẽ một hình chữ nhật và tô màu cho nó bằng cọ vẽ vừa tạo (không vẽ viền) pg->FillRectangle(sb1, 60,30, 40,40);

// Vẽ một hình chữ nhật với bút màu đỏ (viền đỏ), và trong tô màu vàng SolidBrush^ sb2 = gcnew SolidBrush(Color::Yellow); pg->FillRectangle(sb2, 90, 40, 45, 45);

pg->DrawRectangle(pen1, 90, 40, 45, 45); // Vẽ một hình elip và tô màu xanh

SolidBrush^ sb3 = gcnew SolidBrush(Color::Green);

pg->FillEllipse(sb3, 30,100, 65, 50);

và kết quả sau khi click

104 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

Vẽ theo sự kiện tương tác với chuột

Để biết được .Net cung cấp cho chúng ta những sự kiện tương tác nào với

chuột ta chọn khung Properties, chọn tab Event kéo xuống phí dưới ta sẽ nhìn thầy một

loạt các sự kiện về Mouse liên quan tới đối tượng đang được chọn bên form nghĩa là các sự kiện của chuột này sẽ xảy ra khi ta làm hành động tương ứng với đối tượng

đang được chọn bên form (có thể là form hoặc các điều khiển trong form). Để hiểu rõ

hơn về việc vẽ theo sự kiện tương tác với chuột chúng ta sẽ đi làm một ví dụ.

Ví dụ vẽ đoạn thẳng với tọa độ phụ thuộc vào tọa độ chuột trên đối tượng:

Ta tiếp tục làm việc trên project đã được ta ra ở phần trên. Ta khai báo thêm

hai biến thành viên theo kiểu Point để lưu tọa đọ điểm đầu và điểm cuối của đoạn

thẳng.

Trong các sự kiện về chuột được liệt kê trong khung Properties có sự kiện

MouseDown xảy ra khi ta nhấn chuột và sự kiện MouseUp xảy ra khi ta nhả chuột,

chúng ta sẽ sử dụng 2 sự kiện này.

105 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

Code thực hiện cho sự kiện MouseDown: Khi nhấn chuột ta sẽ lấy tọa độ hiện tại của

chuột trên form và gán cho điểm p1

private:

System::Void

Form1_MouseDown(System::Object^

sender,

System::Windows::Forms::MouseEventArgs^ e) {

p1.X = e->X;//Tọa độ X của chuột được gán cho X của điểm p1 p1.Y = e->Y;// Tọa độ Y của chuột được gán choY của điểm p1

}

Tương tự với sự kiện MouseUp và sau khi lấy được tọa độ khi nhả chuột gán cho p2 ta

tiến hành vẽ đoạn thẳng ngay với điểm bắt đầu là p1 và kết thúc ở p2

private:

System::Void

Form1_MouseUp(System::Object^

sender,

System::Windows::Forms::MouseEventArgs^ e) {

p2.X = e->X; p2.Y = e->Y;

Graphics^ gr = CreateGraphics();

Pen^ pen1 = gcnew Pen(Color::Black); gr->DrawLine(pen1, p1.X, p1.Y, p2.X, p2.Y);

//gr->Dispose(); delete gr;

}

106 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

4.5. Sử dụng màu sắc, fonts

4.5.1. Sử dụng màu sắc

Vấn đề Color (màu sắc) được trình bày trong cấu trúc

System::Drawing::Color và được tạo lên từ 4 thành phần R, G, B và A. Ba thành phần

đầu tiên đại diện cho 3 yếu tố đỏ (R), xanh lá cây (G), xanh da trời (B) của một màu

theo hệ màu RGB, các giá trị này nằm trong khoảng từ 0 đến 255. Thành phần A trình

bày độ trong suốt của màu sắc và cũng có giá trị chạy từ 0 (trong suốt hoàn toàn) đến

255 (mờ hoàn toàn). Cũng giống như Graphics, cấu trúc Color không có hàm khởi tạo.

Chúng ta có thể tạo ra một thể hiển của cấu trúc Color bằng 3 phương thức sau đây:

- FromArgb: tạo ra một Color từ tập các giá trị A, R, G, B.

// Tạo một đối tượng màu đỏ với độ trong suốt là 255 (mờ đục hoàn toàn)

Color c1 = Color::FromArgb(255, 255, 0, 0);

- FromKnownColor: tạo ra một Color từ thành phần KnownColor. Lớp Color định

nghĩa ra một số lượng rất lớn các thuộc tính để trình bày các màu sắc được định nghĩa

bởi hệ thống bao gồm một dãy các màu từ AliceBlue cho đến YellowGreen. Kiểu liệt kê KnownColor định nghĩa một danh sách các màu trong hệ thống, nó bao gồm các màu chuẩn được định nghĩa sẵn, chính là các màu sắc được sử dụng trong Windows GUI như ActiveCaption và WindowText. Các giá trị màu sắc này có thể được thay đổi nếu người dùng điều chỉnh màu sắc desktop trong Control Panel.

// Khởi tạo một màu chuẩn từ KnownColor

Color c2 = Color::FromKnownColor(KnownColor::Cornsilk);

- FromName: tạo một Color với tham số là tên màu

//Tạo một màu với tên là Blue

107 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

Color c1 = Color::FromName( "Blue" );

//Thêm một cách nữa để tao ra một màu

Color c3 = Color::Cornsilk;

Chú ý rằng khi một màu đã được tạo ra thì không thể thay đổi giá trị của nó. Nếu cần

thay đổi một màu, bạn sẽ phải tạo ra một màu mới dựa trên một màu đã có.

Ví dụ:

// tạo ra một màu đỏ

Color c4 = Color::FromArgb(255, 255, 0, 0);

// tạo ra một màu khác dựa trên màu c4 và thay đổi thông số độ trong suốt

Color c5 = Color::FromArgb(127, c4.R, c4.G, c4.B);

Ngoài các cách sử dụng màu sắc ở trên thì trong lập trình winform còn hỗ trợ chúng ta một cách sử dụng màu sắc rất trực quan và thuận tiện cho người sử dụng đó là sử dụng

control hộp thoại màu ColorDialog.

- Cú pháp khai báo và gọi một ColorDialog như sau:

//Khai báo

ColorDialog^ MyDialog = gcnew ColorDialog; //Gọi nó ra

MyDialog->ShowDialog();

108 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

- Sau khi ColorDialog được gọi ra, người sử dụng chọn màu sắc ưng ý và nhấn ok thì

ta có thể sử dụng màu sắc vừa được chọn đó thông qua thuộc tính quan trọng nhất của

ColorDialog đó là thuộc tính: Color

Ví dụ sử dụng ColorDialog:

private: System::Void button1_Click(System::Object^ sender, System::EventArgs^

//Tạo đối tượng hộp thoại màu

e) {

ColorDialog^ MyDialog = gcnew ColorDialog; //tạo đối tượng đồ họa trên panel1

Graphics^ gr=panel1->CreateGraphics();

//Sau khi chọn xong màu và nhấn ok sẽ thực hiện tô toàn bộ vùng vẽ theo màu chọn

(

MyDialog->ShowDialog()

==

if ::System::Windows::Forms::DialogResult::OK )

gr->Clear(MyDialog->Color);

{

}

}

4.5.2. Sử dụng fonts

Trong namspace System::Drawing có cung cấp cho chúng ta lớp Font để làm

việc với font chữ. Một đối tượng của lớp Font sẽ trình bình một font với một số thuộc tính như tên, kích cỡ hay kiểu font. Bảng dưới đây liệt kê một số thuộc tính của lớp

Font, các thuộc tính này là thuộc tính chỉ đọc (read-only) nghĩa là khi đã tạo ra đối

tượng Font với các thuộc tính được khai báo thì các thuộc tính này không thể thay đổi

được nữa.

Thuộc tính Mô tả

Bold Có giá trị True nếu style của font là in đậm (Bold)

FontFamily Trả về họ font của font hiện tại

Height Trả về độ cao

Italic Có giá trị True nếu style của font là in nghiêng (Italic)

Name Trả về tên font

Size Kích thước font

109 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

Strikeout Trả về true nếu font có style là kiểu gạch giữa

Style Trả về thông tin kiểu (style) của font

Underline Trả về true nếu font có style là kiểu gạch chân

Unit Trả về kiểu đơn vị đo của font. Mặc định là pixels

Style của font có thể được kết hợp từ nhiều giá trị thuộc tập hợp FontStyle, nó bao gồm

Bold, Italic, Regular, Strikeout, và Underline. Một font được tạo ra có thể gồm một

hoặc nhiều Style.

Cú pháp khai báo sử dụng một font như sau:

//Khai báo một font, bạn nên khai báo rõ ràng từ NameSpace để tránh nhầm với thuộc tính /font của Form

private: System::Drawing::Font^ font1;

//Tạo font với một style

=

gcnew

System::Drawing::Font("Verdana",

8,

FontStyle::Regular,

font1 GraphicsUnit::Millimeter);

//Tạo font với nhiều style ta dùng dấu | để phân biệt giữa các style

font1 = gcnew System::Drawing::Font("Verdana", 8, FontStyle::Regular|FontStyle::Italic,

GraphicsUnit::Millimeter);

trong đó

- “Verdana” là tên font, có rất nhiều tên font ví dụ như “Tahoma”, “Times New

Roman”…

- 8: kích cỡ font

- FontStyle::Regular: kiểu font có thể là Bold, Italic, Regular, Strikeout, và Underline

- GraphicsUnit::Millimeter: xách định đơn vị đo của font nó có thể là các giá trị: Inch, Millimeter, Pixel.

Sau đây là ví dụ vẽ một dòng text theo sự kiện click chuột như ví dụ trước tuy nhiên lần này ta sẽ vẽ ra một dòng text khi chuột phải được click:

System::Void

Form1_MouseUp(System::Object^

sender,

private: System::Windows::Forms::MouseEventArgs^ e)

{ Graphics^ gr = CreateGraphics();

110 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

Pen^ pen1 = gcnew Pen(Color::Black);

//Chuột trái được click

if (e->Button == ::CppDraw::MouseButtons::Left)

{ // vẽ đoạn thẳng

p2.X = e->X; p2.Y = e->Y;

gr->DrawLine(pen1, p1.X,p1.Y, p2.X,p2.Y); }

//Nếu chuột phải được click

else if (e->Button == ::CppDraw::MouseButtons::Right)

{ // Vẽ text với font1, chữ màu đen, tại vị trí click chuột phải

gr->DrawString(L"Right click Text", font1, Brushes::Black, (float)e->X, (float)e->Y);

} delete gr;

}

Tương tự như màu sắc, đối với việc sử dụng font chữ, lập trình winform cũng hỗ trợ chúng ta một cách sử dụng trực quan thông qua hộp thoại font

111 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

- Cú pháp khai báo và gọi một FontDialog như sau:

//Khai báo FontDialog^ MyDialog = gcnew ColorDialog;

//Gọi nó ra

MyDialog->ShowDialog();

- Sau khi FontDialog được gọi ra, người sử dụng chọn font chữ và nhấn ok thì ta có thể sử dụng font đó thông qua thuộc tính Font của ColorDialog, ngoài ra FontDigalog còn

cho phép chúng lựa chọn và sử dụng màu sắc (một số màu cơ bản).

Ví dụ sử dụng FontDialog:

//khai báo

FontDialog^ myFd=gcnew FontDialog(); //cho phép chọn màu sắc

myFd->ShowColor=true; //tạo đối tượng đồ họa

Graphics^ gr=panel1->CreateGraphics(); tạo cọ tô màu với màu lấy từ Fontdiglog

112 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

SolidBrush^ br= gcnew SolidBrush(myFd->Color);

//Sau khi chọn màu xong nhấn Ok sẽ vẽ chuỗi if ( myFd->ShowDialog() == ::System::Windows::Forms::DialogResult::OK )

{ gr->DrawString("Day la vi du ve font chu",myFd->Font,br,20,50);

}

4.6. Thao tác với hình ảnh

Để làm việc với hình ảnh chúng ta sử dụng lớp Bitmap được cung cấp sẵn trong

System::Drawing. Lớp này hỗ trợ chúng ta trong việc trình bày và thao tác với một số

định dạng ảnh như jpg, png, gif… Lớp Bitmap là một bản tóm lược của GDI + bitmap, nó bao gồm tập các dữ liệu pixel của hình ảnh và thuộc tính của nó. Một bitmap là một đối tượng

được sử dụng để làm việc với ảnh như một tập hợp các điểm ảnh (pixel). Bảng dưới đây liệt kê một số thuộc tính và phương thức phổ biến của lớp Bitmap.

Thuộc tính

Mô tả

Height HorizontalResolution Palette PhysicalDimension PixelFormat RawFormat Size VerticalResolution Width

Trả về chiều cao bằng của ảnh (pixel) Trả về độ phân giải ngang (pixel/inch) Trả về hoặc thiết lập bảng màu Trả về kích thước của ảnh Trả về định dạng điểm ảnh Trả về định dạng ảnh Trả về chiều rộng và chiều cao của ảnh (pixel) Trả về độ phân giải dọc (pixel/inch) Trả về độ rộng của ảnh (pixel)

Phương thức

113 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

FromFile FromHbitmap FromHicon FromResource FromStream GetBounds GetPixel GetThumbnailImage

IsAlphaPixelFormat

Tạo ra một ảnh từ file Tạo ra một ảnh Bitmap từ một Windows handle Tạo ra một ảnh Bitmap từ một Windows handle thành icon. Tạo ra một ảnh Bitmap từ một Windows resource. Tạo ra một ảnh Bitmap từ một data stream Trả về đường bao của ảnh Trả về một điểm ảnh ( Color) Tạo ảnh thumbail Trả về giá trị để biểu thị xem pixel có chứa thông tin alpha hay không Khóa một Bitmap trong bộ nhớ hệ thống Tạo độ trong suốt mặc định cho ảnh Quay, lật ảnh Lưu ảnh Thiết lập một điểm ảnh cho ảnh Thiết lập độ phân giải cho ảnh Mở khóa ảnh này ra khỏi bộ nhớ hệ thống

LockBits MakeTransparent RotateFlip Save SetPixel SetResolution UnlockBits Ví dụ: Vẽ một ảnh lên form // Vẽ một ảnh của tên là ramp1.gif, ảnh này đặt cùng thư mục với file nguồn chương trình Bitmap^ bmp = gcnew Bitmap(L"ramp1.gif");

gr->DrawImage(bmp, 10,10);//Vẽ ảnh tại vị trí 10,10

Như đã trình bày ở trên, một đối tượng của lớp Bitmap sẽ trình bày một ảnh như là

một tập hợp các pixel, trong khi xử lý ảnh số ta thường thao tác xử lý ảnh dựa trên các pixel này, để lấy thông tin của một điểm ảnh ta dùng phương thức GetPixel, để thiết lập một điểm ảnh (pixel) cho ảnh ta sử dụng SetPixel. Ví dụ sau đây minh họa cho việc load một ảnh, đọc từng điểm ảnh của nó và thay thành điểm ảnh khác: private: Bitmap^ image1; void Button1_Click( System::Object^ /*sender*/, System::EventArgs^ /*e*/ )

{

114 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông

Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện

try

{ // Đọc ảnh từ máy tính

image1 = gcnew Bitmap( "C:\\Documents and Settings\\All Users\\" "Documents\\My Music\\music.bmp",true );

int x; int y;

// Duyệt toàn bộ điểm ảnh for ( x = 0; x < image1->Width; x++ )

{ for ( y = 0; y < image1->Height; y++ )

{ Color pixelColor = image1->GetPixel( x, y );

Color newColor = Color::FromArgb( pixelColor.R, 0, 0 ); image1->SetPixel( x, y, newColor );

} }

// Hiển thị ảnh lên picturebox PictureBox1->Image = image1;

} catch ( ArgumentException^ )

{ MessageBox::Show( "There was an error."

"Check the path to the image file." ); }

}

115 Bộ môn Truyền thông đa phương tiện – Trường Đại học Công nghệ thông tin và truyền thông