Tài liệu Thực hành lập trình windows: TH Lập trình Windows Chương 1-2 
Bài tập chương 1 
1. Viết chương trình hiển thị màn hình như sau: 
Hướng dẫn: 
 1/9 
TH Lập trình Windows Chương 1-2 
 2/9 
TH Lập trình Windows Chương 1-2 
 3/9 
TH Lập trình Windows Chương 1-2 
 4/9 
TH Lập trình Windows Chương 1-2 
2. Từ chương trình câu 1, thay đổi một số thuộc tính của cửa sổ lần lượt như sau: 
 5/9 
TH Lập trình Windows Chương 1-2 
- 
3. Lần lượt thay đổi trạng thái cửa sổ như sau: 
• Nằm ở giữa màn hình, kích thước 640x480 
• Luơn nằm trên các cửa sổ khác . 
• Khơng thể thay đổi kích thước 
• Cửa sổ phĩng to đầy màn hình 
Gợi ý: sử dụng các hàm thuộc lớp CWnd: Create, ShowWindow, SetWindowPos 
Bài tập chương 2 
1. Bài 1 
 6/9 
TH Lập trình Windows Chương 1-2 
Gợi ý: 
- Sử dụng hàm GetClientRect để lấy kích thước vùng Client 
- Chia vùng Client thành 4 phần bằng nhau, mỗi phần là một hình chữ nhật 
- Sử dụng các đối tượng CPen, CBrush và các hàm Ellipse, Chord, Pie, RoundRect, 
SetTextColor, SetBk...
                
              
                                            
                                
            
 
            
                 86 trang
86 trang | 
Chia sẻ: Khủng Long | Lượt xem: 1098 | Lượt tải: 0 
              
            Bạn đang xem trước 20 trang mẫu tài liệu Thực hành lập trình windows, để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên
TH Lập trình Windows Chương 1-2 
Bài tập chương 1 
1. Viết chương trình hiển thị màn hình như sau: 
Hướng dẫn: 
 1/9 
TH Lập trình Windows Chương 1-2 
 2/9 
TH Lập trình Windows Chương 1-2 
 3/9 
TH Lập trình Windows Chương 1-2 
 4/9 
TH Lập trình Windows Chương 1-2 
2. Từ chương trình câu 1, thay đổi một số thuộc tính của cửa sổ lần lượt như sau: 
 5/9 
TH Lập trình Windows Chương 1-2 
- 
3. Lần lượt thay đổi trạng thái cửa sổ như sau: 
• Nằm ở giữa màn hình, kích thước 640x480 
• Luơn nằm trên các cửa sổ khác . 
• Khơng thể thay đổi kích thước 
• Cửa sổ phĩng to đầy màn hình 
Gợi ý: sử dụng các hàm thuộc lớp CWnd: Create, ShowWindow, SetWindowPos 
Bài tập chương 2 
1. Bài 1 
 6/9 
TH Lập trình Windows Chương 1-2 
Gợi ý: 
- Sử dụng hàm GetClientRect để lấy kích thước vùng Client 
- Chia vùng Client thành 4 phần bằng nhau, mỗi phần là một hình chữ nhật 
- Sử dụng các đối tượng CPen, CBrush và các hàm Ellipse, Chord, Pie, RoundRect, 
SetTextColor, SetBkMode, DrawText 
Ví dụ: hàm vẽ Ellipse: 
 7/9 
TH Lập trình Windows Chương 1-2 
2. Bài 2 
Gợi ý: 
- Tính kích thước bitmap, mỗi ảnh sau cĩ kích thước gấp 2 lần ảnh trước 
- Sử dụng hàm BitBlt và StretchBlt. 
 8/9 
TH Lập trình Windows Chương 1-2 
3. Bài 3 
 9/9 
TH Lập trình Windows Chương 3 
Bài tập chương 3 
1. Dùng MFC AppWizard xây dựng ứng dụng sau: 
Chuỗi Hello!MFC cĩ thể chuyển động theo các phương: 
- Sang trái : khi nhấn phím ← 
- Sang phải: khi nhấn phím → 
- Đi lên: khi nhấn phím ↑ 
- Đi xuống: khi nhấn phím ↓ 
- Phím S: Start – Stop chuyển động 
Gợi ý: 
- Sử dụng MDC và các hàm LoadBitmap, StretchBlt để load ảnh nền. 
- Tạo font chữ, sử dụng các hàm SetTextColor, DrawText để xuất chuỗi 
Hello!MFC 
- Chuỗi Hello!MFC nằm trong một frame hình chữ nhật (CRect). Để thay đổi vị trí 
chuỗi, chỉ cần di chuyển frame. Chú ý: Để tính tốn kích thước frame trên, sử 
dụng hàm GetTextMetrics kết hợp với độ dài chuỗi. 
- Khai báo hàm xử lý sự kiện WM_TIMER. Trong hàm OnTimer, cập nhật lại vị trí 
frame tuỳ theo chiều di chuyển đang được chọn 
- Khai báo hàm xử lý sự kiện WM_KEYDOWN. Trong hàm OnKeyDown, cập 
nhật lại chiều chuyển động dựa vào giá trị các phím được nhấn 
1/7 
TH Lập trình Windows Chương 3 
Ví dụ: 
- Khai báo các biến thuộc lớp CChildView: 
- Tạo MDC: 
- Load ảnh nền: 
- Tính kích thước và vị trí frame chứa chuỗi Hello!MFC: 
2/7 
TH Lập trình Windows Chương 3 
- Xử lý sự kiện nhấn phím: 
- Xử lý sự kiện WM_TIMER: 
3/7 
TH Lập trình Windows Chương 3 
2. Dùng MFC AppWizard xây dựng ứng dụng vẽ tự do như sau: 
Yêu cầu: 
- Giữ chuột trái rê vẽ tự do 
- Khi nhấn một trong các phím: 
o ‘R’, ‘G’, ‘B’: nét vẽ chuyển sang màu tượng ứng (Red, Green, Blue) 
o Phím ‘A’, ‘C’: thay đổi con trỏ chuột (tùy ý), phím ‘E’: về dạng mặc định 
o Phím ↑, ↓: thay đổi độ dày nét vẽ ( 1 ≤ nét vẽ ≤ 20) 
o Phím Delete: xĩa màn hình 
- Khi click chuột trên thanh tiêu đề: thay đổi tiêu đề cửa sổ 
Gợi ý: 
- Để thực hiện được thao tác vẽ, sử dụng các hàm xử lý sự kiện nhấn chuột 
(WM_LBUTTONDOWN) để bắt đầu chọn vị trí vẽ và di chuyển chuột 
(WM_MOUSEMOVE ) thực hiện thao tác vẽ. 
4/7 
TH Lập trình Windows Chương 3 
- Thay đổi con trỏ chuột và độ dày nét vẽ thực hiện trong hàm OnKeyDown 
- Để thay đổi tiêu đề khi click trên thanh tiêu đề cửa sổ, xử lý sự kiện 
WM_NCLBUTTONDOWN của lớp CmainFrame 
Ví dụ: 
Trong lớp CChildView, khai báo các biến, các hàm và viết code cho các hàm: 
// CChildView.h 
//Hàm thay đổi con trỏ chuột 
//Nhấn nút trái chuột 
//Di chuyển chuột 
5/7 
TH Lập trình Windows Chương 3 
//Nhấn phím 
//Thay đổi con trỏ chuột 
6/7 
TH Lập trình Windows Chương 3 
//Nhấn nút trái chuột ngồi vùng client 
7/7 
TH Lập trình Windows Chương 4 
Bài tập chương 4 
Dùng MFC AppWizard xây dựng ứng dụng vẽ các đoạn thẳng như sau: 
Yêu cầu: Dùng chuột rê vẽ các đoạn thẳng, cho phép lưu vào file có tên Lines.dat 
- Chúc năng bàn phím: 
 Thay đổi màu vẽ: 
