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
}
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
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
}
};
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
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
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
}
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
{
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
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
}
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
}
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
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
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
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
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
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
}
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
}
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
}
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 { 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ử 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 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 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 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 // các phần tửcó kiểu int 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 hoặc: #include a. Hàm khởi tạo 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 • Khởi tạo bằng một mảng các đối tượng phần tử: Set • Khởi tạo bằng một đối tượng thuộc lớp tập hợp khác: 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 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 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>; 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 iterator insert( 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 ý: 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 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 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&); 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 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 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; 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 for(i=mySet.begin(); i cout << mySet[i] << “ ”; break; }while(function != ‘5’); return; } 2.5.3 Lớp chuỗi kí tự 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 • Hàm khởi tạo từ một mảng các kí tự: String 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. 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à “+=” 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 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: 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: 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: 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: 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. 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: • Đổi chuỗi thành các kí tự thường: 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; 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 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(); 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 • Khởi tạo bằng một ngăn xếp khác, có cùng kiểu phần tử: Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện 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 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ử: 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ử: sẽ trả về phần tử đang nằm ở đỉnh ngăn xếp. Kiểm tra tính rỗng: 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: 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 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: 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 • Khởi tạo bằng một hàng đợi khác, có cùng kiểu phần tử: 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 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ử: sẽ thêm một phần tử có kiểu T vào cuối hàng đợi. 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ử: sẽ trảvề phần tử đang nằm ở đỉnh đầu hàng đợi. • Kiểm tra tính rỗng: 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: 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 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; 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 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: Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện #include hoặc: #include 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 • Khởi tạo tửmột danh sách cùng kiểu: List • Khởi tạo từmột mảng các phần tử: List 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 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 Toán tử so sánh bằng “==” Cú pháp: 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: 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.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: 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 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: 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: 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: Trong đó: • Phương thức thứ nhất trả về phần tử ở vị trí hiện tại của con chạy 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 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 int function; do{ clrscr(); cout << “CAC CHUC NANG:” << endl; cout << “1: Them mot nhan vien” << endl; cout << “2: Xoa mot nhan vien” << endl; 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); 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 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. Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện - 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, 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 Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện 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 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. Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện 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 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ả 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 Lớp màu sắc 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ữ Đây sẽ là lớp thực hiện mọi thao tác đồ họa Làm việc với một biểu tượng (icon) Sử dụng để vẽ hình ( hình rỗng chưa tô màu) 2 lớp được sử dụng để thao tác với điểm Thao tác với hình chữ nhật Thao tác với một vùng Trình bày một kích thước Giúp làm việc với các thông tin trình bày văn bản Tương tự lớp Brush tuy nhiên nó sử dụng hình ảnh để tô màu 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. 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 Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện 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. 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. 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. 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) 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: và kết quả sau khi click 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. 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 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 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. - 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. - 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 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 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: 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: 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 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: 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: Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện 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 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: - 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: Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện 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 Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện 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*/ ) Bài giảng Kỹ thuật lập trình – Ngành Truyền thông đa phương tiện59
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
Form Designer đơn giản của form Đăng Nhập
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
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ướ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
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
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
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
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
Bitmap
Brush
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
Font
Graphics
Icon
Pen
Point
Rectangle
Region
Size
StringFormat
TextureBrush
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
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
//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 );
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
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
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;
}
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
// 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);
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
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
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
}
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
// 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);
// Khởi tạo một màu chuẩn từ KnownColor
Color c2 = Color::FromKnownColor(KnownColor::Cornsilk);
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
Color c3 = Color::Cornsilk;
//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
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);
{
}
}
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
//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);
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
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;
}
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
//Khai báo
FontDialog^ MyDialog = gcnew ColorDialog;
//Gọi nó ra
MyDialog->ShowDialog();
//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
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);
}
đượ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
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
{
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
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