TRƯỜNG ĐẠI HỌC KỸ THUẬT TP. HỒ CHÍ MINH
KHOA CÔNG NGHỆ THÔNG TIN
oOo
BÁO CÁO
LUẬN VĂN TỐT NGHIỆP
Đề tài:
- Nghiên cứu các phương pháp nhận dạng từ
dưới cursor mouse trên Desktop Windows.
- Viết chương trình nhận dạng từ này.
Giáo viên hướng dẫn : Tiến Só Nguyễn Văn Hiệp
Sinh viên thực hiện : Võ Minh Trực (Lớp KS2-K5T)
Phùng Đình Mân (Lớp KS2-K6T)
Tháng 7 năm 1999
Chúng tôi xin chân thành cảm
ơn quý Thầy Cô khoa Công Nghệ
Thông Tin - Trường Đại Học Kỹ Thuật
và các bạn cùng lớp đã giúp đỡ chúng
tôi thời gian qua, đặc biệt, lòng biết ơn
sâu sắc đến Thầy Nguyễn Văn Hiệp -
Tiến Só Tin Học - đã tận tình hướng
dẫn chúng tôi hoàn thành Luận Án Tốt
nghiệp này.
KHOA CÔNG NGHỆ THÔNG TIN - TRƯỜNG ĐẠI HỌC KỸ THUẬT TP.HCM
MỤC LỤC
PHẦN I: THUYẾT MINH 2
LỜI MỞ ĐẦU 3
CHƯƠNG 1: TÌM HIỂU VỀ LẬP TRÌNH WINDOWS 4
I. Khái quát về lập trình trong Windows 5
II. Thông điệp và xử lý thông điệp 6
III. Giao diện thiết bò đồ họa GDI 10
IV. Cửa sổ trong Windows 13
V. Chương trình Windows tiếp nhận thông điệp chuột 18
CHƯƠNG 2: TÌM HIỂU VỀ HOOK 21
1 - Chuỗi hook 22
2 - Thủ tục hook 22
3 - Các loại hook 23
4 - Sử dụng hook 24
5 - Hook trong Windows 3.x 25
6 - Giới thiệu một số hàm liên quan đến hook 26
CHƯƠNG 3: KỸ THUẬT OVERRIDE HÀM API 29
I. Khái quát về kỹ thuật override 30
II. Lý do sử dụng kỹ thuật override trong lập trình Windows 30
III. Cơ chế hoạt động và quản lý bộ nhớ trên Windows 16bits 31
IV. Cơ chế hoạt động và quản lý bộ nhớ trên Windows 32bits 33
V. Hiện thực kỹ thuật override trên Windows 16bits 36
VI. Một số hàm được sử dụng trong kỹ thuật override 40
CHƯƠNG 4: KẾT XUẤT VĂN BẢN TRONG WINDOWS 43
I. Kết xuất văn bản trong Windows 44
II. Các hàm căn bản để kết xuất văn bản 44
CHƯƠNG 5: PHÂN TÍCH VÀ THIẾT KẾ CHƯƠNG TRÌNH 53
I. Phân tích vấn đề 54
II. Thiết kế chương trình 55
III. Giới thiệu một số hàm có liên quan 64
IV. Giới thiệu một số cấu trúc dữ liệu có liên quan 75
KẾT QUẢ VÀ HƯỚNG PHÁT TRIỂN 79
PHẦN II: CHƯƠNG TRÌNH NGUỒN 80
CÁCH DÙNG CHƯƠNG TRÌNH 103
TÀI LIỆU THAM KHẢO 104
BÁO CÁO LUẬN VĂN TỐT NGHIỆP
Đề tài : “NHẬN DẠNG TỪ DƯỚI CURSOR MOUSE TRÊN DESKTOP WINDOWS”
1
KHOA CÔNG NGHỆ THÔNG TIN - TRƯỜNG ĐẠI HỌC KỸ THUẬT TP.HCM
Phần I:
BÁO CÁO LUẬN VĂN TỐT NGHIỆP
Đề tài : “NHẬN DẠNG TỪ DƯỚI CURSOR MOUSE TRÊN DESKTOP WINDOWS”
2
KHOA CÔNG NGHỆ THÔNG TIN - TRƯỜNG ĐẠI HỌC KỸ THUẬT TP.HCM
Lời mở đầu
Lời mở đầu
gày nay, hầu như mọi công việc hàng ngày liên quan đến cuộc sống của chúng ta
đều diễn ra trên máy tính. Từ việc soạn thảo văn bản, gởi nhận thông tin
đến việc tra cứu, truy cập thông tin từ hệ thống mạng máy tính toàn cầu Internet đối
với người sử dụng là công việc thường ngày và rất phổ biến.
Từ đó, sẽ phát sinh vấn đề là người sử dụng sẽ cần tìm hiểu ý nghóa của một
từ, một câu hoặc cần phải dòch một đoạn văn bản, một file dữ liệu nào đó ra tiếng
Việt và ngược lại. Đây là một nhu cầu cần thiết và hầu như xảy ra thường xuyên đối
với nhiều người, do đó nhận dạng từ đặc biệt là nhận dạng từ trên màn hình trong
môi trường Windows là việc làm cần thiết và có ý nghóa thực tế.
Kết quả của việc nhận dạng từ sẽ được dùng để xây dựng nên các ứng dụng
khác chẳng hạn như các từ điển được tra cứu theo kiểu tương tác trực tiếp sẽ rất
thuận tiện cho người sử dụng bởi vì theo cách này thì cho dù đang ở trong bất kỳ ứng
dụng nào khi cần tra cứu thì thao tác trực tiếp ngay trên ứng dụng đang dùng tức là
chỉ cần click chuột vào đó chứ không cần phải mở từ điển rồi tra cứu từ đó theo kiểu
cổ điển.
Vì thế, trong thời gian làm Luận Án Tốt nghiệp được sự hướng dẫn của Tiến Só
Tin Học Nguyễn Văn Hiệp nhóm sinh viên chúng tôi thực hiện đề tài: “ Nhận dạng
từ dưới cursor mouse trên deskop Windows. Viết chương trình nhận dạng từ này ”.
Trong giai đoạn đầu của Luận Án Tốt Nghiệp chúng tôi đã nghiên cứu được một số
vấn đề quan trọng và căn bản có ý nghóa trong việc thực hiện yêu cầu đã đặt ra của
đề tài. Đề tài này chỉ tập trung nhận dạng từ ở dạng text trên desktop của môi trường
Windows rồi xuất kết quả ra.
Trong thời gian làm Luận Án Tốt Nghiệp nhóm sinh viên chúng tôi đã tiến
hành nghiên cứu cơ chế hoạt động và quản lý của hệ điều hành Windows. Nghiên
cứu về phương thức lập trình trong môi trường Windows và các phương tiện mà
Windows hỗ trợ khi lập trình. Tham khảo và nghiên cứu kỹ thuật override các hàm
giao tiếp của Windows ở chế độ 16 bit và 32 bit. Nghiên cứu cách xử lý các thông
điệp trong Windows và tìm hiểu về cách kết xuất văn bản, về chế độ ánh xạ, vấn đề
tọa độ . . . và cách xử lý văn bản. Trên cơ sở đó bước đầu chúng tôi đã xây dựng
xong một ứng dụng có khả năng nhận dạng được từ trên nền Windows 16 bit được
viết bằng ngôn ngữ Visual C++ version 1.5 và hướng phát triển trong thời gian tới là
hiện thực nó trên nền Win32.
Báo cáo của chúng tôi sẽ lần lượt điểm qua những nội dung mà chúng tôi đã
nghiên cứu và tìm hiểu được trong thời gian qua. Sau đó là phần giới thiệu chi tiết về
chương trình từ khâu phân tích-thiết kế cho đến phần chương trình nguồn và cuối
cùng sẽ là nêu những vấn đề còn tồn tại và hướng phát triển trong tương lai.
BÁO CÁO LUẬN VĂN TỐT NGHIỆP
Đề tài : “NHẬN DẠNG TỪ DƯỚI CURSOR MOUSE TRÊN DESKTOP WINDOWS”
3
KHOA CÔNG NGHỆ THÔNG TIN - TRƯỜNG ĐẠI HỌC KỸ THUẬT TP.HCM
Chương 1:
TÌM HIỂU VỀ
TÌM HIỂU VỀ
LẬP TRÌNH WINDOWS
LẬP TRÌNH WINDOWS
BÁO CÁO LUẬN VĂN TỐT NGHIỆP
Đề tài : “NHẬN DẠNG TỪ DƯỚI CURSOR MOUSE TRÊN DESKTOP WINDOWS”
4
KHOA CÔNG NGHỆ THÔNG TIN - TRƯỜNG ĐẠI HỌC KỸ THUẬT TP.HCM
I - KHÁI QUÁT VỀ LẬP TRÌNH TRONG WINDOWS:
1 - Khái quát về lập trình trong Windows:
Môi trường lập trình Windows về cơ bản là dựa trên bộ hàm API (Application
Programmer Interface), nó có chức năng như các ngắt trong bảng vector ngắt của
DOS, nhưng nó thân thiện hơn ở chỗ cách gọi hàm API giống hệt cách gọi hàm của
ngôn ngữ cấp cao, mỗi hàm có một tên gọi hẳn hoi, và tên gọi thường được đặt rất
phù hợp với công dụng của hàm (mặc dù có hơi dài dòng) từ đó tạo khả năng gợi
nhớ cao. Với Windows, người lập trình không còn phải lập trình theo kiểu assembly
nữa mà lập trình theo kiểu ngôn ngữ cấp cao, mọi hoạt động trong máy ở mức thấp
từ hàm API trở xuống thuộc phạm vi của Windows, và Windows không khuyến
khích việc các ứng dụng can thiệp vào lónh vực này. Bù lại, bằng các hàm API, nó
hỗ trợ rất hiệu quả cho người lập trình, giúp khai thác khả năng của thiết bò triệt để,
dễ dàng và tiện lợi hơn bao giờ hết. Có thể nói Windows đã mở ra cho người lập
trình không gian rộng lớn để phát triển ứng dụng, và hạn chế không gian phát triển
hệ thống. Điều này dẫn đến hệ quả là các ứng dụng được tạo ra hết sức dễ dàng, và
quan trọng là hệ thống chạy ổn đònh hơn, không bò treo do lỗi của ứng dụng,
không thể xâm nhập, nhưng sẽ rất khó khăn nếu người lập trình muốn trực tiếp điều
khiển hoạt động trong máy và phát triển về lập trình hệ thống.
- Tìm hiểu hàm Windows API: Windows là một hệ điều hành đa nhiệm
(multitasking) mà qua đó các ứng dụng ở trong môi trường Windows sẽ giao tiếp với
user thông qua một hay nhiều giao diện. Để truy cập các giao diện này thì các ứng
dụng được xây dựng trên môi trường Windows sẽ sử dụng tập các hàm được gọi là
giao diện chương trình ứng dụng API (Application Program Interface). Chương trình
của người sử dụng có thể gọi tới các hàm API để truy cập tới mọi tài nguyên của
Windows. GDI là một bộ phận của API, giao diện thiết bò đồ họa GDI (Graphic
Device Interface) có nhiệm vụ duy trì sự độc lập của Windows đối với các thiết bò
đồ họa hay còn gọi là khả năng độc lập thiết bò (device independent) tức là cho phép
Windows làm việc với nhiều kiểu thiết bò đồ họa khác nhau.
2 - Thư viện liên kết động DLL (Dynamic Link Library):
Thư viện liên kết động là các tập tin được Windows lưu dưới dạng nhò phân
chứa các hàm mà mọi ứng dụng trên Windows đều có thể sử dụng. Nét đặc trưng
của DLL là nó có thể được sử dụng bởi nhiều ứng dụng tại cùng một thời điểm hay
nói cách khác thư viện liên kết động có thể cùng một lúc được gọi bởi nhiều chương
trình. DLL là một dữ liệu chia sẻ được (shared data).
Có 3 loại DLL khác nhau:
- Thư viện liên kết động API: thuộc hệ thống Windows, khi cài hệ điều hành
thì nó đã có sẵn. Chúng được nạp khi Windows khởi động.
- Thư viện liên kết động third party: do các công ty khác tạo ra trên môi trường
Windows, hỗ trợ thêm công tác lập trình trong Windows.
BÁO CÁO LUẬN VĂN TỐT NGHIỆP
Đề tài : “NHẬN DẠNG TỪ DƯỚI CURSOR MOUSE TRÊN DESKTOP WINDOWS”
5
KHOA CÔNG NGHỆ THÔNG TIN - TRƯỜNG ĐẠI HỌC KỸ THUẬT TP.HCM
- Thư viện liên kết động do chúng ta tạo ra.
Windows sử dụng cấu trúc thư viện liên kết động DLL (Dynamic Link Library)
nhằm mục đích không sao chép một khối lượng lớn các mã vào trong chương trình
như ở các thư viện thông thường. Nhờ cấu trúc động của DLL nên mọi chương trình
đều có thể truy cập thư viện trong thời gian thực thi. Các hàm API được Windows
giữ dưới dạng hỗn hợp trong một số DLL. Trong quá trình dòch khi gặp lệnh gọi hàm
API từ chương trình ứng dụng thì chương trình dòch không thêm mã này vào module
thực hiện mà chỉ thêm các lệnh liên kết (chứa tên của DLL bên trong có hàm cần
nạp) và tên hàm đó. Khi thực thi chương trình thì hàm API thực sự mới được nạp vào
bộ nhớ để thực hiện.
Cùng với sự phát triển của Windows là sựï phát triển của lập trình hướng đối
tượng, và để hỗ trợ cho việc lập trình hướng đối tượng, Microsoft đã cung cấp cho
người lập trình một bộ thư viện các lớp cơ bản để phát triển các ứng dụng hướng đối
tượng gọi là MFC (Microsoft Foundation Classes), nội dung của nó bao gồm thông
tin về các lớp cơ bản được chuẩn hóa như lớp application; document; view; OLE; cửa
sổ; nút bấm; text; v.v…, trong các lớp này mọi thứ liên quan đến nó (bao gồm dữ liệu
và các chương trình xử lý của nó) đều được làm hoàn chỉnh, người lập trình chỉ việc
lấy ra sử dụng, hoặc có thể thêm bớt một ít tính năng đặc trưng cho đối tượng của
mình. Mục tiêu chính của MFC là hệ thống hóa các hàm API, cung cấp một thể thức
gọi gọn các hàm API, cung cấp một “khung làm việc” (framework) cực mạnh để
người lập trình không cần phải quan tâm đến những đoạn chương trình thuộc về “thủ
tục” mà chỉ cần quan tâm đến phần cốt lõi để đạt được mục đích.
II - THÔNG ĐIỆP VÀ XỬ LÝ THÔNG ĐIỆP:
1 - Khái niệm:
Lập trình trên môi trường Windows khác với lập trình ở các môi trường khác ở
điểm là lập trình trên Windows luôn luôn gắn liền với những thông điệp. Mọi hoạt
động xảy ra trên một chương trình Windows đều thông qua các thông điệp. Thông
điệp sẽ được hệ thống báo cho các ứng dụng biết các tác động từ bên ngoài vào hệ
thống Windows. Một cửa sổ có thể gởi đi một thông điệp cho một cửa sổ khác và
các cửa sổ đáp ứng lại thông điệp bằng cách gởi đi một thông điệp khác cho một cửa
sổ khác.
Trong Windows có 3 loại thông điệp cơ bản:
- Những thông điệp tổng quát: có mã nhận diện mang tiền tố WM_ được coi là
phần lớn trong ứng dụng và Windows đã cung cấp các hàm để giải quyết.
- Những control notification: đây là những thông điệp WM_COMMAND được
chuyển từ cửa sổ con tới cửa sổ bố mẹ.
- Những nút lệnh: là thông điệp WM_COMMAND phát đi từ trình đơn, từ các
nút điều khiển. Đây là loại thông điệp yêu cầu ứng dụng phải thực hiện một công
việc gì đó.
BÁO CÁO LUẬN VĂN TỐT NGHIỆP
Đề tài : “NHẬN DẠNG TỪ DƯỚI CURSOR MOUSE TRÊN DESKTOP WINDOWS”
6
KHOA CÔNG NGHỆ THÔNG TIN - TRƯỜNG ĐẠI HỌC KỸ THUẬT TP.HCM
2 - Gởi đi các thông điệp:
Windows cho phép ứng dụng gởi đi những thông điệp cho mình, cho các ứng
dụng khác hoặc cho hệ thống.
Có 3 hàm Windows API để gởi thông điệp đi:
a) Hàm SendMessage:
Cú pháp:
LRESULT SendMessage(hwnd, uMsg, wParam, lParam)
HWND hwnd; // handle của cửa sổ nhận (đích)
UINT uMsg; // thông điệp để gởi
WPARAM wParam; // thông số thông điệp đầu tiên
LPARAM lParam; // thông số thông điệp thứ hai
- Hàm SendMessage gởi thông điệp tới một hay nhiều cửa sổ. Hàm gọi thủ tục
cửa sổ cho cửa sổ và không trở về cho đến lúc thủ tục cửa sổ đã xử lý thông điệp.
- Giá trò trả về: cho biết kết quả xử lý thông điệp và phụ thuộc vào thông điệp
được gởi.
b) Hàm PostMessage:
- Cú pháp:
BOOL PostMessage(hwnd, uMsg, wParam, lParam)
HWND hwnd; // handle của của sổ đích
UINT uMsg; // thông điệp gởi
WPARAM wParam; // thông số thông điệp đầu tiên
LPARAM lParam; // thông số thông điệp thứ hai
- Hàm PostMessage gởi (đặt) một thông điệp vào trong hàng thông điệp cửa sổ
và rồi trở về mà không đợi cửa sổ tương ứng xử lý thông điệp. Những thông điệp
trong một hàng thông điệp được lấy bằng cách gọi hàm SetMessage hay
PeekMessage.
- Giá trò trả về: trả về khác 0 nếu thành công, ngược lại 0.
c) Hàm SendDlgItemMessage:
- Cú pháp:
LRESULT SendDlgItemMessage(hwndDlg,idDlgItem,uMsg,wParam,lParam)
HWND hwndDlg; // handle của hộp hội thoại
int idDlgItem; // mã nhận diện ô điều khiển sẽ nhận thông điệp
UINT uMsg; // thông điệp gởi đi
WPARAM wParam; // thông số thông điệp đầu tiên
LPARAM lParam; // thông số thông điệp thứ hai
BÁO CÁO LUẬN VĂN TỐT NGHIỆP
Đề tài : “NHẬN DẠNG TỪ DƯỚI CURSOR MOUSE TRÊN DESKTOP WINDOWS”
7
KHOA CÔNG NGHỆ THÔNG TIN - TRƯỜNG ĐẠI HỌC KỸ THUẬT TP.HCM
- Hàm SendDlgItemMessage gởi một thông điệp tới một điều khiển trong hộp
hội thoại.
- Giá trò trả về: cho biết kết quả xử lý thông điệp và phụ thuộc vào thông điệp
được gởi.
3 - Vòng lặp thông điệp:
Một thread hoặc một process đẩy một thông điệp ra khỏi hàng đợi bằng cách
dùng vòng lặp thông điệp. Vòng loop chính của một ứng dụng đặt tại cuối hàm
WinMain() của ứng dụng đó. Vòng lặp thông điệp có dạng như sau:
while GetMessage(&msg,NULL,0,0)
{ TranslateMessage(&msg);
DispatchMessage(&msg);
}
Sau đây là Sơ đồ dòng thông điệp:
Nó mô tả đơn giản hóa quá trình xử lý thông điệp. Thông điệp có thể bắt
nguồn từ nhiều cách khác nhau, sơ đồ sau đây sẽ giải thích chi tiết hơn về vòng lặp
thông điệp và chỉ ra cách thông điệp được đặt vào hàng đợi như thế nào:
BÁO CÁO LUẬN VĂN TỐT NGHIỆP
Đề tài : “NHẬN DẠNG TỪ DƯỚI CURSOR MOUSE TRÊN DESKTOP WINDOWS”
8
Thread1 Message Queue Thread2 Message Queue Thread3 Message Queue
System Dispatcher
Hardware Event Occur
System Message Queue
GetMessage()
TranslateMessage()
Dispatch Message()
GetMessage()
TranslateMessage()
Dispatch Message()
GetMessage()
TranslateMessage()
Dispatch Message()
WndProc()
WndProc() WndProc()
DefWndProc()
DefWndProc() DefWndProc()
Thread1 Hook Thread2 Hook Thread3 Hook
System Dispatcher
KHOA CÔNG NGHỆ THÔNG TIN - TRƯỜNG ĐẠI HỌC KỸ THUẬT TP.HCM
Thông điệp không chỉ phát xuất từ sự kiện phần cứng, cũng có thể có thông
điệp của chương trình phát xuất từ một chương trình đang chạy. Các threads có thể
gởi dữ liệu trở về sau và về trước bằng cách gởi thông điệp. Thông điệp có thể gởi
vào hàng đợi bằng hàm PostMessage() , hoặc chúng có thể được gởi trực tiếp cho
vòng lặp thông điệp để xử lý ngay lập tức bằng hàm SendMessage().
4 - Xử lý thông điệp:
Việc xử lý thông điệp là yếu tố chính làm cho các ứng dụng Windows vận
hành được. Hệ thống và các ứng dụng khác sinh ra các thông điệp cho mọi sự kiện
xuất hiện trong hệ thống thông điệp của Windows sẽ cho phép Windows chạy đa
nhiệm trong một thời điểm. Windows 95 và Windows NT mở rộng khả năng của
version Windows trước bằng việc cấp phát cho mỗi dòng xử lý (thread) hay mỗi tiến
trình (proccess) một hàng đợi thông điệp riêng. Trong version Windows cũ thì tất cả
ứng dụng đều dùng chung một hàng đợi thông điệp, vì thế để các ứng dụng khác xử
lý thông điệp, ứng dụng phải trả quyền điều khiển về cho Windows mỗi khi nó có
thể. Với Windows 95 và Windows NT, điều này không còn nữa.
Windows sinh ra thông điệp cho mọi sự kiện phần cứng, ví dụ như người dùng
nhấn một phím hoặc di chuyển chuột. Nó gởi thông điệp đến hàng đợi thông điệp
của thread thích hợp, nếu thông điệp được dành cho nhiều thread thì nó cũng được
đưa vào các hàng đợi của các thread đó.
Một thông điệp trên thực tế là một cấu trúc dữ liệu như sau:
typedef struct tagMSG {
HWND hwd; // handle cửa sổ
UINT message; //số chỉ đònh loại message
WPARAM wParam; //được chuyển cho WndProc()
LPARAM wParam; //được chuyển cho WndProc()
DWORD time; //số mili giây từ lúc bắt đầu
POINT pt; //cấu trúc điểm POINT
BÁO CÁO LUẬN VĂN TỐT NGHIỆP
Đề tài : “NHẬN DẠNG TỪ DƯỚI CURSOR MOUSE TRÊN DESKTOP WINDOWS”
9
Hardware Events
Message Sent
From Other Threads
System Dispatcher
System Message Queue
Thread Message Queue
WndProc()
Message Loop
PostMessage()
TranslateMessage()
SentMessage()
SentMessage()
(To Another Thread)
Other threads
PostMessage()
Other threads
PostMessage()
KHOA CÔNG NGHỆ THÔNG TIN - TRƯỜNG ĐẠI HỌC KỸ THUẬT TP.HCM
}
III - GIAO DIỆN THIẾT BỊ ĐỒ HỌA GDI
(GRAPHIC DEVICE INTERFACE):
1 - Khái niệm:
Windows là một hệ điều hành đa nhiệm (multitasking) trong đó các ứng dụng
giao tiếp với user thông qua một hay nhiều giao diện. Để truy xuất các giao diện thì
chương trình ứng dụng phải sử dụng các hàm Giao diện chương trình ứng dụng. API
là tập các lệnh mà một ứng dụng sử dụng để yêu cầu và tiến hành các dòch vụ cấp
thấp được thi hành bởi Windows.
Giao diện thiết bò đồ họa GDI (Graphic Device Interface) là một phần của API
có nhiệm vụ duy trì sự độc lập của Windows đối với các thiết bò đồ họa (cho phép
Windows làm việc với nhiều thiết bò đồ họa khác nhau). Windows GDI là một thư
viện bao gồm một số hàm giúp kết xuất đồ họa (graphic output) lên màn hình, máy
in…GDI sẽ tạo ra: điểm, đường kẻ, hình dạng (shape: chữ nhật, tròn…), chữ văn bản.
2 - Device Context:
Ngữ cảnh thiết bò DC (Device Context) là một phần quan trọng của GDI
Windows. Một DC là một cấu trúc dữ liệu dài khoảng 800 bytes được Windows duy
trì có nhiệm vụ lo lưu giữ những thông tin cần thiết mà ứng dụng sẽ cần đến khi phải
hiển thò kết xuất lên một thiết bò vật lý. GDI không bao giờ cho phép chương trình
làm việc trực tiếp với một DC mà GDI phân phối cho chương trình một handle để
nhận dạng một DC cụ thể. Tất cả các hàm API; GDI đều nhận thông số đầu tiên là
một handle – hdc.
DC là một công cụ chứa các thuộc tính vẽ, DC cho phép kết nối logic một
chương trình về một thiết bò cụ thể nào đó. Ngoài ra do Windows là một hệ điều
hành đa nhiệm nên các chương trình không thể truy xuất trực tiếp các thiết bò vật lý
để tránh xung đột. Thay vào đó, chương trình Windows phải sử dụng kết nối logic do
DC đại diện. Nghóa là tất cả các chương trình cách tiếp cận này để GDI có thể giải
quyết tranh chấp khi 2 chương trình yêu cầu dùng cùng một thiết bò nên DC còn có
vai trò làm permission slip. DC lưu trữ thông tin liên quan đến mặt bằng vẽ và
những khả năng của nó. Trước khi sử dụng bất kỳ hàm vẽ GDI nào thì điều phải tạo
một DC cho thiết bò, và khi sử dụng xong thì phải trả nó về cho Windows nhằm đảm
bảo cho hoạt động của hệ thống được thông suốt bởi vì số lượng DC mà Windows
quản lý là có giới hạn.
DC ở Win16: Ngữ cảnh thiết bò (DC) là một nối kết giữa một ứng dụng
Windows, một driver thiết bò và một thiết bò đầu ra (output device). Windows duy trì
một cache gồm 5 DC đặc biệt cho hoạt động hệ thống. Ứng dụng phải giải phóng
các DC này sau khi sử dụng.
Luồng thông tin từ ứng dụng Windows qua DC và device driver tới thiết bò đầu
ra:
BÁO CÁO LUẬN VĂN TỐT NGHIỆP
Đề tài : “NHẬN DẠNG TỪ DƯỚI CURSOR MOUSE TRÊN DESKTOP WINDOWS”
10
KHOA CÔNG NGHỆ THÔNG TIN - TRƯỜNG ĐẠI HỌC KỸ THUẬT TP.HCM
Truy xuất thiết bò đầu ra (Accessing Output Devices): Bất kỳ ứng dụng
Windows nào cũng có thể sử dụng hàm GDI để truy xuất một thiết bò đầu ra. GDI
chuyển các gọi độc lập thiết bò từ ứng dụng tới driver thiết bò. Rồi driver thiết bò
thông dòch các gọi đó vào trong sự hoạt động độc lập thiết bò.
Những đặc tính của DC mô tả các đối tượng vẽ được chọn (pens và brushes),
font được chọn và màu của nó, cách thức mà đối tượng được vẽ (hay ánh xạ) tới
thiết bò, vùng trên thiết bò có sẵn cho output (vùng xén) và những thông tin quan
trọng khác. Cấu trúc chứa những đặc tính DC được gọi là khối dữ liệu DC.
3 - Chế dộ ánh xạ (mapping mode):
Để duy trì sự độc lập thiết bò, GDI tạo ra output ở không gian luận lý và ánh xạ
nó lên màn hình. Chế độ ánh xạ cho biết mối quan hệ giữa không gian luận lý và
những pixel trên thiết bò.
Có tới 8 chế độ ánh xạ khác nhau nhưng chúng tôi chỉ quan tâm tới chế độ ánh
xạ MM_TEXT vì đây là chế độ ánh xạ mặc đònh. Trong chế độ này một đơn vò luận
lý được ánh xạ tới một pixel trên thiết bò hay màn hình. Như vậy đơn vò tính luận lý
là pixel và các tọa độ x, y cũng được tính theo pixel, trò x tăng khi qua phải và giảm
khi qua trái, trò y tăng khi đi xuống và giảm khi đi lên. Origin của hệ thống tọa độ là
góc trái-trên (upper-left) của màn hình.
4 - Hệ thống tọa độ windows:
Windows sử dụng các hệ thống tọa độ khác nhau tùy theo hoàn cảnh như:
Hệ toạ độ thiết bò (Device coordinate system)
- Hệ toạ độ toàn màn hình (Full screen coordinate system)
- Hệ toạ độ vùng client (Client area coordinate system)
- Hệ toạ độ toàn cửa sổ (Whole window coordinate system)
BÁO CÁO LUẬN VĂN TỐT NGHIỆP
Đề tài : “NHẬN DẠNG TỪ DƯỚI CURSOR MOUSE TRÊN DESKTOP WINDOWS”
11
Windows
Application
GDI
Device
Context
Device
Driver
Output
Device
Windows
Application
Windows
Application
Device
Driver
Device
Driver
Output
Device
Output
Device
KHOA CÔNG NGHỆ THÔNG TIN - TRƯỜNG ĐẠI HỌC KỸ THUẬT TP.HCM
- Hệ toạ độ logic (Logical coordinate system)
Trong phạm vi ứng dụng của đề tài chúng tôi chỉ quan tâm đến các hệ toạ độ :
a) Full screen coordinate system:
là hệ thống tọa độ thiết bò liên quan tới trọn màn hình. Tọa độ màn hình được
tính theo pixel và chọn tọa độ (0,0) làm góc upper-left của màn hình. Hệ thống này
sử dụng khi liên quan đến trọn màn hình trên tọa độ màn hình. Thường vò trí của một
đối tượng như con nháy hoặc con trỏ hoặc cửa sổ so với góc upper-left của màn hình
thì dùng hệ tọa độ này.
b) Client area coordinate system:
Cũng là hệ tọa độ thiết bò, nó khác với hệ tọa độ trọn màn hình ở origin của hệ
tọa độ. Tọa độ trọn màn hình là tương đối so với upper-left của màn hình còn tọa độ
vùng client là tương đối so với upper-left của vùng client. Tọa độ này cũng tính theo
device unit (pixel) giống như tọa độ màn hình.
Hàm ClientToScreen để chuyển tọa độ vùng client qua tọa độ trọn màn hình.
Hàm ScreenToClient chuyển tọa độ trọn màn hình qua tọa độ vùng client.
c) Whole window coordinate system:
Gần giống hệ tọa độ vùng client, là tương đối so với góc upper-left của cửa sổ,
được sử dụng khi vẽ vùng nonclient của cửa sổ.
d) Logical coordinate:
Hầu hết các hàm GDI sử dụng hệ tọa độ này. Hệ thống tọa độ logic không
phải là hệ thống tọa độ thiết bò, hệ thống tọa độ logic bao giờ cũng được ánh xạ lên
một hệ thống tọa độ thiết bò. Hệ tọa độ logic có thể được ánh xạ lên hệ tọa độ toàn
màn hình, hệ tọa độ vùng client hoặc hệ tọa độ toàn cửa sổ.
Dùng hàm DPtoLP để chuyển tọa độ thiết bò sang hệ tọa độ logic.
Dùng hàm LPtoDP để chuyển tọa độ logic sang hệ tọa độ thiết bò.
Như vậy điều quan trọng trong việc tính toán sử dụng hệ tọa độ là phải kiểm
soát được việc sử dụng các hệ tọa độ một cách đồng bộ bởi vì việc chuyển đổi giữa
các hệ tọa độ đã được cung cấp bởi các hàm nêu trên.
5 - Viewport và window:
Mapping mode cho biết ánh xạ tọa độ logic và những kích thước được cung cấp
khi gọi các hàm GDI qua hệ thống tọa độ thiết bò gắn liền với DC. Tức là mapping
mode quyết đònh GDI ánh xạ việc ánh xạ một window (tọa độ logic) qua một
viewport (tọa độ thiết bò). Viewport nghóa là một vùng hình chữ nhật của hệ thống
tọa độ thiết bò được đònh nghóa bởi một DC còn window khi sử dụng để qui chiếu
GDI mapping mode là một hình chữ nhật của hệ thống tọa độ logic được đònh nghóa
bởi một DC.
BÁO CÁO LUẬN VĂN TỐT NGHIỆP
Đề tài : “NHẬN DẠNG TỪ DƯỚI CURSOR MOUSE TRÊN DESKTOP WINDOWS”
12
KHOA CÔNG NGHỆ THÔNG TIN - TRƯỜNG ĐẠI HỌC KỸ THUẬT TP.HCM
Công thức để chuyển đổi một hệ tọa độ window (logic) qua một hệ tọa độ
viewport (thiết bò):
xviewport = (xwindow - xwindowOrg)(xviewportExt / xwindowExt) + xviewportOrg
yviewport = (ywindow - ywindowOrg)(yviewportExt / ywindowExt) + yviewportOrg
Trong đó:
(xwindow,ywindow) là điểm trên tọa độ logic được chuyển đổi thành điểm
(xviewport,yviewport)
(xwindowOrg,ywindowOrg) và (xviewportOrg,yviewportOrg) là origin của
vùng hình chữ nhật window và viewport theo mặc nhiên các điểm này được cho về
(0,0) trên DC mặc nhiên.
Công thức sử dụng 2 điểm cho biết extent của một vùng theo tọa độ logic
(xwindowExt,ywindowExt) và của một vùng theo hệ tọa độ thiết bò
(xviewportExt,yviewportExt).
Tỉ lệ của (viewpot extent / window extent) là hệ số scaling dùng để dòch đơn vò
logic qua đơn vò thiết bò.
Việc chuyển đổi ngược lại tương tự bằng các biến đổi công thức trên.
IV - CỬA SỔ TRONG WINDOWS:
Cửa sổ là khái niệm cơ bản trong giao diện GDI của Windows, nó là một kiến
trúc chuẩn mực để từ đó xây dựng nên các đối tượng khác như: cửa sổ chính của ứng
dụng (main frame); text box; edit control; button; combo box; menu; scroll bar; nói
chung là toàn bộ những công cụ tạo nên giao diện GDI đều có thể gọi là cửa sổ.
Cũng có thể xem cửa sổ như vùng chữ nhật màn hình mà nơi đó ứng dụng in ra các
kết xuất và nhận các dữ liệu từ người dùng.
Windows quản lý tất cả cửa sổ hiện có trong hệ thống bằng cách gán cho mỗi
cửa sổ một handle (trên thực tế nó là một số nguyên)ø, ta chỉ cần có được handle cửa
sổ thì có thể thao tác mọi thứ trên cửa sổ đó.
Một cửa sổ chia sẻ màn hình với các cửa sổ khác, kể cả các cửa sổ của ứng
dụng khác. Chỉ có một cửa sổ trong một thời điểm có thể nhận dữ liệu nhập từ người
dùng. Người dùng có thể dùng chuột, bàn phím, hay các thiết bò nhập khác để tương
tác với cửa sổ này và ứng dụng sở hữu nó.
1 - Các loại cửa sổ:
Windows cung cấp nhiều kiểu cửa sổ khác nhau để có thể kết hợp hình thành
nên các hình thức cửa sổ khác nhau. Các kiểu được sử dụng trong hàm
CreateWindow khi cửa sổ được tạo.
Một số kiểu cửa sổ sau:
- Cửa sổ chồng lên nhau (Overlapped windows hay top-level window): là cửa
sổ không bao giờ có cửa sổ cha mẹ.
BÁO CÁO LUẬN VĂN TỐT NGHIỆP
Đề tài : “NHẬN DẠNG TỪ DƯỚI CURSOR MOUSE TRÊN DESKTOP WINDOWS”
13
KHOA CÔNG NGHỆ THÔNG TIN - TRƯỜNG ĐẠI HỌC KỸ THUẬT TP.HCM
- Cửa sổ bò sở hữu (Owned windows): là kiểu đặc biệt, được sở hữu bởi một
cửa sổ bò chồng
- Cửa sổ pop-up: là kiểu đặc biệt của cửa sổ overlapped nhưng có thể có hoặc
không title bar.
- Cửa sổ con: là cửa sổ xác đònh vùng client của cửa sổ cha mẹ, được sử dụng
để chia vùng client của cửa sổ cha mẹ ra thành các vùng chức năng khác nhau. Một
ứng dụng dùng hàm ShowWindow để cho thấy hay che dấu một cửa sổ con. Mỗi cửa
sổ con phải có một cửa sổ cha mẹ. Cửa sổ cha mẹ nhường một phần trong vùng của
nó cho cửa sổ con và cửa sổ con sẽ nhận tất cả các tác động từ bên ngoài vào vùng
này. Một cửa sổ con có thể có nhiều cửa sổ con khác và mỗi cửa sổ con đều có cho
riêng nó một handle riêng để giao dòch khi gởi thông điệp cho cửa sổ cha mẹ. Mỗi
cửa sổ con là một cửa sổ độc lập, nó nhận tác động bên ngoài của riêng nó và các
thông điệp khác. Những input gởi cho cửa sổ con được đi trực tiếp tới cửa sổ con và
không chuyển qua cửa sổ cha mẹ ngoại trừ trường hợp cửa sổ con bò hàm
EnabledWindow cho disabled. Trong trường hợp này thì Windows chuyển bất kỳ
input nào tới cửa sổ con đó cho cửa sổ cha mẹ của nó. Điều này cho phép cửa sổ
cha mẹ kiểm tra được input và làm cho cửa sổ con ở trạng thái enabled nếu nó thấy
điều đó là cần thiết.
Những hoạt động của cửa sổ cha mẹ cũng ảnh hưởng đến cửa sổ con như sau:
- Shown: Cửa sổ cha mẹ sẽ được hiển thò trước cửa sổ con.
- Hidden: Cửa sổ cha mẹ sẽ bò che sau cửa sổ con. Cửa sổ con sẽ được nhìn
thấy (hết bò che) (visible) chỉ khi cửa sổ cha mẹ được nhìn thấy.
- Destroyed: Cửa sổ cha mẹ bò huỷ sau cửa sổ con.
- Moved: Cửa sổ con bò di chuyển cùng với vùng client của cửa sổ cha mẹ. Cửa
sổ con đáp ứng cho việc tô vẽ sau khi di chuyển.
- Gia tăng kích thước hay ở trạng thái kích thước cực đại: tô vẽ bất kỳ phần nào
của cửa sổ cha mẹ mà đã được phơi bày ra như là kết quả của kích thước tăng lên
của vùng client.
Windows không tự động xén (clip) một cửa sổ con ra khỏi vùng client của cửa
sổ cha mẹ. Điều này nghóa là cửa sổ cha mẹ vẽ lên trên cửa sổ con nếu nếu nó tiến
hành bất kỳ sự tô vẽ nào trong cùng vò trí với vò trí của cửa sổ con. Windows chỉ xén
cửa sổ con ra khỏi vùng client của cửa sổ cha mẹ nếu cửa sổ cha mẹ có kiểu
WS_CLIPCHILDREN. Nếu cửa sổ con bò xén thì cửa sổ cha mẹ không thể tô vẽ lên
nó. Một cửa sổ con có thể chồng lên các cửa sổ con khác trong cùng vùng client.
Cửa sổ anh em (cùng cha mẹ) có thể tô vẽ trong mỗi vùng client của các cửa sổ
khác trừ khi một cửa sổ con có kiểu WS_CLIPSIBLINGS. Nếu ứng dụng xác đònh
kiểu này cho một cửa sổ con thì bất kỳ phần nào của cửa sổ anh em của cửa sổ con
đó nằm trong cửa sổ này đều bò xén. Nếu một cửa sổ có kiểu WS_CLIPCHILDREN
hoặc WS_CLIPSIBLINGS thì một mất mát nhỏ trong sự thực hiện (performance)
xảy ra. Mỗi cửa sổ chiếm tài nguyên hệ thống bởi vậy ứng dụng sẽ không sử dụng
các cửa sổ con một cách bừa bãi. Để hoạt động tối ưu một ứng dụng cần chia luận lý
BÁO CÁO LUẬN VĂN TỐT NGHIỆP
Đề tài : “NHẬN DẠNG TỪ DƯỚI CURSOR MOUSE TRÊN DESKTOP WINDOWS”
14
KHOA CÔNG NGHỆ THÔNG TIN - TRƯỜNG ĐẠI HỌC KỸ THUẬT TP.HCM
cửa sổ chính của nó trong thủ tục cửa sổ của cửa sổ chính còn hơn là dùng các cửa sổ
con.
2 - Thủ tục cửa sổ (Window Procedures):
Một thủ tục cửa sổ xử lý tất cả những thông điệp được gởi tới tất cả các cửa sổ
trong lớp được đưa ra. Windows gởi các thông điệp tới thủ tục cửa sổ khi nó nhận
input từ user có ý đònh chuyển cho cửa sổ được đưa ra hay khi nó cần thủ tục để thực
hiện một vài hành động trên cửa sổ của nó như việc tô vẽ lại bên trong vùng client.
Thủ tục cửa sổ nhận các kiểu thông điệp như: nhập vào từ bàn phím, chuột;
yêu cầu tiêu đề cửa sổ; tường thuật sự thay đổi gây ra bởi cửa sổ khác (như thay đổi
file WIN.INI); cơ hội sửa đổi đáp ứng hệ thống tiêu chuẩn đến những hoạt động
chắc chắn (như điều chỉnh menu trước lúc hiển thò); yêu cầu thực hiện một vài hành
động trên cửa sổ hay vùng client của nó (cập nhật vùng client); thông tin về tình
trạng của nó trong mối quan hệ với các cửa sổ khác (truy xuấ nhất đònh thất bại của
nó tới bàn phím hay trở thành cửa sổ hoạt động).
Một thủ tục cửa sổ nhận hầu hết các thông điệp là từ Windows nhưng nó cũng
có thể nhận thông điệp từ các cửa sổ khác gồm cả những cửa sổ nó sở hữu. Những
thông điệp này có thể là những yêu cầu về thông tin hay thông báo mà một sư kiện
được đưa ra đã xảy ra trong một cửa sổ khác. Một thủ tục cửa sổ tiếp tục nhận thông
điệp fừ hệ thống và có thể chấp nhận những cửa sổ khác trong hệ thống cho đến khi
thủ tục cửa sổ, thủ tục cửa sổ của một cửa sổ cha mẹ hay hệ thống hủy cửa sổ. Ngay
cả khi cửa sổ ở trong quá trình đang bò hủy, thủ tục cửa sổ nhận những thông điệp
thêm vào đưa tới nó cơ hội để tiến hành bất kỳ nhiệm vụ làm sạch (cleanup) nào
trước lúc kết thúc. Những thông điệp này gồm WM_ , WM_DESTROY,
WM_QUERYENDSESSION và WM_ENDSESSION. Nhưng khi cửa sổ bò hủy thì
không có thêm thông điệp nào được đưa tới thủ tục cho cửa sổ cụ thể đó. Nếu có
nhiều hơn một cửa sổ của lớp, tuy nhiên, thủ tục cửa sổ tiếp tục nhận thông điệp cho
những cửa sổ khác cho đến khi cũng chính chúng bò hủy. Một thủ tục cửa sổ chỉ rõ
làm thế nào tất cả cửa sổ của một cửa sổ đưa ra thực sự có hành vi bằng cách đáp
ứng những gì các cửa sổ tạo ra những lệnh từ user hay hệ thống. Thủ tục cửa sổ phải
kiểm tra những thông điệp mà nó nhận từ hệ thống và quyết đònh bất kỳ hành động
gì sẽ diễn ra. Thủ tục cửa sổ cũng có thể chọn không đáp ứng một thông điệp được
đưa ra. Nếu không đáp ứng thủ tục phải chuyển thông điệp tới hàm DefWindowProc
để đưa cho hệ thống cơ hội để đáp ứng. Hàm này thực hiện hành động có sẵn trên cơ
sở thông điệp được đưa ra và những thông số của nó. Nhiều thông điệp (đặc biệt là
thông điệp vùng non-client) phải được xử lý vì thế DefWindowProc được yêu cầu
trong tất cả các thủ tục cửa sổ.
Thủ tục cửa sổ cũng nhận các thông điệp mà thực sự đã dự đònh được xử lý
bởi hệ thống. Nững thông điệp vùng-nonclient thông báo cho thủ tục biết user thực
hiện một vài hành động trong vùng client của cửa sổ hoặc một vài thông tin về cửa
sổ được yêu cầu bởi hệ thống để thực hiện một hành động. Mặc dù Windows chuyển
những thông điệp này tới thủ tục cửa sổ thì thủ tục sẽ chuyển chúng cho hàm
DefWindowProc và không cố gắng xử lý chúng. Ở trường hợp này thủ tục cửa sổ
phải phớt lờ thông điệp hay trả về không chuyển nó tới DefWindowProc.
BÁO CÁO LUẬN VĂN TỐT NGHIỆP
Đề tài : “NHẬN DẠNG TỪ DƯỚI CURSOR MOUSE TRÊN DESKTOP WINDOWS”
15
KHOA CÔNG NGHỆ THÔNG TIN - TRƯỜNG ĐẠI HỌC KỸ THUẬT TP.HCM
3) Thông điệp cửa sổ:
Một thông điệp cửa sổ là một tập những giá trò mà Windows gởi tới thủ tục cửa
sổ để cung cấp input cho cửa sổ hay yêu cầu cửa sổ thực hiện một vài hành động.
Windows tính đến một sự thay đổi rộng khắp những thông điệp mà nó hay ứng dụng
của nó có thể gởi tới thủ tục cửa sổ. Hầu hết những thông điệp được gởi tới cửa sổ
như là kết quả của hàm đưa ra đang được thực thi hay như là kết quả của input từ
user. Mỗi thông điệp gồm 4 giá trò: một handle xác đònh cửa sổ, một danh hiệu thông
điệp, một giá trò thông điệp-đặc biệt 16-bit và một giá trò thông điệp-đặc biệt 32-bit.
Những giá trò này được chuyển tới thủ tục cửa sổ như là những thông số riêng lẻ. Rồi
thủ tục cửa sổ kiểm tra danh hiệu thông điệp để quyết đònh những đáp ứng gì phải
làm và làm thế nào để thông dòch giá trò 16-bit và 32-bit.
Cú pháp thủ tục cửa sổ:
- LONG FAR PASCAL WndProc(hwnd, wMsg, wParam, lParam)
HWND hwnd;
WORD wMsg;
WORD wParam;
DWORD lParam;
Các thông số:
hwnd cho biết cửa sổ nhận thông điệp
wMsg loại thông điệp
wParam thông tin thông điệp-đặc biệt thêm vào 16-bit
lParam thông tin thông điệp-đặc biệt thêm vào 32-bit
Hàm trả về giá trò 32-bit cho biết kết quả xử lý thông điệp
4 - Default window procedure:
Hàm DefWindowProc là phần xử lý thông điệp có sẵn cho những thủ tục cửa
sổ không hay không thể truy xuất một vài thông điệp được gởi tới cho chúng. Hầu
hết các thủ tục cửa sổ thì hàm DefWindowProc thực hiện hầu hết, nếu không muốn
nói là tất cả, việc xử lý thông điệp vùng client. Đây là các thông điệp biểu hiện
những hành động được thực hiện trên các phần khác của cửa sổ hơn là vùng client.
5 - Vấn đề tô vẽ màn hình:
Khi một cửa sổ bò di chuyển thì Windows tự động sao chép nội dung của vùng
client tới vò trí mới. Điều này tiết kiệm thời gian bởi vì một cửa sổ không phải tính
toán lại và vẽ lại nội dung của vùng client như là phần của sự di chuyển. Nếu cửa sổ
di chuyển hay thay đổi kích thước thì Windows chỉ sao chép phần lớn vùng client
trước đó khi nó cần điền vò trí mới. Nếu cửa sổ sổ gia tăng kích thước thì Windows
sao chép toàn bộ vùng client và gởi thông báo WM_PAINT tới cửa sổ để điền vào
trong vùng được phơi bày mới hơn. Khi cửa sổ bò di chuyển thì Windows cho rằng
nội dung của vùng client vẫn hợp lệ và có thể được sao chép không cần thay dổi tới
vò trí mới. Tuy nhiên với một vài cửa sổ thì nội dung của vùng client không còn hợp
lệ sau khi di chuyển đặc biệt là nếu di chuyển luôn sự thay đổi kích thước. Để tô vẽ
BÁO CÁO LUẬN VĂN TỐT NGHIỆP
Đề tài : “NHẬN DẠNG TỪ DƯỚI CURSOR MOUSE TRÊN DESKTOP WINDOWS”
16
KHOA CÔNG NGHỆ THÔNG TIN - TRƯỜNG ĐẠI HỌC KỸ THUẬT TP.HCM
lại toàn bộ vùng client thay cho sao chép nội dung trước đó mỗi lần một cửa sổ thay
đổi kích thước thì một cửa sổ sẽ xác đònh kiểu CS_VREDRAW và trong lớp cửa sổ.
Để quản lý hiển thò màn hình, Windows tiến hành nhiều hoạt động ảnh hưởng
tới nội dung của vùng client. Nếu Windows di chuyển, đònh kích thước hay thay đổi
bề mặt màn hình, sự thay đổi có thể ảnh hưởng cửa sổ được đưa ra. Nếu vậy,
Windows đánh dấu vùng bò thay đổi bằng hoạt động sẵn sàng cho việc cập nhật và ở
cơ hội tiếp theo nó gởi thông điệp WM_PAINT tới cửa sổ vì thế nó có thể cập nhật
cửa sổ trong vùng cần cập nhật. Nếu một cửa sổ vẽ trong vùng client của nó thì nó
phải gọi BeginPaint để lấy handle của ngữ cảnh màn hình, phải cập nhật vùng bò
thay đổi như đã đònh nghóa bởi vùng cập nhật và cuối cùng nó phải gọi EndPaint để
hoàn tất công việc. Một cửa sổ có thể vẽ trong vùng client của nó bất kỳ lúc nào tức
là ngoài thời điểm mà nó đáp ứng thông điệp WM_PAINT chỉ cần nó lấy ngữ cảnh
màn hình cho vùng client trước lúc nó tiến hành vẽ.
Thông điệp WM_PAINT: là một yêu cầu của Windows tới một cửa sổ để cập
nhật màn hình cửa nó. Windows gởi WM_PAINT bất cứ khi nào cần vẽ một phần lại
cửa sổ. Khi cửa sổ nhận thông điệp WM_PAINT thì nó sẽ lấy vùng cập nhật bằng
hàm BeginPaint và nó sẽ tiến hành bất kỳ hoạt động gì cần thiết để cập nhật phần
đó của vùng client.
InvalidateRect và InvalidateRgn thực sự không sinh ra thông điệp
WM_PAINT. Windows tích luỹ những thay đổi được tạo ra bởi các hàm này và
những thay đổi của riêng nó trong trong lúc một cửa sổ xử lý những thông điệp khác
trong hàng thông điệp của nó. Làm trễ WM_PAINT làm cho cửa sổ xử lý tất cả
những thay đổi cùng một lúc thay vì cập nhật những những mẫu nhỏ trong những
bước riêng lẻ làm lãng phí thời gian.
Để chỉ thò Windows gởi thông điệp WM_PAINT một ứng dụng có thể sử dụng
UpdateWindow, hàm này gởi thông điệp trực tiếp tới cửa sổ, bất chấp những thông
điệp khác trong hàng thông điệp của ứng dụng. UpdateWindow được sử dụng khi
một cửa sổ cần cập nhật vùng client của nó ngay lập tức (chẳng hạn chỉ ngay sau
cửa sổ được tạo). Khi một cửa sổ nhận WM_PAINT nó phải gọi BeginPaint để lấy
ngữ cảnh màn hình cho vùng client và lấy thông tin khác như vùng cập nhật và
background bò xóa hay không. Windows tự động chọn vùng cập nhật như là vùng
xén của ngữ cảnh màn hình. GDI huỷ bỏ (xén) những gì được vẽ bên ngoài vùng
xén chỉ những gì ở bên trong vùng cập nhật là thực sự nhìn thấy được. BeginPaint
xóa vùng cập nhật để ngăn chặn vùng giống nhau từ việc sinh ra các thông điệp
WM_PAINT đến sau. Sau khi vẽ xong Windows phải gọi hàm EndPaint để giải
phóng DC.
Vùng cập nhật: Một vùng cập nhật xác đònh phần của vùng client được đánh
dấu cho việc vẽ cho thông điệp WM_PAINT kế tiếp. Mục đích của vùng cập nhật là
để lưu các ứng dụng thời điểm nó đưa ra để vẽ toàn bộ nội dung của vùng client.
Nếu chỉ có phần mà cần vẽ được cộng vào vùng cập nhật thì chỉ có phần đó được
vẽ.
Hàm InvalidateRect và InvalidateRgn cộng một hình chữ nhật hay một vùng
vào vùng cập nhật. Hình chữ nhật hay vùng phải được đưa ra ở trong tọa độ client.
BÁO CÁO LUẬN VĂN TỐT NGHIỆP
Đề tài : “NHẬN DẠNG TỪ DƯỚI CURSOR MOUSE TRÊN DESKTOP WINDOWS”
17
KHOA CÔNG NGHỆ THÔNG TIN - TRƯỜNG ĐẠI HỌC KỸ THUẬT TP.HCM
Vùng cập nhật bản thân nó được đònh nghóa trong tọa độ client. Windows cộng
những vùng và hình chữ nhật của chính nó vào một vùng cập nhật của cửa sổ sau khi
những hoạt động như di chuyển, đònh kích thước và cuộn cửa sổ.
Hàm ValidateRect và ValidateRgn xóa một hình chữ nhật hay một vùng ra
khỏi vùng cập nhật. Những hàm này được sử dụng điển hình khi cửa sổ đã cập nhật
một phần đặc biệt của màn hình trong vùng cập nhật trước khi nhận thông điệp
WM_PAINT.
Hàm GetUpdateRect lấy hình chữ nhật nhỏ nhất bao lấy toàn bộ vùng cập
nhật. Hàm GetUpdateRgn lấy vùng cập nhật chính nó. Những hàm này có thể được
sử dụng để tính toán kích thước hiện hành của vùng cập nhật để quyết đònh những
công việc vẽ nào được yêu cầu.
V – CHƯƠNG TRÌNH WINDOWS TIẾP NHẬN THÔNG ĐIỆP CHUỘT:
Giới thiệu dòng chảy dữ liệu thông điệp nhập từ con chuột:
1 - Mouse:
Khi mouse báo vò trí của mình (vò trí cursor) và có tác động lên mouse thì một
tín hiệu được phát đi từ mouse gây ra một ngắt quãng, mouse driver giải quyết ngắt
quãng này.
2 - Mouse device driver:
Khi Windows khởi động thì mouse driver tự động nạp vào và kiểm tra xem có
chuột hay không. Nếu có thì Windows gọi driver cung cấp một thủ tục để báo cáo
các biến cố xảy ra trên chuột. Khi có một mouse event thì driver thông báo cho
Windows biết. Nếu event là di chuyển mouse thì ưu tiên đáp ứng vò trí con trỏ di
BÁO CÁO LUẬN VĂN TỐT NGHIỆP
Đề tài : “NHẬN DẠNG TỪ DƯỚI CURSOR MOUSE TRÊN DESKTOP WINDOWS”
18
Hardware event
queue
Device driverMouse
GetMessage()
DispatchMessage()
WindowProc()
DefWindowProc()
Hook
chain
Virtual &
Scan code
KHOA CÔNG NGHỆ THÔNG TIN - TRƯỜNG ĐẠI HỌC KỸ THUẬT TP.HCM
chuyển ngay lúc ngắt. Còn lại tất cả các event khác đều được đưa vào hardware
event queue.
3 - Hardware event queue:
Các mouse event được đưa vào hardware event queue chờ giao cho message
loop của chương trình giải quyết. Queu này là một vùng đệm có thể chứa tối đa 120
event. Những event trong queue chưa thuộc một chương trình cụ thể nào cho tới khi
nó được tiếp nhận bởi hàm GetMessage(). Điều này đảm bảo cho hệ thống hoạt
động đúng đắn. Sau đó là vòng lặp GetMessage().
4 - GetMessage() loop:
GetMessage() loop đưa các thông điệp vào xử lý. GetMessage() sẽ quyết đònh
chương trình nào sẽ tiếp nhận thông điệp bằng cách xem chương trình nào sở hữu
cửa sổ mà con trỏ chuột nằm trên đó. Tùy theo vò trí của con trỏ mà phát sinh hai
loại thông điệp: thông điệp vùng client và thông điệp vùng non-client. Muốn biết
cursor ở vùng nào thì GetMessage() chuyển đi một thông điệp WM_NCHITTEST
cho thủ tục cửa sổ. Hàm GetMessage() dựa vào cơ chế pull-model để đọc thông tin
tình huống trong queu và lại dựa vào push-model để biết vò trí của cursor. Tức là
GetMessage() sẽ gọi thủ tục cửa sổ như là một chương trình thường trú vậy.
GetMessage() sử dụng hàm SendMessage() để gọi thủ tục cửa sổ. Trò trả về nằm
trong phạm vi của thông điệp WM_NCHITTEST mà GetMessage() gởi cho thủ tục
cửa sổ của ta. WM_NCHITTEST là thông điệp đến đầu tiên trong hàng loạt thông
điệp mà mouse phát ra. Nó yêu cầu thủ tục cửa sổ nhận diện vò trí cursor. Đa số
chương trình chuyển thông điệp này cho DefWindowProc() lo tìm vò trí cursor và
cung cấp một hit-test code như là trò trả về.
Khi DefWindowProc() trả về kết quả khác HTCLIENT, HTERROR,
HTNOWHERE, HTTRANSPARENT thì cursor nằm trên vùng non-client thì
Windows sẽ phát đi thông điệp non-client.
Còn khi DefWindows trả về kết quả HTCLIENT thì cursor nằm trên vùng
client và những thông điệp do Windows phát đi lúc này thì sẽ được trình ứng dụng
xử lý.
Hàm SendMessage() sẽ sử dụng mã hit-test code để quyết đònh xem loại thông
điệp chuột nào mà cho phát sinh. Khi hi-test code bằng HTCLIENT thì một thông
điệp vùng client sẽ được phát sinh còn tất cả các hit-test code khác sẽ phát sinh ra
những thông điệp chuột vùng non-client.
Trước khi SendMessage() trả về một thông điệp chuột cho chương trình của ta
thì có một việc mà hàm này phải thi hành: nó phải bảo đảm là hình dáng cursor phù
hợp vò trí hiện thời của mouse. Muốn thế nó phải gởi đi một thông điệp khác cho thủ
tục cửa sổ WM_GETCURSOR. Tương tự như thông điệp WM_NCHITTEST đa số
chương trình phớt lờ thông điệp này và giao cho DefWindowProc() thực hiện. Mã
hit-test code được cho ở trong byte thấp của thông số lParam để cho
DefWindowProc() biết mà thiết đặt hình dáng của con trỏ.
BÁO CÁO LUẬN VĂN TỐT NGHIỆP
Đề tài : “NHẬN DẠNG TỪ DƯỚI CURSOR MOUSE TRÊN DESKTOP WINDOWS”
19
KHOA CÔNG NGHỆ THÔNG TIN - TRƯỜNG ĐẠI HỌC KỸ THUẬT TP.HCM
Hai thông điệp WM_NCHITTEST và WM_SETCURSOR bao giờ cũng đi
trước một thông điệp chuột. Vì Windows phải tìm ra xem vò trí cursor hiện ở trong
vùng client hay vùng non-client để phát ra thông điệp vùng client hay thông điệp
vùng non-client một cách thích hợp. Một khi đã được nhận diện thì Windows phải
đảm bảo là người sử dụng nhận được hình dáng cursor thích hợp.
Windows cho phép đặt message hook để thay đổi dòng chảy các thông điệp.
Một WH_GETMESSAGE hook có thể thay đổi dòng chảy của bất cứ thông điệp
chuột của vùng client hoặc vùng non-client. Khi GetMessage() sẵn sàng đem một
thông điệp vào chương trình của ta thì nó sẽ gọi hook xem có thay đổi gì không trước
khi thông điệp được chuyển cho chương trình.
Khi GetMessage() đã đưa thông điệp vào chương trình rồi thì thông điệp sẽ
được trao trực tiếp cho thủ tục cửa sổ thích hợp bởi hàm DispatchMessage(). Bây giờ
thông điệp đã nằm trong thủ tục cửa sổ.
5 - Thủ tục cửa sổ:
Hơn 20 thông điệp của Windows về chuột (trừ WM_NCHITTEST) thì có 10
thông điệp thuộc vùng non-client do DefWindowProc() giải quyết. Hai thông số
wParam, lParam của thủ tục cửa sổ sẽ cho biết thông tin về thông điệp. Trò của hai
thông số lParam và wParam đều tương tự nhau cho các thông điệp chuột trên vùng
client.
Trò của thông số lParam chứa vò trí cursor theo tọa độ của vùng client. Tọa độ
này cho origin về góc upper-left của vùng client với đơn vò tính là pixel. Trò x nằm ở
word thấp còn y nằm ở word cao của lParam.
Trò của wParam là một lô cờ hiệu mô tả trạng thái của các nút chuột cũng như
trạng thái các nút <Ctrl>, <Shift>
6 – DefWindowProc():
Đối với chuột thì DefWindowProc() không quan tâm đến những thông điệp
thuộc vùng client mà chỉ quan tâm đến những thông điệp thuộc vùng non-client.
DefWindowProc() có nhiệm vụ cung cấp một giao diện chung cho bàn phím và
con chuột bằng cách dòch phần nhập liệu từ bàn phím hoặc con chuột thành các lệnh
hệ thống (system command) và cho hiện lên như các thông điệp
WM_SYSCOMMAND. Cuối cùng DefWindowProc() giải quyết các thông điệp
WM_NCHITTEST và WM_SETCURSOR cung cấp trước cho các thông điệp chuột
khác.
BÁO CÁO LUẬN VĂN TỐT NGHIỆP
Đề tài : “NHẬN DẠNG TỪ DƯỚI CURSOR MOUSE TRÊN DESKTOP WINDOWS”
20
KHOA CÔNG NGHỆ THÔNG TIN - TRƯỜNG ĐẠI HỌC KỸ THUẬT TP.HCM
Chương 2:
TÌM HIỂU VỀ HOOKS
TÌM HIỂU VỀ HOOKS
BÁO CÁO LUẬN VĂN TỐT NGHIỆP
Đề tài : “NHẬN DẠNG TỪ DƯỚI CURSOR MOUSE TRÊN DESKTOP WINDOWS”
21
KHOA CÔNG NGHỆ THÔNG TIN - TRƯỜNG ĐẠI HỌC KỸ THUẬT TP.HCM
Hook là một cơ chế cực mạnh cho phép ta cài đặt một thủ tục để điều khiển
hoặc chận hứng các thông điệp trước khi các thông điệp này tới được nơi tiếp nhận.
Hay nói một cách khác hook là một điểm trong kỹ thuật message-handling hệ
thống, nơi mà một ứng dụng có thể đặt một thủ tục để quản lý sự lưu thông của các
thông điệp trong hệ thống và xử lý một kiểu thông báo nào đó trước khi chúng tới
được thủ tục cửa sổ đích.
Do có khả năng can thiệp mạnh nên hook có xu hướng làm chậm lại hệ thống
vì chúng làm tăng số lượng các hoạt động của hệ thống đối với mỗi thông điệp. Chỉ
đặt hook khi thực sự cần thiết và dỡ bỏ chúng khi không cần đến.
1 - Chuỗi hook:
Hệ thống cho phép nhiều kiểu hook khác nhau: mỗi kiểu cung cấp việc truy
xuất tới một khía cạnh khác nhau của kỹ thuật message-handling. Chẳng hạn, một
ứng dụng có thể sử dụng hook WM_MOUSE để quản lý những thông điệp chuột
trong luồng thông điệp.
Hệ thống duy trì một chuỗi hook riêng lẻ đối với mỗi kiểu hook. Một chuỗi
hook là một danh sách các pointer chỉ tới các hàm callback application-defined đặc
biệt mà những hàm này gọi các thủ tục hook. Khi một thông điệp xảy ra là nó đã
được tổ chức với một kiểu hook cụ thể, hệ thống chuyển thông điệp tới mỗi thủ tục
hook có mặt trong chuỗi hook, theo trật tự cái nọ sau cái kia. Hoạt động của một thủ
tục hook có thể phụ thuộc vào kiểu hook mà nó liên quan. Các thủ tục hook cho một
vài kiểu hook có thể chỉ quản lý những thông điệp; những cái khác có thể thay đổi
những thông điệp hay dừng sự phát triển của nó trong chuỗi, ngăn chặn chúng tìm
tới thủ tục hook kế tiếp hay cửa sổ cuối cùng (đích).
2 – Thủ tục hook:
Để có được sự tiện lợi của một loại hook chi tiết, người lập trình cung cấp một
thủ tục hook và sử dụng hàm SetWindowsHookEx để đặt nó vào trong chuỗi hook.
Một thủ tục hook có cú pháp:
- LRESULT CALLBACK HookProc (
Int nCode,
WPARAM wParam,
LPARAM lParam
);
HookProc là một placeholder cho một ứng dụng đã được đònh nghóa trước.
Thông số nCode là một mã hook phụ thuộc vào kiểu hook; mỗi kiểu có một tập
các đặc tính các mã hook. Những giá trò của thông số wParam và lParam phụ thuộc
vào mã hook, nhưng điển hình thì chúng chứa thông tin về một thông điệp được send
hay được post. Hàm SetWindowsHookEx luôn luôn đặt một thủ tục hook ở đầu một
chuỗi hook. Khi một sự kiện xảy ra mà sự kiện này được quản lý bởi một kiểu hook
cụ thể thì hệ thống gọi thủ tục ở đầu chuỗi hook đã được tổ chức. Mỗi thủ tục hook
BÁO CÁO LUẬN VĂN TỐT NGHIỆP
Đề tài : “NHẬN DẠNG TỪ DƯỚI CURSOR MOUSE TRÊN DESKTOP WINDOWS”
22
KHOA CÔNG NGHỆ THÔNG TIN - TRƯỜNG ĐẠI HỌC KỸ THUẬT TP.HCM
trong chuỗi quyết đònh nên chuyển hay không chuyển sự kiện tới thủ tục tiếp theo.
Một thủ tục hook chuyển một sự kiện tới thủ tục tiếp theo bằng cách gọi hàm
CallNextHookEx. Chú ý rằng những thủ tục hook dành cho các kiểu hook chỉ có thể
quản lý các thông điệp, hệ thống chuyển thông điệp tới mỗi thủ tục hook, chứ không
dính dáng gì đến có hay không một thủ tục cụ thể gọi CallNextHookEx. Một thủ tục
hook có thể toàn cục, quản lý những thông điệp đối với tất cả các thread trong hệ
thống hay nó có thể là thread cụ thể, quản lý các thông điệp cho chỉ một thread
riêng biệt. Một thủ tục hook toàn cục có thể được gọi trong ngữ cảnh của bất kỳ ứng
dụng nào, bởi thế thủ tục phải ở trong một module DLL riêng lẻ. Một thủ tục hook
loại thread cụ thể chỉ được gọi trong ngữ cảnh của thread đã được tổ chức. Nếu một
ứng dụng đặt một thủ tục hook cho một trong các thread của riêng nó thì thủ tục
hook có thể ở trong cả module giống nhau như quãng nghó giữa các mã ứng dụng
hoặc trong một DLL. Nếu ứng dụng đặt một thủ tục hook cho một thread của một
ứng dụng khác thì thủ tục phải ở trong một DLL. Chú ý chỉ sử dụng hook toàn cục
cho mục đích debug còn không thì nên tránh không sử dụng. Hook toàn cục có thể
gây tổn hại cho hoạt động của hệ thống và gây nên xung đột với những ứng dụng
khác có cùng kiểu hook toàn cục.
3 – Các loại hook:
Một loại hook làm cho một ứng dụng có thể quản lý một mặt khác nhau của kỹ
thuật message-handling hệ thống.
Bao gồm các loại hook sau đây:
- WH_CALLWNDPROC hook quản lý các thông điệp trước lúc hệ thống gởi
chúng tới cửa sổ đích.
- WH_CALLWNDPROCRET hook quản lý các thông điệp sau khi chúng được
xử lý bởi thủ tục cửa sổ đích.
- WH_CBT hook nhận những thông báo có ích tới ứng dụng huấn luyện trên
cơ sở tính toán (CBT).
- WH_DEBUG hook có ích cho việc debug những thủ tục hook khác.
- WH_FOREGROUNDIDLE hook sẽ được gọi khi thread foreground của ứng
dụng sẽ trở thành không dùng đến. Hook này có ích cho hoạt động những
nhiệm vụ (task) độ ưu tiên thấp trong thời gian không được dùng đến.
- WH_GETMESSAGE hook quản lý các thông điệp được post tới hàng thông
điệp.
- WH_JOURNALPLAYBACK hook post những thông điệp được ghi trước đó
bởi thủ tục hook WH_JOURNALRECORD.
- WH_JOURNALRECORD hook ghi những thông điệp đầu vào được post tới
hàng thông điệp hệ thống. Hook này có ích cho việc ghi các macro.
- WH_KEYBOARD hook quản lý các thông điệp keystroke.
BÁO CÁO LUẬN VĂN TỐT NGHIỆP
Đề tài : “NHẬN DẠNG TỪ DƯỚI CURSOR MOUSE TRÊN DESKTOP WINDOWS”
23