Phím R: đỏ 
Phím G: màu xanh lá 
Phím B: màu xanh dương 
 Lưu vào file: phím S 
 Load từ file: phím L 
 Xoá màn hình: phím C 
Gợi ý: 
 Xây dựng lớp CLine kế thừ từ CObject: 
1/2 
TH Lập trình Windows Chương 4 
 Định nghĩa hàm Serialize: 
 Trong lớp CChildView , khai báo danh sách các đối tượng CLine: 
CArray m_arrLines; 
 Để vẽ một đoạn thẳng, sử dụng các hàm xử lý sự kiện: 
- Nhấn chuột (WM_LBUTTONDOWN): xác định hai điểm của đoạn thẳng, 
đưa đoạn thẳng vào danh sách m_arrLines. 
- Di chuyển chuột (WM_MOUSEMOVE ): cập nhật vị trí điểm thứ hai của 
đoạn thẳng và thực hiện thao tác vẽ. 
- Nhả chuột (WM_LBUTTONUP): kết thúc thao tác vẽ đoạn thẳng. 
 Để lưu và load danh sách các đoạn thẳng đã vẽ, trong lớp CChildView, khai báo 
và định nghĩa hàm Serialize: 
 
2/2 
THỰC HÀNH BÀI DRAWS 
PHẦN I: 
1) Tạo ứng dụng SDI: 
 2) Tạo class CShape 
  Trong file Shape.h, khai báo marco và các biến như sau: 
 Khai báo hàm Draw: 
 Định nghĩa hàm Draw: 
void CShape::Draw(CDC *pDC) 
{ 
 CBrush br (clrBkColor); 
 CBrush *pOldBr = pDC->SelectObject(&br); 
 CPen pen(PS_SOLID, nPenWidth, clrBorderColor); 
 CPen *pOldPen =pDC->SelectObject(&pen); 
 switch (nShape) 
 { 
 case 0://ve doan thang 
 pDC->MoveTo(pLeftTop); 
 pDC->LineTo(pRightBottom); 
 break; 
 case 1://ve ellipse 
pDC-> Ellipse (pLeftTop.x, pLeftTop.y, pRightBottom.x, 
pRightBottom.y); 
 break; 
 case 2://ve hinh chu nhat 
pDC-> Rectangle (pLeftTop.x, pLeftTop.y, pRightBottom.x, 
pRightBottom.y); 
 break; 
 } 
 pDC->SelectObject(pOldBr); 
 pDC->SelectObject(pOldPen); 
 br.DeleteObject(); 
 pen.DeleteObject(); 
} 
 Khai báo hàm ảo Serialize: 
 Bổ sung marcro IMPLEMENT_SERIAL(CShape, CObject,1)trên 
hàm Serialize và định nghĩa hàm này như sau: 
IMPLEMENT_SERIAL(CShape, CObject,1) 
void CShape::Serialize(CArchive& ar) 
{ 
 if (ar.IsStoring()) 
 { // storing code (luu du lieu) 
ar << nShape << clrBkColor << clrBorderColor << nPenWidth << 
pLeftTop << pRightBottom; 
 } 
 else 
 { // loading code (load du lieu) 
ar >> nShape >> clrBkColor >> clrBorderColor >> nPenWidth >> 
pLeftTop >> pRightBottom; 
 } 
} 
3) Trong class CDrawsDoc, khai báo các biến: 
 Trong hàm Serialize của lớp CDrawsDoc, bổ sung đoạn code 
sau: 
  Trong hàm OnNewDocument, khởi tạo giá trị ban đầu cho các 
biến: 
4) Chuyển sang class CDrawsView, khai báo các biến: 
  Tạo hàm xử lý sự kiện WM_CREATE: 
 Trong hàm OnCreate, tạo memdc: 
  Trong hàm OnDraw: 
 Tạo hàm xử lý sự kiện WM_LBUTTONDOWN: 
  Tạo hàm xử lý sự kiện WM_MOUSEMOVE: 
 Tạo hàm xử lý sự kiện WM_ERASEBKGND, chặn sự kiện xĩa 
view: 
 Chạy thử ứng dụng, dùng chuột vẽ các ellipse màu đỏ, đĩng 
và save thành file 
Mở lại ứng dụng, mở file đã lưu, xem kết quả. 
PHẦN II: Bổ sung Dialog option cho phép lựa chọn các thuộc tính 
vẽ 
1) Bổ sung hộp thoại Option dialog: Trong tab Resource view, 
click phải trên mục Dialog: 
 Thiết kế hộp thoại như sau: 
 Double click vào vùng trống trên hộp thoại, tạo class gắn 
với hộp thoại như sau: 
2) Tạo class CColorStatic kế thừa từ class CStatic để hiển thị 
màu chữ, màu nền cho đối tượng Static: 
 
 
 
 Để thấy được class mới tạo trong cửa sổ Class View, khai 
