• Một chương trình Windows phải chứa một hàm đặc biệt để xử lý các thông điệp gọi là hàm xử lý cửa sổ WinProc hoặc WindowProc: – Được gọi khi có bất kỳ thông điệp được truyền đến cửa sổ
Trang 11
TRƯỜNG ĐẠI HỌC B\CH KHOA H[ NỘI
VIỆN CÔNG NGHỆ THÔNG TIN V[ TRUYỀN THÔNG
Phạm Ngọc Hưng
Bộ môn Kỹ thuật Máy tính
hungpn@soict.hut.edu.vn
LẬP TRÌNH WINDOWS
Trang 3• Chương 3 Một số chủ đề nâng cao
– Tạo thư viện liên kết động (DLL) (3LT + 2BT)
Trang 4Tài liệu tham khảo
• 1 Ivor Horton’s, Beginning Visual C++ 2010
• 2 Programming Windows with MFC 2nd
Trang 55
Chương 1 Tổng quan lập trình Windows
• 1.1 Cơ bản về lập trình Windows (1T)
• 1.2 Cấu trúc của chương trình Windows (2T)
• 1.3 Microsoft Foundation Classes (MFC)
• 1.4 Lập trình Windows với VC++ 2008
(1LT + 1BT)
5 Lập trình Windows
Trang 61.1 Cơ bản về lập trình Windows
• Windows: đồ họa trực quan, tài nguyên đa
dạng.
• Ứng dụng thân thiện với người sử dụng
thông qua giao diện đồ họa Windows
• Các ứng dụng có giao diện tương tác giống
nhau:
– Windows, title bar, toolbar, menu bar, status bar
– Thanh thực đơn: File, Edit, Tool, Help…
– Hộp thoại: thường chứa các điều khiển chung: Edit
Control, Button Control, Checkbox….
6 Lập trình Windows
Trang 77
Các thành phần của một cửa sổ
7 Lập trình Windows
Trang 8Cơ chế lập trình Event-driven
8 Lập trình Windows
Trang 99
Thông điệp (Windows Messages)
• Hệ thống (Windows) ghi lại mỗi sự kiện xảy ra
(event) trong một thông điệp (message) và đặt
trong hàng đợi thông điệp (messages queue)
• Thông điệp phát sinh:
Trang 10Windows Message (cont.)
• HĐH Windows đảm nhiệm việc truyền tất cả các
thông điệp của ứng dụng vào các cửa sổ khác nhau
của ứng dụng đó
• Một chương trình Windows phải chứa một hàm
đặc biệt để xử lý các thông điệp gọi là hàm xử lý
cửa sổ WinProc (hoặc WindowProc):
– Được gọi khi có bất kỳ thông điệp được truyền
đến cửa sổ (thông qua con trỏ hàm)
– Xử lý các thông điệp đó và trả điều khiển về cho
hệ thống
• Nhiều thông điệp trả lại cho Windows xử lý, gọi
hàm DefWindowProc( )
10 Lập trình Windows
Trang 1111
Windows Message (cont.)
11 Lập trình Windows
Trang 12Windows API
• Application Programming Interface: Giao
diện lập trình ứng dụng
• Cung cấp các hàm truy cập tài nguyên trong
hệ thống (Windows) chứa trong các thư viện
liên kết động DLL.
• Các ứng dụng có thể truy cập đến các hàm
API
• Các hàm GDI (Graphics Device Interface) cho
phép ứng dụng làm việc với nhiều kiểu thiết
bị đồ họa.
12 Lập trình Windows
Trang 1313
Windows Data Types (1)
• Định nghĩa nhờ từ khóa typedef trong các tập tin (windef.h;
winbase.h, winuser.h được include trong windows.h).
• Ví dụ:
– typedef unsigned int UINT;
– char * PSTR
• WPARAM (UINT) và LPARAM (LONG) đều 32 bit
• LRESULT: kiểu LONG
• HANDLE: Một gi| trị 32bits không dấu (unsigned) do HĐH
tạo ra để l{m định danh cho 1 đối tượng (file, cửa sổ, vùng
nhớ, menu, toolbar…) Ví dụ : HWND, HINSTANCE,
hPrevInstance
13 Lập trình Windows
Trang 14Windows Data Types (2)
HANDLE Số nguyên 32-bit, định danh.
HWND Số nguyên 32-bit, định danh.
BYTE Giá trị 8-bit không dấu.
WORD Số nguyên 16-bit không dấu.
DWORD Số nguyên 32-bit không dấu.
UINT Số nguyên không dấu 32-bit.
LONG long 32-bit.
BOOL Kiểu logic True/False
LPSTR Con trỏ chuỗi (char *)
LPCSTR Hằng con trỏ chuỗi.
WPARAM 32-bit.
LPARAM 32-bit.
BSTR Giá trị 32-bit trỏ đến kí tự.
LPVOID Con trỏ 32-bit đến một kiểu không xác định.
LPTSTR Giống như LPSTRnhưng có thể chuyển sang dạng Unicode và
DBCS.
LPCTSTR Giống như LPCTSTRnhưng có thể chuyển sang dạng Unicode và
DBCS.
14 Lập trình Windows
Trang 1515
Microsoft style (1)
• Tất cả c|c kiểu dữ liệu mở rộng của windows , tên class, tên
struct, tên hằng số định sẵn đều được viết in hoa
Ví dụ :
Tên kiểu dữ liệu : UINT , ATOM , HANDLE, HWND, BYTE,….
Tên cấu trúc : MSG, PAINSTRUCT, WNDCLASS ,
Tên hằng số định sẵn : NULL, IDI_APPLICATION,
CS_VREDRAW,…
• Tất cả c|c method (c|c h{m, c|c phương thức) đều được viết
hoa (pascal notation)
Trang 16Microsoft Style (2)
• Qui ước: bắt đầu (tiền tố) chữ thường thể
hiện kiểu dữ liệu biến.
• Ví dụ: szCmdLine là một biến lưu chuỗi nhập
từ dòng lệnh, sz là thể hiện cho biến kiểu
chuỗi kết thúc ký tự 0,
• hInstance và hPrevInstance, trong đó h viết
tắt cho kiểu handle.
16 Lập trình Windows
Trang 1717
Microsoft Style (3) – Tiền tố tên biến
Tiền tố Kiểu dữ liệu
Trang 18Microsoft style (4) - Calling convention
• Định nghĩa kiểu h{m gọi bởi Windows OS
#define CALLBACK stdcall
#define WINAPI stdcall
#define APIENTRY WINAPI
#define APIPRIVATE stdcall
#define PASCAL stdcall
• Thêm vào trước tên hàm để chỉ ra cho
compiler rằng hàm này có cách tổ chức phục
vụ cho việc gọi đến như thế nào.
18 Lập trình Windows
Trang 1919
1.2 Cấu trúc của chương trình Windows
19 Lập trình Windows
Trang 201.2 Cấu trúc của chương trình Windows
• Chương trình Windows đơn giản (dùng hàm API)
gồm 2 hàm WinMain() và hàm xử lý cửa sổ
WinProc().
• WinMain() thực hiện các chức năng:
– Tell Windows what kind of window the program requires
– Create the program window
– Initialize the program window
– Retrieve Windows messages intended for the program
• WinProc(): xử lý các thông điệp liên quan đến cửa
sổ của nó
20 Lập trình Windows
Trang 2121
1.2.1 Hàm WinMain()
• Hàm chính của ứng dụng trên Windows
• Program entry point
• hInstance, is a handle to the instance of the program you
are writing.
• hPrevInstance, is used if your program had any previous
instance If not, this argument can be ignored.
• szCmdLine, is a string that represents all items used on the
command line to compile the application.
• nCmdShow, controls how the window you are building will
Trang 22Hàm WinMain (cont.)
• Tìm hiểu hàm WinMain mẫu:
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("HelloWin"); // tên ứng dụng
HWND hwnd;
MSG msg;
WNDCLASS wndclass; // biến để định danh một cửa sổ
/* Ðịnh nghĩa kiểu cửa sổ */
wndclass.style = SC_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc; // Hàm thủ tục cửa sổ
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance; // Ðịnh danh ứng dụng
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCusor (NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL; // Không có menu
22
Trang 2323
Tìm hiểu hàm WinMain mẫu (cont.)
wndclass.lpszClassName = szAppName; // tên ứng dụng
/* Ðăng ký lớp cửa sổ */
if (!RegisterClass(&wndclass)) return 0 ;
/* Tạo thể hiện lớp cửa sổ đã định nghĩa */
hwnd = CreateWindow(szAppName, // Tên cửa sổ
"Hello Program" , // Tiêu đề
WS_OVERLAPPEDWINDOW, // Kiểu cửa sổ
CW_USEDEFAULT, // Toạ độ x
CW_USEDEFAULT, // Toạ độ y
CW_USEDEFAULT, // Chiều rộng
CW_USEDEFAULT, // Chiều dài
NULL, // Cửa sổ cha
NULL, // Không có menu
/* Chu trình xử lý các thông điệp*/
while (GetMessage (&msg, NULL, 0 , 0 )) {
Trang 24Định nghĩa lớp cửa sổ WNDCLASS
• Windows cung cấp một cấu trúc WNDCLASS (file
winuser.h) gọi là lớp cửa sổ
• Lớp này chứa các thuộc tính tạo thành một cửa sổ
typedef struct _WNDCLASS
{ UINT style;
Trang 2525
Định nghĩa lớp cửa sổ WNDCLASS
• Ý nghĩa thuộc tính lớp cửa sổ WNDCLASS:
style Kiểu lớp Kết hợp nhiều kiểu giá trị khác nhau bằng
toán tử OR.
lpfnWndProc Con trỏ đến thủ tục xử lý cửa sổ
cbClsExtra Số byte được cấp phát thêm sau
cấu trúc window-class Mặc định
cbWndExtra Số byte được cấp phát thêm sau
một instance của window Mặc định
hInstance Định danh chứa thủ tục cửa sổ
của lớp window
hIcon Định danh của biểu tượng Dùng hàm LoadIcon
hCursor Định danh của con trỏ chuột Dùng hàm LoadCursor
hbrBackground Định danh của chổi tô nền Dùng hàm GetStockObject
lpszMenuName Tên thực đơn
Tên thực đơn gắn với cửa sổ, thực đơn này được khai báo trong tập tin tài nguyên.
lpszClassName Tên lớp
25
Trang 2727
Tạo cửa sổ
• Lớp cửa sổ thể hiện đặc tính chung cửa sổ Cho
phép tạo nhiều thể hiện cửa sổ của lớp
• Dùng hàm CreateWindow, chỉ định các đặc tính
riêng của cửa sổ, và phân biệt nó với các cửa sổ
khác tạo ra cùng một lớp
HWND CreateWindow(LPCSTR lpClassName, // Tên lớp cửa sổ đã đăng ký
LPCSTR lpwindowName, // Tên của cửa sổ
DWORD dwStyle, // Kiểu của cửa sổ
int x, // Vị trí ngang ban đầu
int y, // Vị trí dọc ban đầu
int nWidth, // Ðộ rộng ban đầu
int nHeight, // Ðộ cao ban đầu
HWND hWndParent, // Ðịnh danh của cửa sổ cha
MENU hMenu, // Ðịnh dang của thực đơn
INSTANCE hInstance, // Ðịnh danh thể hiện ứng dụng
PVOID lpParam // Các tham số ban đầu
) ;
27 Lập trình Windows
Trang 28Hiển thị cửa sổ
• Để xuất hiện cửa sổ gọi hàm ShowWindow
BOOL ShowWindow(HWND hWnd, // Ðịnh danh của cửa sổ cần thể hiện
int iCmdShow // Trạng thái hiển thị
• Một số trạng thái hiển thị (iCmdShow):
SW_HIDE: Ẩn cửa sổ.
SW_MAXIMIZE: Phóng cửa sổ ra toàn bộ màn hình.
SW_MINIMIZE: Thu nhỏ thành biểu tượng trên màn hình.
SW_RESTORE: Hiển thị dưới dạng chuẩn.
28 Lập trình Windows
Trang 2929
1.2.2 Hàm xử lý thông điệp WinProc
• Có thể có nhiều hơn một hàm xử lý thông điệp
• Luôn đi kèm cửa sổ của nó
• Giao tiếp với hệ thống (Windows), toàn bộ các
thông điệp gửi tới được xử lý qua hàm này
• Thường khai báo như sau:
• Trong đó tham số đầu tiên là định danh của cửa sổ,
tham số thứ 2 là định danh thông điệp, và cuối cùng
là 2 tham số WPARAM và LPARAM bổ sung thông
tin kèm theo thông điệp
LRESULT CALLBACK WinProc (HWND, UINT, WPARAM, LPARAM);
29 Lập trình Windows
Trang 30Message Loop
• Windows duy trì một hàng đợi thông điệp cho mỗi
chương trình
• Khi sự kiện nhập thông tin xuất hiện, Windows
dịch sự kiện thành dạng thông điệp và đưa vào
hàng đợi thông điệp của ứng dụng tương ứng
• Ứng dụng nhận thông điệp từ hàng đợi bằng đoạn
mã:
MSG msg; // Windows message structure
while (GetMessage(&msg, NULL, 0,0)) {
TranslateMessage (&msg);
DispatchMessage (&msg);
}
30 Lập trình Windows
Trang 3131
Message Loop
• Trong đó msg là một biến cấu trúc kiểu MSG được
định nghĩa trong winuser.h
typedef struct tagMSG {
• POINT là kiểu tọa độ điểm, định nghĩa trong windef.h
typedef struct tagPOINT {
LONG x;
LONG y;
Trang 32Message Loop
• Hàm GetMessage sẽ trả về 0 nếu msg chứa
thông điệp có định danh WM_QUIT
(0x0012), khi đó vòng lặp thông điệp ngưng
và ứng dụng kết thúc
• Ngược lại thì hàm sẽ trả về một giá trị khác 0
với các thông điệp khác.
32 Lập trình Windows
Trang 3333
Multitasking
33 Lập trình Windows
Trang 34Hàm xử lý thông điệp WinProc - Ví dụ
• Tìm hiểu một hàm xử lý cửa sổ:
LRESULT CALLBACK WinProc (HWND hwnd, UINT msg, WPARAM
wParam, LPARAM lParam)
Trang 3535
• Thông thường chỉ chặn để xử lý các thông điệp cần thiết, còn
lại giao cho hàm xử lý mặc địnhDefWindowProc
DrawText(hdc, "Hello" , - 1 , &rect, DT_SINGLELINE| DT_CENTER| DT_VCENTER);
return DefWindowProc (hwnd, msg, wParam, lParam);
}
35
Trang 36Tóm tắt
36 Lập trình Windows
Trang 3737
1.2.3 Chương trình Windows đơn giản
- Chương trình: HelloWorld (Sử dụng trực tiếp
Windows API)
- 2 hàm chính
- Hàm WinMain: thực hiện c|c chức năng
- Khai b|o lớp cửa sổ
- Đăng ký lớp cửa sổ vừa khai b|o
- Tạo v{ hiển thị lớp cửa sổ
- Vòng lặp nhận thông điệp v{ gửi tới thủ tục xử lý
- Hàm WinProc: H{m xử lý thông điệp gửi đến C|c
thông điệp được Windows xử lý mặc định bằng h{m
DefWindowProc()
37 Lập trình Windows
Trang 38Win32 Application in Visual C++ Developer Studio
38 Lập trình Windows
Trang 39LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR
szCmdLine, int iCmdShow)
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
Trang 40HelloWorld (2)
hwnd = CreateWindow(szAppName, // Tên lớp cửa sổ
TEXT (" The Hello World Program"), //
Trang 41DrawText(hdc, TEXT( "Hello World" ), - 1 , &rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER);
return DefWindowProc (hwnd, msg, wParam, lParam);
}
41 Lập trình Windows
Trang 42HelloWorld (run)
42 Lập trình Windows
Trang 4343
Ý nghĩa các hàm trong HelloWorld
Tên hàm Ý nghĩa
LoadIcon Nạp một biểu tượng để sử dụng trong chương trình.
LoadCursor Nạp một con trỏ chuột cho chương trình.
MessageBox Hiển thị một thông điệp.
CreateWindow Tạo một cửa sổ dựa trên một lớp cửa sổ.
ShowWindow Hiển thị cửa sổ lên màn hình.
UpdateWindow Yêu cầu cửa sổ vẽ lại chính bản thân nó.
GetMesssage Nhận một thông điệp từ hàng đợi thông điệp.
TranslateMessage Dịch thông điệp bàn phím.
DispatchMessage Gởi thông điệp đến hàm xứ lý cửa sổ.
BeginPaint Khởi tạo chức năng vẽ của cửa sổ.
GetClientRect Lấy hình chữ nhật lưu vùng làm việc.
DrawText Hiển thị một chuỗi văn bản.
EndPaint Kết thúc việc vẽ cửa sổ.
PostQuitMessage Đưa thông điệp thoát vào hàng đợi thông điệp.
DefWindowProc Thực hiện việc xử lý mặc định các thông điệp.
43
Trang 441.3 Microsoft Foundation Classes (MFC)
• MFC = Microsoft Foundation Classes
• Thư viện c|c lớp đóng gói c|c h{m Win32
Trang 4545
MFC và Win32 API
• Win32 API: tập hợp các hàm, cấu trúc, thông
điệp, macros và interfaces
– Cho phép phát triển ứng dụng Win32 platforms
– Program low-level, tiêu tốn thời gian
Trang 46MFC và Win32 API – Ví dụ
• Khái niệm Win32 của một cửa sổ (window) được
đóng gói bởi lớp CWnd trong MFC
• CWnd chứa 1 biến thành viên kiểu HWND (kiểu dữ
liệu định nghĩa Win32 biểu diễn một cửa sổ)
• CWnd chứa các phương thức đóng gói gọi đến các
hàm Win32 mà dùng HWND như 1 tham số
• Ví dụ:
– Hàm: BOOL ShowWindow(HWND hWnd, int nCmdShow);
– Được đóng gói trong MFC:
BOOL CWnd::ShowWindow(int nCmdShow);
46 Lập trình Windows
Trang 4747
MFC Application Framework
• Ngoài việc đóng gói của Win32 API, MFC còn định
nghĩa một nhóm các lớp để biểu biễn các object ứng
dụng chung và thiết lập mối quan hệ trong nhóm
này để thực thi các hành vi của ứng dụng
• Application Framework: một nền tảng để xây dựng
các ứng dụng
• Dùng MFC Wizard để tạo ra tập hợp các lớp dẫn
xuất từ các lớp của framework
• Hoặc xây dựng các lớp mới theo yêu cầu sử dụng
47 Lập trình Windows
Trang 4848 Lập trình Windows
Trang 4949
Cấu trúc ứng dụng MFC
• Ứng dụng MFC cung cấp:
– Một lớp biểu diễn ứng dụng (Application Class)
– Một lớp biểu diễn cửa sổ chính của ứng dụng
(Main Window)
– Triển khai h{m WinMain() (được ẩn đi)
(WinMain() Function)
49 Lập trình Windows
Trang 501.4 Lập trình Windows với VC++ 2008
• 3 c|ch tạo ứng dụng Windows với VC++:
– Ứng dụng sử dụng trực tiếp Windows API
Trang 5353
The Solution
• Solution Explorer: allows you to view and
navigate all the files that make up your
application.
• Class View allows you to navigate and
manipulate your source code on a C++ class
level.
• Resource View: allows you to find and edit
each of the various resources in your
application, including dialog window
designs, icons, and menus.
53 Lập trình Windows
Trang 54Output Pane & Editor Area
• Output Pane:
– Cung cấp thông tin cho người lập trình
– Compiler progress statements
– Warnings, error messages
– Thông tin debugger:
– Current values of variables when step through code (Cửa
Trang 5555
Menu Bar + Rearranging IDE
• Menu bar + Tool bars
• Kéo thả, bố trí c|c cửa sổ l{m việc
• Floating, Dock, Auto hiden, ….
55 Lập trình Windows
Trang 56C|c th{nh phần ứng dụng ph|t triển với VC++
56
Trang 5757
Character Sets, và _T macro (1)
• Old Windows: Tập ký tự ANSI 8 bit
• Windows NT: Tập ký tự Unicode 16 bit (bao
trùm ANSI)
• Biên dịch ứng dụng VC++ trên Windows NT
có thể chọn sử dụng Unicode hoặc không.
• Nếu một chuỗi “Hello” thì trình biên dịch sẽ
thể hiện dạng ANSI (8bit/1 ký tự).
• Nếu chuỗi L”Hello” thì trình biên dịch sẽ thể
hiện dạng chuỗi Unicode.
57 Lập trình Windows
Trang 58Character Sets, và _T macro (2)
• Dùng macro _T (của MFC) cho chuỗi dạng
_T(“Hello”) thì kết quả sẽ được thể hiện dạng
Unicode nếu ký hiệu tiền xử lý _UNICODE
được định nghĩa (chọn kiểu chuỗi ký tự
Unicode cho ứng dụng), nếu không mặc định
l{ ký tự ANSI.
58