báo file tiêu đề colorstatic.h trên phần khai báo lớp 
COptionDlg như sau: 
 
 Trong class CColorStatic, khai báo các biến sau: 
 
Tạo hai hàm SetBkColor và SetTextColornhư sau: 
 
 
 
 Viết code cho hai hàm vừa tạo: 
 
 Tạo hàm xử lý sự kiện =WM_CTRLCOLOR: 
 
 Viết code cho hàm vừa tạo: 
 
3) Khai báo các biến cho các control trên hộp thoại Options: 
4) Chuyển sang tab ResourceView, chọn Menu IDR_MAINFRAME, bổ 
sung thêm menu Tools, Options: 
  Click phải trên menu Options: 
 5) Trong class COptionDlg, khai báo các biến sau: 
 Thêm hàm ảo OnInitDialog vào class COptionDlg: 
 Tạo hàm xử lý sự kiện cho hai control Static: 
  Thiêt lập thuộc tính Notify cho hai control Static này là 
True: 
 Viết code cho hai hàm xử lý sự kiện vừa tạo: 
6) Cuộn lên trên đầu file CDrawsDoc.cpp, khai báo tiêu đề file 
“OptionDlg.h”: 
 Viết code xử lý sự kiện menu: 
 Kết thúc 
TH Lập trình Windows chương 5 Dialog - Controls 
HƯỚNG DẪN THỰC HÀNH CHƯƠNG 5 
2 Dialog và các Controls 
2.1 Bài tập 1 (FontView) 
Bước 1: Tạo project (Dialog base), thiết kế giao diện theo yêu cầu 
Bước 2: Khai báo các biến thành viên ứng với các controls : 
Loại control ID Caption Biến đối tượng 
ComboBox IDC_COMBOSIZE m_cbSize 
ListBox IDC_LIST_FONT m_lbFonts 
Editbox IDC_CONTENT m_editContent 
CheckBox IDC_CHECK_TRUETYPE m_chkCheckbox 
CheckBox IDC_B m_chkB 
CheckBox IDC_I m_chkI 
CheckBox IDC_U m_chkU 
Static IDC_STATIC_FONTVIEW m_staticFontView 
 1/19 
TH Lập trình Windows chương 5 Dialog - Controls 
Bước 3: Tạo menu: 
Bước 4: 
Khai báo và định nghĩa hàm xử lý font : 
int CALLBACK EnumFontfamProc (LPENUMLOGFONT lpelf, 
 LPNEWTEXTMETRIC lpntm, DWORD nFonttype, long lParam); 
Bước 5: Trong lớp CFontViewDlg, khai báo và định nghĩa các hàm 
 2/19 
TH Lập trình Windows chương 5 Dialog - Controls 
//Hàm liệt kê và hiển thị font 
//Hàm tạo và chọn font dựa vào các lựa chọn 
 3/19 
TH Lập trình Windows chương 5 Dialog - Controls 
//Hàm kiểm tra có đoạn văn bản nào đang được chọn trong EditBox 
//Hàm cập nhật trạng thái menu 
 4/19 
TH Lập trình Windows chương 5 Dialog - Controls 
//Tạo danh sách các cỡ chữ trong ComboBox 
Bước 5: Trong lớp CFontViewDlg, khai báo và định nghĩa các hàm xử lý sự kiện 
//Trong OnInitDialog 
// Thay đổi lựa chọn font trong ListBox 
//Check – uncheck ComboBox True Type 
 5/19 
TH Lập trình Windows chương 5 Dialog - Controls 
// Sự kiện từ menu 
 6/19 
TH Lập trình Windows chương 5 Dialog - Controls 
//sự kiện click vào menu -> cập nhật trạng thái menu 
//Xử lý sự kiện phím 
//Check – uncheck các CheckBox B, I, U 
//Thay đổi lựa chọn trên ComboBox Size 
 7/19 
TH Lập trình Windows chương 5 Dialog - Controls 
2.2 Bài tập 2 (ColorText) 
Bước 1: Tạo project (Dialog base), thiết kế giao diện theo yêu cầu 
Bước 2: Tạo các lớp CColorStatic kế thừa từ lớp cơ sở CStatic và CiconListBox kế thừa từ lớp 
cơ sở CListBox (xem trong slides) 
Bước 3: Trong lớp CcolorTextDlg khai báo các biến : 
Bước 4: Khai báo các biến thành viên ứng với các controls : 
Loại control ID Caption Biến đối tượng 
CColorStatic IDC_STATIC_TEXT Advanced 
Control 
Programming
m_staticText 
CIconListBox IDC_LIST_ICON m_lbIcon 
Bước 5: Khai báo các và định nghĩa các hàm xử lý sự kiện : 
//Trong OnInitDialog 
 8/19 
TH Lập trình Windows chương 5 Dialog - Controls 
//Trong OnPaint 
// Các sự kiện từ Radio Button, ListBox 
 9/19 
TH Lập trình Windows chương 5 Dialog - Controls 
 10/19 
TH Lập trình Windows chương 5 Dialog - Controls 
2.3 Bài tập 3 (SampleEditor) 
Bước 1: Tạo project (Dialog base), thiết kế giao diện theo yêu cầu 
ListBox 
EditBox 
CheckBox
ComboBo
 11/19 
TH Lập trình Windows chương 5 Dialog - Controls 
Bước 2: Xây dựng các lớp đáp ứng yêu cầu thiết kế giao diện 
• ComboBox hiển thị màu sắc: 
 12/19 
TH Lập trình Windows chương 5 Dialog - Controls 
• ListBox hiển thị màu cho text: Tạo lớp CColorListBox kế thừa từ lớp cơ sở CListBox: 
File ColorListbox.h 
File ColorListbox.cpp 
// 
//Thêm một chuỗi vào ListBox với màu text là cColor 
// Thiết lập kích thước cho mỗi item 
 13/19 
TH Lập trình Windows chương 5 Dialog - Controls 
// Vẽ lại ListBox 
 14/19 
TH Lập trình Windows chương 5 Dialog - Controls 
• Lớp CEditColor : kế thừa từ lớp cơ sở CEdit, thêm các chức năng chọn màu văn bản, 
màu nền 
 //File EditColor.h 
 15/19 
TH Lập trình Windows chương 5 Dialog - Controls 
//File EditColor.cpp 
 16/19 
TH Lập trình Windows chương 5 Dialog - Controls 
Bước 3: Khai báo các biến thành viên ứng với các controls : 
Loại control ID Caption Biến đối tượng 
ComboBox IDC_COMBOCOLOR m_cbColor 
(COwnerDrawComboBox)
ComboBox IDC_COMBOSIZE m_cbSize 
ListBox IDC_FONTLIST m_lbFonts 
(CColorListBox) 
Editbox IDC_CONTENT m_editContent 
(CEditColor) 
CheckBox IDC_CHECKB m_bB 
CheckBox IDC_CHECKI m_bI 
CheckBox IDC_CHECKU m_bU 
Bước 4: 
// file SimpleEditor.h 
Khai báo và định nghĩa hàm xử lý font : 
int CALLBACK EnumFontfamProc (LPENUMLOGFONT lpelf, 
 LPNEWTEXTMETRIC lpntm, DWORD nFonttype, long lParam); 
//file SimpleEditor.cpp 
 17/19 
TH Lập trình Windows chương 5 Dialog - Controls 
 18/19 
TH Lập trình Windows chương 5 Dialog - Controls 
//Trong hàm OnInitDialog() 
 19/19 
TH Lập trình Windows chương 5 Kiến trúc Documents/Views – Dialog, Property Sheets 
HƯỚNG DẪN THỰC HÀNH CHƯƠNG 5 
3 Kiến trúc Documents/Views 
3.1 SdiSquares 
Bước 1: Tạo ứng dụng SDI với project name: SdiSquares 
Bước 2: Thiết kế lại menu 
Bước 3: Trong lớp CSquaresDoc: 
ID_COLOR_RED Red 
ID_COLOR_YELLOW Yellow 
ID_COLOR_GREEN Green 
ID_COLOR_CYAN Cyan 
ID_COLOR_BLUE Blue 
ID_COLOR_WHITE White 
• Khai báo hai biến 
 COLORREF m_clrCurrentColor; // màu tô hiện tại 
COLORREF m_clrGrid[4][4]; // màu tô trong các ô 
• Xây dựng các hàm: 
// Đặt giá trị màu (color) cho ô thứ [i][j] 
// Báo tài liệu đã được thay đổi, cập nhật các view 
void CSquaresDoc::SetSquare(int i, int j, COLORREF color) 
{ 
 ASSERT (i >= 0 && i = 0 && j <= 3); 
 m_clrGrid[i][j] = color; 
 SetModifiedFlag (TRUE); 
 UpdateAllViews (NULL); 
} 
//Lấy giá trị màu của ô thứ [i][j] 
COLORREF CSquaresDoc::GetSquare(int i, int j) 
{ 
 ASSERT (i >= 0 && i = 0 && j <= 3); 
 return m_clrGrid[i][j]; 
} 
// Lấy giá trị màu hiện tại 
COLORREF CSquaresDoc::GetCurrentColor() 
{ 
 return m_clrCurrentColor; 
} 
• Khởi tạo giá trị các biến trong hàm OnNewDocument() 
for (int i =0; i<4; i++) 
 for (int j=0; j<4; j++) 
 m_clrGrid[i][j] = RGB (255, 255, 255); 
 1 
TH Lập trình Windows chương 5 Kiến trúc Documents/Views – Dialog, Property Sheets 
 m_clrCurrentColor = RGB (255, 0, 0); 
• Khai báo các hàm xử lý sự kiện ON_COMMAND, 
ON_UPDATE_COMMAND_UI cho các menu ID_COLOR_RED -
>ID_COLOR_WHITE 
• Xử lý việc lưu và lấy giá trị các biến trong hàm Serialize 
if (ar.IsStoring()) 
 { 
 for (int i=0; i<4; i++) 
 for (int j=0; j<4; j++) 
 ar << m_clrGrid[i][j]; 
 ar << m_clrCurrentColor; 
 } 
 else 
 { 
 for (int i=0; i<4; i++) 
 for (int j=0; j<4; j++) 
 ar >> m_clrGrid[i][j]; 
 ar >> m_clrCurrentColor; 
 } 
Bước 4: Trong lớp CSquaresView: 
• Thực hiện thao tác vẽ trong hàm OnDraw 
CSquaresDoc* pDoc = GetDocument(); 
 ASSERT_VALID(pDoc); 
 // vẽ và tô màu các ô trong lưới với giá trị từ các biến 
của lớp Doc 
for (int i=0; i<4; i++) { 
 for (int j=0; j<4; j++) { 
 COLORREF color = pDoc->GetSquare (i, j); 
 CBrush brush (color); 
 int x1 = (j * 100) + 50; 
 int y1 = (i * 100) + 50; 
 int x2 = x1 + 100; 
 int y2 = y1 +100; 
 CRect rect (x1, y1, x2, y2); 
 pDC->FillRect (rect, &brush); 
 } 
 } 
// vẽ các đường thẳng theo phương đứng 
 for (int x=50; x<=450; x+=100) { 
 pDC->MoveTo (x, 50); 
 pDC->LineTo (x, 450); 
 } 
// vẽ các đường thẳng theo phương ngang 
 for (int y=50; y<=450; y+=100) { 
 pDC->MoveTo (50, y); 
 2 
TH Lập trình Windows chương 5 Kiến trúc Documents/Views – Dialog, Property Sheets 
 pDC->LineTo (450, y); 
 } 
• Khai báo hàm xử lý sự kiện khi nhấn nút trái chuột 
 if (point.x >= 50 && point.x = 50 && 
point.y <= 450) { 
 int i = (point.y-50)/100; 
 int j = (point.x - 50) / 100; 
 CSquaresDoc* pDoc = GetDocument (); 
 COLORREF clrCurrentColor = pDoc->GetCurrentColor (); 
 pDoc->SetSquare (i, j, clrCurrentColor); 
 } 
3.2 MDIDrawEllipse 
Bước 1: Tạo ứng dụng MDI với project name: MDIDrawEllipse 
Bước 2: Thiết kế lại menu 
 3 
TH Lập trình Windows chương 5 Kiến trúc Documents/Views – Dialog, Property Sheets 
Bước 3: Xây dựng lớp CEllipse 
class CEllipse : public CObject 
{ 
 DECLARE_SERIAL(CEllipse) 
 CPoint m_P1, m_P2; 
 COLORREF m_clrBorderColor, m_clrFillColor; 
 BOOL m_bThick; 
public: 
 CEllipse(); 
 virtual ~CEllipse(); 
 void Draw(CDC *pDC); 
 void SetPoint2(CPoint p); 
 void SetPoint1(CPoint p); 
 void SetBorderColor(COLORREF clrBorderColor); 
 void SetFillColor(COLORREF clrFillColor); 
 void SetPenWidth(int nPenWidth); 
 CPoint GetPoint2(); 
 CPoint GetPoint1(); 
 COLORREF GetBorderColor(); 
 COLORREF GetFillColor(); 
 BOOL GetPenWidth(); 
 void Serialize(CArchive& ar); 
}; 
// Ellipse.cpp 
CEllipse::CEllipse() 
{ 
 m_P1 = m_P2 = CPoint(0,0); 
 m_clrBorderColor = RGB(0,0,0); 
 m_clrFillColor = RGB(255, 255, 255); 
 m_bThick=FALSE; 
} 
IMPLEMENT_SERIAL(CEllipse, CObject,1) 
. . . 
void CEllipse::Draw(CDC* pDC) 
{ 
 CPen NewPen, *pOldPen = NULL; 
 CBrush NewBrush, *pOldBrush = NULL; 
 if(m_bThick) 
 NewPen.CreatePen(PS_SOLID, 5, m_clrBorderColor); 
 else 
 NewPen.CreatePen(PS_SOLID, 0, m_clrBorderColor); 
 NewBrush.CreateSolidBrush(m_clrFillColor); 
 pOldPen = pDC->SelectObject(&NewPen); 
 4 
TH Lập trình Windows chương 5 Kiến trúc Documents/Views – Dialog, Property Sheets 
 pOldBrush = pDC->SelectObject(&NewBrush); 
 pDC->Ellipse(CRect(m_P1, m_P2)); 
 pDC->SelectObject(pOldPen); 
 pDC->SelectObject(pOldBrush); 
 NewPen.DeleteObject(); 
 NewBrush.DeleteObject(); 
} 
void CEllipse::Serialize(CArchive& ar) 
{ 
 CObject::Serialize(); 
 if (ar.IsStoring()) 
 { 
 ar << 
m_P1<<m_P2<<m_clrFillColor<<m_clrBorderColor<<m_bThick; 
 } 
 else 
 { 
 ar >> 
m_P1>>m_P2>>m_clrFillColor>>m_clrBorderColor>>m_bThick; 
 } 
} 
Bước 4: Trong lớp CMDIDrawEllipseDoc: 
• Khai báo các biến: 
COLORREF m_clrBkColor, m_clrBorderColor; 
 BOOL m_bThick; 
 CArray m_Objects; // danh sách 
các Ellipses 
• Xây dựng hàm: 
void CMDIDrawEllipseDoc::SetEllipse(CPoint point) 
{ 
 CEllipse *pEllipse = new CEllipse; 
 pEllipse->SetPoint1(point); 
 pEllipse->SetPoint2(point); 
 pEllipse->SetFillColor(m_clrBkColor); 
 pEllipse->SetPenWidth (m_bThick); 
 pEllipse->SetBorderColor (m_clrBorderColor); 
 m_Objects.Add(pEllipse); 
 SetModifiedFlag (TRUE); 
 UpdateAllViews (NULL); 
} 
• Khởi tạo giá trị các biến trong hàm OnNewDocument() 
m_Objects.RemoveAll(); 
 5 
TH Lập trình Windows chương 5 Kiến trúc Documents/Views – Dialog, Property Sheets 
 m_clrBkColor = RGB (255, 0, 0); 
 m_clrBorderColor = RGB(255,255,0); 
 m_bThick=FALSE; 
• Khai báo các hàm xử lý sự kiện ON_COMMAND, 
ON_UPDATE_COMMAND_UI cho các menu. 
• Xử lý việc lưu và lấy giá trị các biến trong hàm Serialize 
if (ar.IsStoring()) 
 { 
 ar<<m_clrBkColor<<m_clrBorderColor<<m_bThick; 
 for(int i=0;i<m_Objects.GetSize();i++) 
 ar << m_Objects[i]; 
 } 
else 
 { 
 ar>>m_clrBkColor>>m_clrBorderColor>>m_bThick; 
 while(!ar.IsBufferEmpty()) 
 { 
 CEllipse *pEll=new CEllipse(); 
 Ar >> pEll ; 
 m_Objects.Add (pEll); 
 } 
 } 
Bước 5: Trong lớp CMDIDrawEllipseView: 
• Khai báo các biến: 
CDC m_MemDC; 
 CBitmap m_MemBitmap, *m_pOldBitmap; 
• Khai báo và định nghĩa hàm 
// MDIDrawEllipseView.h 
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); 
// MDIDrawEllipseView.cpp 
ON_WM_CREATE() //BEGIN MESSAGEMAP 
// 
int CMDIDrawEllipseView::OnCreate(LPCREATESTRUCT 
lpCreateStruct) 
{ 
 if (CView::OnCreate(lpCreateStruct) == -1) 
 return -1; 
 // lay kich thuoc man hinh 
 CClientDC dc(this); 
 int MaxX = ::GetSystemMetrics(SM_CXSCREEN); 
 int MaxY = ::GetSystemMetrics(SM_CYSCREEN); 
 //Tao ra MemDC tuong thich voi dc cua man hinh 
 m_MemDC.CreateCompatibleDC(&dc); 
 6 
TH Lập trình Windows chương 5 Kiến trúc Documents/Views – Dialog, Property Sheets 
 //tao doi tuong CBitmap(kich thuoc MaxX,MaxY) tuong 
thich voi dc man hinh 
 m_MemBitmap.CreateCompatibleBitmap (&dc,MaxX,MaxY); 
 // Dua doi tuong bitmap m_MemBitmap vao m_MemDC 
 m_pOldBitmap=m_MemDC.SelectObject(&m_MemBitmap); 
 return 0; 
} 
• Thực hiện thao tác vẽ trong hàm OnDraw 
CMDIDrawEllipseDoc* pDoc = GetDocument(); 
 ASSERT_VALID(pDoc); 
 CRect rect; 
 GetClientRect(&rect); 
 m_MemDC.FillSolidRect(rect,RGB(255,255,255)); 
 int i, n = pDoc->m_Objects.GetSize(); 
 for (i=0; i<n; i++) 
 pDoc->m_Objects[i]->Draw(&m_MemDC); 
 pDC-
>BitBlt(0,0,rect.Width(),rect.Height(),&m_MemDC,0,0,SRCC
OPY); 
• Khai báo hàm xử lý sự kiện khi nhấn nút trái chuột 
CMDIDrawEllipseDoc* pDoc = GetDocument(); 
 ASSERT_VALID(pDoc); 
 pDoc->SetEllipse (point); 
• Khai báo hàm xử lý sự kiện khi di chuyển chuột 
CMDIDrawEllipseDoc* pDoc = GetDocument(); 
 ASSERT_VALID(pDoc); 
 if (nFlags & MK_LBUTTON==MK_LBUTTON) 
 if (pDoc->m_Objects.GetSize()>0) 
 { 
 CEllipse* pEllipse= pDoc->m_Objects[pDoc-
>m_Objects.GetSize()-1]; 
 pEllipse->SetPoint2(point); 
 Invalidate(); 
 } 
• Khai báo hàm xử lý sự kiện khi nhả nút trái chuột 
CMDIDrawEllipseDoc* pDoc = GetDocument(); 
 ASSERT_VALID(pDoc); 
 if (pDoc->m_Objects.GetSize()>0) 
 { 
 CEllipse* pEllipse= pDoc->m_Objects[pDoc-
>m_Objects.GetSize()-1]; 
 pEllipse->SetPoint2(point); 
 CClientDC dc(this); 
 pEllipse->Draw(&dc); 
 pDoc->SetModifiedFlag (TRUE); 
 pDoc->UpdateAllViews (NULL); 
 7 
TH Lập trình Windows chương 5 Kiến trúc Documents/Views – Dialog, Property Sheets 
 } 
• Hủy các đối tượng trong hàm 
CMDIDrawEllipseView::~CMDIDrawEllipseView() 
m_MemDC.DeleteDC(); 
 m_MemBitmap.DeleteObject(); 
4 Dialog, Property Sheets 
4.1 DlgDemo (Modal dialog) 
Bước 1: Tạo ứng dụng SDI (bỏ chọn Document/View) 
 Thiết kế lại menu File: Gồm hai menu Options và Exit. 
Bước 2: Từ menu Insert, chọn Resource, Dialog, New để thêm 
vào ứng dụng một hộp thoại dialog. 
 Thiết kế lại dialog (IDD_OPTIONS ) và thêm các controls 
theo yêu cầu 
Double click vào dialog để tạo lớp mới COptionsDialog : 
public CDialog và khai báo các biến cho các controls tương 
ứng: 
Loại control ID Caption Biến đối 
tượng 
Command 
Button 
IDC_RESET Reset 
Editbox IDC_WIDTH m_nWidth 
Editbox IDC_HEIGHT m_nHeight 
Radio Button IDC_INCHES 
(group) 
Inches 
m_nUnits 
 8 
TH Lập trình Windows chương 5 Kiến trúc Documents/Views – Dialog, Property Sheets 
Radio Button IDC_CENTIMETERS Centimeters
Radio Button IDC_PIXELS Pixels 
Bước 3: Trong lớp CChildView khai báo các biến: 
int m_nUnits; 
 int m_nHeight; 
 int m_nWidth; 
Trong hàm OnPaint() 
void CChildView::OnPaint() 
{ 
 CPaintDC dc(this); // Device context for painting. 
 CBrush brush (RGB (255, 0, 255)); 
 CBrush* pOldBrush = dc.SelectObject (&brush); 
 switch (m_nUnits) { 
 case 0: // Inches. 
 dc.SetMapMode (MM_LOENGLISH); 
 dc.Rectangle (0, 0, m_nWidth * 100, -m_nHeight * 
100); 
 break; 
 case 1: // Centimeters. 
 dc.SetMapMode (MM_LOMETRIC); 
 dc.Rectangle (0, 0, m_nWidth * 100, -m_nHeight * 
100); 
 break; 
 case 2: // Pixels. 
 dc.SetMapMode (MM_TEXT); 
 dc.Rectangle (0, 0, m_nWidth, m_nHeight); 
 break; 
 } 
 dc.SelectObject (pOldBrush); 
} 
Khai báo hàm xử lý sự kiện cho menu File -> Option 
void CChildView::OnFileOptions() 
{ 
 COptionsDialog dlg; 
 dlg.m_nWidth = m_nWidth; 
 dlg.m_nHeight = m_nHeight; 
 dlg.m_nUnits = m_nUnits; 
 if (dlg.DoModal () == IDOK) { 
 m_nWidth = dlg.m_nWidth; 
 9 
TH Lập trình Windows chương 5 Kiến trúc Documents/Views – Dialog, Property Sheets 
 m_nHeight = dlg.m_nHeight; 
 m_nUnits = dlg.m_nUnits; 
 Invalidate (); 
 } 
} 
4.2 DlgDemo (Modeless dialog) 
Bước 1-2: 
Tạo ứng dụng và thiết kế hộp thoại Options giống bài tập 
3.1 
Right click vào lớp COptionsDlg , chọn Add Windows 
Message Handler, chọn sự kiện WM_INITDIALOG để thêm hàm 
OnInitDialog cho lớp này. 
BOOL COptionsDialog::OnInitDialog() 
{ 
 CDialog::OnInitDialog(); 
 // TODO: Add extra initialization here 
 CMainFrame* pMain = (CMainFrame*)AfxGetApp()-
>GetMainWnd(); 
 m_nWidth = pMain->m_nWidth; 
 m_nHeight = pMain->m_nHeight; 
 m_nUnits = pMain->m_nUnits; 
 UpdateData(FALSE); 
 return TRUE; // return TRUE unless you set the focus to a 
control 
} 
Khai báo hàm xử lý sự kiện cho các nút OK, Cancel và Reset 
void COptionsDialog::OnReset() 
{ 
 m_nWidth = 4; 
 m_nHeight = 2; 
 m_nUnits = 0; 
 UpdateData (FALSE); 
} 
void COptionsDialog::OnOK() 
{ 
 UpdateData(TRUE); 
 CMainFrame* pMain = (CMainFrame*)AfxGetApp()-
>GetMainWnd(); 
 pMain->m_nWidth = m_nWidth; 
 pMain->m_nHeight = m_nHeight; 
 pMain->m_nUnits = m_nUnits; 
 pMain->Invalidate (); 
 CDialog::OnOK(); 
} 
 10 
TH Lập trình Windows chương 5 Kiến trúc Documents/Views – Dialog, Property Sheets 
void COptionsDialog::OnCancel() 
{ 
 ShowWindow(SW_HIDE); 
 CDialog::OnCancel(); 
} 
Bước 3: Trong lớp CMainFrame khai báo các biến: 
int m_nUnits; 
 int m_nHeight; 
 int m_nWidth; 
Bước 4: Trong lớp CChildView 
Khai báo biến : 
COptionsDialog pDialog; 
Khai báo hàm xử lý sự kiện cho menu File -> Option 
void CChildView::OnFileOptions() 
{ 
 if(!pDialog) pDialog.Create(IDD_OPTIONS); 
 pDialog.ShowWindow(SW_SHOW); 
} 
4.3 PropDemo (Property Sheets) 
Bước 1: Tạo ứng dụng SDI như bài tập 3.1. 
Bước 2: Insert hai dialog, thiết kế giao diện như yêu cầu và 
tạo hai lớp mới tương ứng với hai dialog trên: 
class CSizePage : public CPropertyPage 
{ 
 . . . 
 // Dialog Data 
 //{{AFX_DATA(CSizePage) 
 enum { IDD = IDD_SIZEPAGE }; 
 int m_nHeight; 
 int m_nWidth; 
 int m_nUnits; 
 //}}AFX_DATA 
. . . 
// Implementation 
protected: 
 // Generated message map functions 
 //{{AFX_MSG(CSizePage) 
 afx_msg void OnChange(); 
 //}}AFX_MSG 
 DECLARE_MESSAGE_MAP() 
}; 
void CSizePage::OnChange() 
{ 
 SetModified (TRUE); 
 11 
TH Lập trình Windows chương 5 Kiến trúc Documents/Views – Dialog, Property Sheets 
} 
class CColorPage : public CPropertyPage 
{ 
 . . . 
// Dialog Data 
 //{{AFX_DATA(CColorPage) 
 enum { IDD = IDD_COLORPAGE }; 
 int m_nColor; 
 //}}AFX_DATA 
. . . 
// Implementation 
protected: 
 // Generated message map functions 
 //{{AFX_MSG(CColorPage) 
 afx_msg void OnChange(); 
 //}}AFX_MSG 
 DECLARE_MESSAGE_MAP() 
}; 
void CColorPage::OnChange() 
{ 
 SetModified (TRUE); 
} 
Bước 3: Tạo lớp mới kế thừa từ lớp CPropertySheet 
class CMyPropertySheet : public CPropertySheet 
{ 
 . . . 
// Attributes 
public: 
 CColorPage m_colorPage; 
 CSizePage m_sizePage; 
 . . . 
 // Generated message map functions 
protected: 
 //{{AFX_MSG(CMyPropertySheet) 
 //}}AFX_MSG 
 afx_msg void OnApply (); 
 DECLARE_MESSAGE_MAP() 
}; 
// MyPropertySheet.cpp 
BEGIN_MESSAGE_MAP(CMyPropertySheet, CPropertySheet) 
 //{{AFX_MSG_MAP(CMyPropertySheet) 
 //}}AFX_MSG_MAP 
 ON_BN_CLICKED (ID_APPLY_NOW, OnApply) 
END_MESSAGE_MAP() 
 12 
TH Lập trình Windows chương 5 Kiến trúc Documents/Views – Dialog, Property Sheets 
////////////////////////////////////////////////////////
///////////////////// 
void CMyPropertySheet::OnApply () 
{ 
 GetActivePage ()->UpdateData (TRUE); 
 CMainFrame* pMain = (CMainFrame*)AfxGetApp()-
>GetMainWnd(); 
 pMain->m_nWidth = m_sizePage.m_nWidth; 
 pMain->m_nHeight = m_sizePage.m_nHeight; 
 pMain->m_nUnits = m_sizePage.m_nUnits; 
 pMain->m_nColor = m_colorPage.m_nColor; 
 pMain->Invalidate (); 
} 
Bước 4: Trong lớp CChildView: 
Trong hàm OnPaint() 
void CChildView::OnPaint() 
{ 
 CPaintDC dc(this); 
 CMainFrame* pMain = (CMainFrame*)AfxGetApp()-
>GetMainWnd(); 
 CBrush brush (CColorPage::m_clrColors[pMain-
>m_nColor]); 
 CBrush* pOldBrush = dc.SelectObject (&brush); 
 switch (pMain->m_nUnits) { 
 case 0: // Inches. 
 dc.SetMapMode (MM_LOENGLISH); 
 dc.Ellipse (0, 0, pMain->m_nWidth * 100, -pMain-
>m_nHeight * 100); 
 break; 
 case 1: // Centimeters. 
 dc.SetMapMode (MM_LOMETRIC); 
 dc.Ellipse (0, 0, pMain->m_nWidth * 100, -pMain-
>m_nHeight * 100); 
 break; 
 case 2: // Pixels. 
 dc.SetMapMode (MM_TEXT); 
 dc.Ellipse (0, 0, pMain->m_nWidth, pMain-
>m_nHeight); 
 } 
 dc.SelectObject (pOldBrush); 
} 
Khai báo hàm xử lý sự kiện cho menu File -> Propertiers 
void CChildView::OnFilePropertiers() 
{ 
 13 
TH Lập trình Windows chương 5 Kiến trúc Documents/Views – Dialog, Property Sheets 
 CMainFrame* pMain = (CMainFrame*)AfxGetApp()-
>GetMainWnd(); 
 CMyPropertySheet ps (_T ("Properties")); 
 ps.m_sizePage.m_nWidth = pMain->m_nWidth; 
 ps.m_sizePage.m_nHeight = pMain->m_nHeight; 
 ps.m_sizePage.m_nUnits = pMain->m_nUnits; 
 ps.m_colorPage.m_nColor = pMain->m_nColor; 
 if (ps.DoModal () == IDOK) { 
 pMain->m_nWidth = ps.m_sizePage.m_nWidth; 
 pMain->m_nHeight = ps.m_sizePage.m_nHeight; 
 pMain->m_nUnits = ps.m_sizePage.m_nUnits; 
 pMain->m_nColor = ps.m_colorPage.m_nColor; 
 pMain->Invalidate (); 
 } 
} 
4.4 Phones(Common Dialog) 
Bước 1: Tạo ứng dụng dialog và thiết kế giao diện theo yêu cầu 
ListBox 
(m_lbPhoneList 
 14 
TH Lập trình Windows chương 5 Kiến trúc Documents/Views – Dialog, Property Sheets 
Bước 2: Tạo lớp CEditNumber kế thừa từ lớp CEdit: 
class CEditNumber : public CEdit 
{ 
 . . . 
 //{{AFX_MSG(CEditNumber) 
 afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT 
nFlags); 
 //}}AFX_MSG 
 . . . 
}; 
//EditNumber.cpp 
void CEditNumber::OnChar(UINT nChar, UINT nRepCnt, UINT 
nFlags) 
{ 
 // TODO: Add your message handler code here and/or call 
default 
 if (((nChar >= _T ('0')) && (nChar <= _T ('9'))) || 
 (nChar == VK_BACK) || (nChar == _T ('(')) || (nChar == _T 
(')')) || 
 (nChar == _T ('-')) || (nChar == _T (' '))) 
 CEdit::OnChar(nChar, nRepCnt, nFlags); 
} 
Bước 3: Insert dialog 
 • Tạo lớp mới CAddPhoneDlg :public CDialog và khai báo các 
biến cho các controls tương ứng 
Loại 
control 
ID Caption Biến đối tượng 
Editbox IDC_NAME m_editName 
Editbox IDC_PHONE CEditNumber 
m_editPhone 
Command IDOK (Bitmap) OK m_btOk 
 15 
TH Lập trình Windows chương 5 Kiến trúc Documents/Views – Dialog, Property Sheets 
Button 
Command 
Button 
IDCANCEL 
(Bitmap) 
Cancel m_btCancel 
• Trong hàm OnInitDialog() 
BOOL CAddPhoneDlg::OnInitDialog() 
{ 
 CDialog::OnInitDialog(); 
 HBITMAP hbitmap=::LoadBitmap (::AfxGetInstanceHandle 
(), 
MAKEINTRESOURCE(IDB_OK)); 
 m_buttonOk.SetBitmap (hbitmap); 
 hbitmap=::LoadBitmap (::AfxGetInstanceHandle (), 
MAKEINTRESOURCE(IDB_CANCEL)); 
 m_buttonCancel.SetBitmap (hbitmap); 
 return TRUE; 
} 
Bước 4: Insert menu và thiết kế menu File theo yêu cầu 
Bước 5: Trong lớp CPhonesDlg 
• Khai báo biến CString m_strPathName; 
• Khai báo và định nghĩa các hàm: 
// Lưu dữ liệu từ ListBox vào file 
BOOL CPhonesDlg::SaveFile(LPCTSTR pszFile) 
{ 
 BOOL bResult = FALSE; 
 try { 
 CStdioFile file (pszFile, CFile::modeWrite | 
CFile::modeCreate); 
 DWORD dwCount = m_lbPhoneList.GetCount (); 
 file.Write (&dwCount, sizeof (dwCount)); 
 if (dwCount) 
{ 
 for (int i=0; i<(int) dwCount; i++) { 
 CString string; 
 m_lbPhoneList.GetText (i, string); 
 string += _T ("\n"); 
 16 
TH Lập trình Windows chương 5 Kiến trúc Documents/Views – Dialog, Property Sheets 
 file.WriteString (string); 
 } 
 } 
 bResult = TRUE; 
 } 
 catch (CFileException* e) { 
 e->ReportError (); 
 e->Delete (); 
 } 
 return bResult; 
} 
 17 
TH Lập trình Windows chương 5 Kiến trúc Documents/Views – Dialog, Property Sheets 
//Đọc file đưa vào ListBox 
BOOL CPhonesDlg::LoadFile(LPCTSTR pszFile) 
{ 
 BOOL bResult = FALSE; 
 try { 
 CStdioFile file (pszFile, CFile::modeRead); 
 m_lbPhoneList.ResetContent (); 
 DWORD dwCount; 
 file.Read (&dwCount, sizeof (dwCount)); 
 if (dwCount) { 
 for (int i=0; i<(int) dwCount; i++) { 
 CString string; 
 file.ReadString (string); 
 m_lbPhoneList.AddString (string); 
 } 
 } 
 bResult = TRUE; 
 } 
 catch (CFileException* e) { 
 e->ReportError (); 
 e->Delete (); 
 } 
 return bResult; 
} 
• Khai báo các hàm xử lý sự kiện từ menu 
void CPhonesDlg::OnFileNew() 
{ 
 CAddPhoneDlg dlg; 
 if(dlg.DoModal ()==IDOK) 
 { 
 CString str=dlg.m_sName +_T("\t")+dlg.m_sPhone ; 
 m_lbPhoneList.AddString (str); 
 } 
} 
void CPhonesDlg::OnFileOpen() 
{ 
 CFileDialog dlg (TRUE, _T ("phn"), _T ("*.phn"), 
 OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, 
m_szFilters); 
 if (dlg.DoModal () == IDOK) 
 { 
 if (LoadFile (dlg.GetPathName ())) 
 { 
 m_strPathName = dlg.GetPathName (); 
 m_lbPhoneList.SetCurSel (0); 
 18 
TH Lập trình Windows chương 5 Kiến trúc Documents/Views – Dialog, Property Sheets 
 } 
 } 
} 
void CPhonesDlg::OnFileSave() 
{ 
if (!m_strPathName.IsEmpty ()) 
 SaveFile (m_strPathName); 
 else 
 OnFileSaveAs (); 
} 
void CPhonesDlg::OnFileSaveAs() 
{ 
 CFileDialog dlg (FALSE, _T ("phn"), m_strPathName, 
OFN_OVERWRITEPROMPT | 
OFN_PATHMUSTEXIST | OFN_HIDEREADONLY, 
m_szFilters); 
 if (dlg.DoModal () == IDOK) 
 if (SaveFile (dlg.GetPathName ())) 
 m_strPathName = dlg.GetPathName (); 
} 
void CPhonesDlg::OnFileExit() 
{ 
 OnOK(); 
} 
// biến m_szFilters[] được khai báo đầu file PhoneDlg.cpp 
như sau: 
TCHAR m_szFilters[] = 
 _T ("My files (*.phn)|*.phn|All files (*.*)|*.phn||"); 
 19 
            Các file đính kèm theo tài liệu này:
 tailieu.pdf tailieu.pdf