Tải bản đầy đủ (.pdf) (77 trang)

Bài Giảng Lập Trình Windows

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (726.22 KB, 77 trang )

<span class='text_page_counter'>(1)</span><div class='page_container' data-page=1>

BỘ GIAO THÔNG VẬN TẢI


<b> TRƯỜNG ĐẠI HỌC HÀNG HẢI </b>


<b> N H HỌC Y T NH </b>


<b> H C NG NGHỆ TH NG TIN </b>



<b> ÀI GIẢNG </b>



<b>LẬP TRÌNH WIND WS </b>



<b>TÊN HỌC PHẦN : Lập trình Windows </b>


<b>MÃ HỌC PHẦN : 17214 </b>



<b>TRÌNH ĐỘ ĐÀO TẠO : ĐẠI HỌC CH NH QUY </b>



<b> DÙNG CHO SV NGÀNH : C NG NGHỆ TH NG TIN</b>



<b> </b>



<b> </b>


</div>
<span class='text_page_counter'>(2)</span><div class='page_container' data-page=2>

i


<b>Tên học phần Lập trình Windows </b> <b>Loại học phần 2 </b>
<b> ộ môn phụ trách giảng ạy Khoa học Máy tính </b>


<b> hoa phụ trách CNTT </b>


<b> ã học phần 17214 </b> <b>Tổng số TC: 3 </b>


TS tiết Lý thuyết Thực hành/Xemina Tự học Bài tập lớn Đồ án môn học
60 30 30 0 0 0



<b>Điều kiện tiên quyết </b>


Sinh viên phải học xong các học phần sau mới được đăng ký học phần này:
Lập trình hướng đ i tượng, C u tr c d li u


<b> ục tiêu của học phần </b>


- Cung c p các kiến th c c ản về lập trình trực quan trên h điều hành Windows
- Cung c p các kiến th c về truy cập và can thi p vào các thành phần c a h điều
hành Windows


<b>Nội ung chủ yếu </b>


Các kiến th c về thao tác với file và thư m c, c sở d li u registry, các luồng, tiến
trình, d ch v , các thư vi n liên kết đ ng và lập trình sockets trên Windows


<b>Nội ung chi tiết của học phần </b>


<b>TÊN CHƯƠNG ỤC </b>


<b>PHÂN PHỐI SỐ TIẾT </b>


<b>TS </b> <b>LT </b> <b>TH/Xemina </b> <b>BT </b> <b>KT </b>
<b>Ch ng I Các khái niệm c ản </b> <b>3 </b> <b>0 </b> <b>0 </b> <b>0 </b>


1 1 Giới thi u về môi trường lập trình trên
Windows


1 1 1 Cở sở về h điều hành Windows



1 1 2 Các phiên ản c a h điều hành
Windows


1 1 3 Vai tr c a Windows trên th trường
phần mềm


1 2 Thư vi n Win32 và Win64
1.2.1. Win32 API


1.2.2. Win64 API


1 3 Giới thi u về công c Visual Studio
2005


1


1


1


<b>Ch ng II Hệ thống i và th mục </b> <b>4 </b> <b>4 </b> <b>0 </b>


2 1 Truy cập và s d ng h th ng file trên môi
trường Windows


2 1 1 H th ng file và thư m c c a Windows
2 1 2 Các thao tác với file và thư m c trên
Windows



2 1 3 Các v n đề liên quan tới Unicode
2 2 Các ví d về thao tác với file
2 2 1 T o file và x lý các l i liên quan


2


1
2


</div>
<span class='text_page_counter'>(3)</span><div class='page_container' data-page=3>

ii


<b>TÊN CHƯƠNG ỤC </b>


<b>PHÂN PHỐI SỐ TIẾT </b>


<b>TS </b> <b>LT </b> <b>TH/Xemina </b> <b>BT </b> <b>KT </b>


2.2.2. Copy file


2 2 3 Hi n th danh sách các file trong thư m c
hi n thời


2 3 Quản lý file và thư m c n ng cao
2 3 1 Con tr file


2 3 2 Truy cập tới các thu c tính c a file và
thư m c


1 1



<b>Ch ng III Hệ thống c s iệu R gistry </b> <b>4 </b> <b>6 </b> <b>0 </b> <b>1 </b>


3 1 Khái ni m và vai tr c a CSDL Registry
3 1 1 Các kh a, các hive


3 1 2 Các ki u d li u
3 2 Quản lý CSDL Registry
3 2 1 Thay đ i kh a


3 2 2 Thêm mới kh a
3 2 3 Li t kê các kh a


3 3 Can thi p Windows qua Registry
3 3 1 Thay đ i giao di n


3 3 2 Thay đ i các thiết lập đ i với các đ a
3 3 3 Thay đ i các thiết lập với người d ng


1
1
2
1
2
3
1


<b>Ch ng IV Quản các tiến trình và u ng </b> <b>4 </b> <b>6 </b> <b>0 </b> <b>1 </b>


4 1 Các tiến trình và luồng trên Windows
4 2 Các thao tác với tiến trình



4 2 1 T o tiến trình


4 2 2 Kết th c và thoát kh i m t tiến trình
4 2 3 Các thao tác với iến môi trường c a
Windows


4 2 4 Ví d : Ghi nhật ký thời gian thực hi n
c a các tiến trình


4 3 Quản lý luồng thread trên Windows
4 3 1 Các khái ni m c ản


4 3 2 Mơ hình Boss/Worker và các mơ hình
khác


4 3 3 B nhớ dành cho luồng


4 3 4 Đ ưu tiên và các tr ng thái c a luồng
4 4 M t s ví d về tiến trình và luồng
4 4 1 Tìm kiếm song song với các tiến trình
4 4 2 Thuật toán s p xếp tr n ng đa luồng


2
1
1
2
2
2
1



<b>Ch ng V Các ch vụ của Win ows </b> <b>4 </b> <b>6 </b> <b>0 </b> <b>1 </b>


5 1 T ng quan về d ch v trên Windows
5 2 Các thành phần c a m t d ch v
5 2 1 Hàm main


5 2 2 Hàm ServiceMain


5 2 3 Ki m soát d ch v qua các Handler
5 3 Ví du: d ch v đ n giản trên Windows


1


1
2


</div>
<span class='text_page_counter'>(4)</span><div class='page_container' data-page=4>

iii


<b>TÊN CHƯƠNG ỤC </b>


<b>PHÂN PHỐI SỐ TIẾT </b>


<b>TS </b> <b>LT </b> <b>TH/Xemina </b> <b>BT </b> <b>KT </b>


5 4 Quản lý các d ch v c a Windows


5 4 1 Các phư ng pháp ki m soát các d ch v
c a Windows



5 4 2 Ví d : Điều khi n các d ch v c a
Windows


2 2


1


<b>Ch ng VI Lập trình mạng v i Sock ts </b> <b>4 </b> <b>4 </b> <b>0 </b> <b>0 </b>


6 1 Khái ni m sockets trên Windows
6 2 Các hàm sockets phía server
6 3 Các hàm sockets phía client
6 4 ng d ng m ng đ n giản
6 4 1 Phía server


6 4 2 Phía client


6.5. Windows Sockets 2.0


0,5
0,5
0,5
2
0,5
1
0,5
0,5
2


<b>Ch ng VII Th viện iên kết ộng </b> <b>4 </b> <b>4 </b> <b>0 </b> <b>0 </b>



7 1 Khái ni m và ng d ng c a thư vi n liên
kết đ ng


7 2 H th ng thư vi n DLL c a Windows
7 3 Các ước t o m t thư vi n DLL
7 3 1 T o thư vi n DLL


7 3 2 Viết ng d ng gọi tới thư vi n DLL


1
1
2
0,5
1
2,5


<b>Nhiệm vụ của sinh viên </b>


Tham dự các u i thuyết trình c a giáo viên, tự học, tự làm ài tập do giáo viên giao,
tham dự các ài ki m tra đ nh kỳ và cu i kỳ


<b>Tài iệu học tập : </b>


<i>- Lê H u Đ t NXB Giáo d c </i>


<i>- Charles Petzold. Programming Windows, fifth edition. Microsoft Press. 1998. </i>


<i>- Johnson M. Hart. Windows System Programming Third Edition. Addison Wesley </i>
Professional. 2004.



<b>Hình thức và tiêu chuẩn ánh giá sinh viên </b>


- Hình th c thi cu i kỳ : Thi v n đáp


- Sinh viên phải đảm ảo các điều ki n theo Quy chế c a Nhà trường và c a B


</div>
<span class='text_page_counter'>(5)</span><div class='page_container' data-page=5>

i


<b> ỤC LỤC </b>


LỜI NÓI ĐẦU ... 1


CH NG 1: C C KH I NI M C BẢN ... 2


1 Giới thi u về môi trường lập trình Windows ... 2


1 1 C sở về h điều hành Windows ... 2


1 2 Các phiên ản c a h điều hành Windows ... 2


1 3 Vai tr c a Windows trên th trường phần mềm ... 3


2 Thư vi n Win32 và Win64 ... 3


2.1 Win32 API ... 3


2.2 Win64 API ... 4


3 Các ước phát tri n ng d ng trên Windows ... 4



3 1 Chư ng trình Win32 đ n giản nh t ... 4


3 2 Chư ng trình c a s đ n giản ... 5


3 3 Quản lý các thông đi p ... 14


3 4 V ng l p x lý thông đi p ... 17


Bài tập: ... 20


CH NG 2: H TH NG FILE VÀ TH M C ... 21


1 Truy cập và s d ng h th ng file trên mơi trường Windows ... 21


<b>2 Các ví d về thao tác với file ... Error! Bookmark not defined. </b>
<b>2.1 Serialization ... Error! Bookmark not defined. </b>
<b>2 2 Cài đ t m t lớp Serializa le ... Error! Bookmark not defined. </b>
3 Quản lý file và thư m c n ng cao ... 21


Bài tập: ... 21


CH NG 3: H TH NG CSDL REGISTRY ... 22


1 Khái ni m và vai tr c a CSDL Registry ... 22


1 1 Các kh a, các hive ... 22


1 2 Các ki u d li u ... 23



2 Quản lý CSDL Registry ... 24


2 1 Thay đ i kh a ... 24


2 2 Thêm mới kh a ... 24


2 3 Li t kê các kh a ... 25


3 Can thi p Windows qua Registry ... 25


3 1 Thay đ i giao di n ... 25


</div>
<span class='text_page_counter'>(6)</span><div class='page_container' data-page=6>

ii


3 3 Thay đ i các thiết lập với người d ng ... 25


Bài tập: ... 25


CH NG 4: QUẢN L C C TI N TRÌNH VÀ LU NG... 26


1 Các tiến trình và luồng trên Windows ... 26


2 Các thao tác với tiến trình ... 27


2 1 T o tiến trình ... 27


2 2 Kết th c và thoát kh i m t tiến trình ... 28


2 3 Các thao tác với iến môi trường c a Windows ... 28



2 4 Ví d : Ghi nhật ký thời gian thực hi n c a các tiến trình ... 28


3 Quản lý luồng thread trên Windows ... 30


3 1 Các khái ni m c ản ... 30


3 2 Mơ hình Boss/Worker và các mơ hình khác ... 30


3 3 B nhớ dành cho luồng ... 30


3 4 Đ ưu tiên và các tr ng thái c a luồng ... 31


4 M t s ví d về tiến trình và luồng ... 31


4 1 Tìm kiếm song song với các tiến trình... 31


4 2 Thuật toán s p xếp tr n ng đa luồng ... 33


Bài tập: ... 36


CH NG 5: C C D CH V C A WINDOWS ... 37


1 T ng quan về d ch v trên Windows ... 37


2 Các thành phần c a m t d ch v ... 37


2 1 Hàm main ... 37


2 2 Hàm ServiceMain ... 37



2 3 Ki m soát d ch v qua các Handler ... 37


3 Ví du: d ch v đ n giản trên Windows ... 38


4 Quản lý các d ch v c a Windows ... 41


4 1 Các phư ng pháp ki m soát các d ch v c a Windows ... 41


4 2 Ví d : Điều khi n các d ch v c a Windows ... 41


Bài tập: ... 45


CH NG 6: LẬP TRÌNH SOCKET ... 46


1 Khái ni m sockets trên Windows ... 46


2 Các hàm sockets phía server... 46


3 Các hàm sockets phía client ... 47


</div>
<span class='text_page_counter'>(7)</span><div class='page_container' data-page=7>

iii


4 1 Phía server ... 47


4 2 Phía client ... 53


5. Windows Sockets 2.0 ... 55


Bài tập: ... 55



CH NG 7: TH VI N LIÊN K T ĐỘNG ... 56


7 1 Khái ni m và ng d ng c a thư vi n liên kết đ ng ... 56


7 2 H th ng thư vi n liên kết đ ng c a Windows ... 56


7 3 Các ước t o m t thư vi n DLL ... 57


7 4 Chia s nhớ gi a các thư vi n liên kết đ ng ... 64


7 5 Các v n đề khác về thư vi n liên kết đ ng ... 65


Bài tập: ... 66


TÀI LI U THAM KHẢO ... 67


</div>
<span class='text_page_counter'>(8)</span><div class='page_container' data-page=8>

1


<b>LỜI NÓI ĐẦU </b>


H điều hành Windows c a Microsoft là h điều hành được cài đ t nhiều nh t trên các
máy PC hi n nay Sự ph iến c a Windows và nền tảng phần c ng c a Intel dẫn tới sự cần
thiết phải c nh ng hi u iết s u về ch ng, đ c i t đ i với nh ng lập trình viên M c đích
c a học phần này là cung c p cho học viên m t cái nhìn t ng quan, từ c ản tới chi tiết về
các khía c nh c a lập trình trên h điều hành Windows, từ các chi tiết trong c u tr c c a m t
chư ng trình tới các khái ni m c p cao về tiến trình, luồng, x lý song song, thư vi n DLL,
lập trình Socket, can thi p vào c sở d li u Registry


Tài li u này dựa trên nh ng kinh nghi m và nghiên c u mà tác giả đã đ c r t, thu thập
trong q trình giảng d y mơn học Lập trình C trên Windows, c ng với sự tham khảo c a các


tài li u c a các đồng nghi p, các tác giả trong và ngoài nước, từ đi n trực tuyến Wikipedia
Với y chư ng được chia thành các ch đề khác nhau từ các khái ni m c ản cho tới các
thao tác với h th ng file, thư m c, h th ng CSDL Registry, quản lý tiến trình và luồng, lập
trình quản lý d ch v , lập trình socket, thư vi n liên kết đ ng DLL hy vọng s cung c p cho
các em sinh viên, các n đ c giả m t tài li u ích M c d đã r t c g ng song vẫn không
tránh kh i m t s thiếu s t, hy vọng s được các n đồng nghi p, các em sinh viên, các
n đ c giả g p ý ch n thành đ tơi c th hồn thi n h n n a tài li u này


Xin g i lời cảm n ch n thành tới các n đồng nghi p và Ban ch nhi m khoa
Công ngh Thông tin đã t o điều ki n gi p đỡ đ tài li u này c th hoàn thành.


<i> Hả ò g, á g 06 ăm 2010 </i>


<b> Tác giả </b>


<b> Nguy n H u Tu n </b>




</div>
<span class='text_page_counter'>(9)</span><div class='page_container' data-page=9>

2


<b>Ch ng 1 Các khái niệm c ản </b>


Tài li u này được iên so n đ cung c p cho người học nh ng kiến th c c ản vế vi c
viết các chư ng trình s d ng giao di n lập trình API trên mơi trường Win32 Ngôn ng được
s d ng là ngơn ng C, hầu hết các trình iên d ch C++ hi n nay đều c th d ch được các
chư ng trình mẫu trình ày trong tài li u này Hầu hết t t cả các thông tin được trình ày
trong tài li u này đều c th ng d ng cho t c ngôn ng nào c th truy cập các hàm API,
chẳng h n như Java, Assem ly, và Visual Basic



Tài li u này được iên so n không phải đ d y các n đ c giả lập trình ng ngôn ng
C, ho c d y ch ng ta s d ng t c m t trình iên d ch c th nào chẳng h n như Borland
C++, Visual C++, tuy nhiên trong phần ph l c tôi s dành m t ch t đ cung c p cho các
n m t s ch ý về m t s trình iên d ch mà tơi đã s d ng


<b>1 Gi i thiệu về mơi tr ờng ập trình Win ows </b>
<b>1 1 C s về hệ iều hành Win ows </b>


H điều hành Windows là m t h điều hành dành cho người d ng cu i End User
Operating System với các tính năng c ản sau: đa nhi m, giao di n đồ họa, plug and play và
quan trọng nh t là Windows Interface Based - t c là giao di n các chư ng trình ch y trên
Windows đều c d ng các c a s


<b>1 2 Các phiên ản của hệ iều hành Win ows </b>


Do cách d ng tiếng Anh và vi c hi u tiếng Anh dẫn tới vi c nhiều người hi u về các
phiên ản c a h điều hành Windows chưa chính xác Ví d c n cho r ng Windows XP
Professional Edition và Windows XP Home Edition là hai phiên ản khác nhau c a h điều
hành Windows Thực ra như vậy vừa đ ng l i vừa không đ ng, đ ng là Windows XP
Professional Edition và Windows XP Home Edition là hai Edition khác nhau c a c ng 1
Version Windows XP, c l sai là vì hi u từ Edition và Version sai Version c ngh a là m t
phiên ản, thường đi k m với các s hi u c a phiên ản 1 0, 1 2 5 0 và thường là m t
thay đ i lớn đ i với ản th n phần mềm, ví d như đ i với Windows thì c 3 thay đ i lớn:
thay đ i về kiến tr c nền tảng c a h điều hành t c là phần kernel c a h điều hành , hai là
cập nhật các ản vá patch cho các l i c a phiên ản trước đ đ i với t t cả các phần c a h
điều hành, a là các phần mới c a h điều hành c th là các ng d ng đi k m ho c h trợ
thêm các công ngh mới, ví d như đ i với Windows là chu n Wi-Fi, DVD, dot NET
framework hay các ng d ng như Windows Media Player, IE


C n Edition là n ản khác nhau c a c ng m t phiên ản, các Edition thường g n với


các yếu t về đ a lý, ngơn ng khác nhau ví d như Compact Edition ngh a là ản r t gọn,
Standard Edition là ản chu n, Ultimate Edition là ản c các tính năng cao c p nh t Đ i
với h điều hành Windows các Edition khác nhau thường ph n i t ởi các tính năng c a
ch ng, do nh m tới vi c ph c v các đ i tượng khác nhau nên Microsoft đi m t s tính
năng khơng cần thiết và tăng thêm các tính năng mà đ i tượng người d ng hay d ng ví d
như ản Home Edition nh m tới người d ng gia đình nên các tính năng đồ họa, video, m
thanh phải t t, c n ản Professional nh m tới các người d ng chuyên nghi p c trình đ cao
nên các tính năng h th ng s cao h n


Windows c các phiên ản sau đ y:
Windows 1.01


</div>
<span class='text_page_counter'>(10)</span><div class='page_container' data-page=10>

3


Windows 2.11
Windows 3.0
Windows 3.1x


Windows For Workgroups 3.1
Windows NT 3.1


Windows For Workgroups 3.11


Windows 3.2 (released in Simplified Chinese only)
Windows NT 3.5


Windows NT 3.51
Windows 95
Windows NT 4.0
Windows 98


Windows 98 SE
Windows 2000
Windows Me
Windows XP


Windows XP 64-bit Edition 2003
Windows Server 2003


Windows XP Professional x64 Edition
Windows Fundamentals for Legacy PCs
Windows Vista


Windows Home Server
Windows Server 2008
Windows 7


T t nhiên là m i Version trên l i c nhiều Edition khác nhau Phần nh n Kernel –
Core c a h điều hành luôn là phần quan trọng nh t c a m t h điều hành Đ i với Windows
nh n gồm 3 thành phần: các d ch v ch y ở m c nh n kernel-mode service, đ ph n i t với
các d ch v ch y ở m c ng d ng gồm các thư vi n chính c a h điều hành, các thư vi n
thực hi n quản lý tiến trình, lập l ch, quản lý vào ra d li u trên đ a c ng, nhớ Phần 2 là
các thư vi n làm vi c với các phần c ng ở m c chung, phần 3 là các Diver


<b>1 3 Vai trò của Win ows trên th tr ờng phần mềm </b>


Do sự th ng tr c a hãng Microsoft n i riêng và sự ph iến gần như đ c tôn c a h
điều hành Windows n i chung ở Vi t Nam nên Windows đ ng vai tr hết s c quan trọng
trong vi c phát tri n phần mềm ở Vi t Nam Về ản ch t các chư ng trình đều phải thực hi n
trên m t nền tảng platform nh t đ nh ao gồm các chi tiết từ phần c ng cho tới phần mềm,
tuy nhiên đ i với đa s ng d ng, các lập trình viên cần quan t m nhiều nh t tới h điều hành


mà ng d ng s ch y


<b>2. Th viện Win32 và Win64 </b>
<b>2.1 Win32 API </b>


</div>
<span class='text_page_counter'>(11)</span><div class='page_container' data-page=11>

4


<b>2.2 Win64 API </b>


Win64 là phiên ản 64 it c a thư vi n Win32, là m t iến th dành cho các nền tảng 64
it c a h điều hành Windows ví d hi n t i là AMD64 và IA-64 Cả hai phiên ản 32 và 64
it c a m t ng d ng đều c th được iên d ch từ m t mã chư ng trình chung, m c d c
m t s khác i t trong hai phiên ản này Sự khác nhau c ản c a hai phiên ản là các con
tr đ a chỉ c a Win32 là 32 it, c n với Win64 là 64 it


<b>3 Các c phát triển ứng ụng trên Win ows </b>
<b>3.1 Ch ng trình Win32 n giản nhất </b>


Nếu n là m t người mới t đầu lập trình trên mơi trường Win32 thì thao tác đầu tiên
mà n cần phải làm được đ là d ch m t chư ng trình c ản trên môi trường Windows Hãy
gõ đo n chư ng trình trên vào và nếu mọi th suôn s n s c m t chư ng trình đ n giản
nh t vô ngh a trong s các chư ng trình mà n đã làm.


Hãy nhớ là d ch chư ng trình này theo ki u d ch m t chư ng trình viết ng ngôn ng
C, không phải ngôn ng C++ Trong hầu hết các trường hợp điều này đ n giản thực hi n ng
cách đ i phần tên mở r ng từ cpp thành c Chẳng h n n c th đ t tên cho file chư ng trình
sau là test c và t đầu làm vi c


<b>#include <windows.h> </b>



<b>int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, </b>
<b>LPSTR lpCmdLine, int nCmdShow) </b>


<b>{ </b>


<b> MessageBox(NULL, "Goodbye, cruel world!", "Note", MB_OK); </b>
<b> return 0; </b>


<b>} </b>


Nếu như chư ng trình khơng làm vi c ước đầu tiên mà n cần làm là đọc t t cả các
l i error mà chư ng trình áo lên và nếu như n không hi u ý ngh a c a ch ng hãy tra
trong t c m t quy n sách d y lập trình ho c các sách hướng dẫn đi k m với trình iên d ch
mà n đang s d ng Hãy ch c ch n là n c đầy đ các file mà trình iên d ch yêu cầu
Thật không may là tôi không th gi p nhiều trong trường hợp này vì các l i ph thu c vào
trình iên d ch và người s d ng trong vi c g y l i cũng như s a l i


B n c th nhận được m t vài cảnh áo từ trình iên d ch về vi c chư ng trình khơng
s d ng các tham s được cung c p c ng với hàm WinMain Nhưng không sao điều quan
trọng là n d ch chư ng trình thành cơng và c m t chư ng trình Win32 thực sự Ch ng ta
s ph n tích các đo n mã chư ng trình kỹ càng h n.


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)


WinMain là hàm chính c a m t chư ng trình trên mơi trường Windows gi ng như
hàm main trên môi trường DOS và UNIX Đ là n i các đo n mã chư ng trình s được thực
thi Các tham s c a hàm main gồm c :


</div>
<span class='text_page_counter'>(12)</span><div class='page_container' data-page=12>

5



Tham s này quản lý module chư ng trình file exe trong nhớ H điều hành s
d ng tham s này đ quản lý chư ng trình khi thực hi n


HINSTANCE hPrevInstance


Luôn là NULL đ i với các chư ng trình Win32
LPSTR lpCmdLine


Các tham s d ng l nh c a chư ng trình được truyền dưới d ng m t x u Khơng ao
gồm tên chư ng trình


int nCmdShow


M t s nguyên c th truyền cho hàm ShowWindow Ch ng ta s àn về tham s
này sau.


Tham s hInstance được d ng cho các công vi c đ i lo i như n p load các tài nguyên
và t c tác v nào khác được thực hi n theo ki u từng module c ản M t module là m t
file EXE ho c file DLL được n p vào chư ng trình c a n Đ i với hầu hết không phải t t
cả các chư ng trình được trình ày trong tài li u này, chỉ c m t module mà ch ng ta cần
quan t m đ là file chư ng trình EXE


<b>Các qui c gọi hàm </b>


WINAPI chỉ đ nh qui ước gọi hàm và được đ nh ngh a là _stdcall Nếu như n không
hi u ý ngh a c a ch ng thì cũng khơng cần ận t m nhiều vì ch ng khơng ảnh hưởng tới tài
li u này chỉ cần nhớ là đ y là m t điều cần thiết ki u c a hàm WinMain là int, nhưng ki u
gọi hàm là WINAPI



Các ki u d li u Win32


Các n s th y r ng r t nhiều từ kh a thông thường ho c các ki u d li u đều c các
cách đ nh ngh a c th trên môi trường Windows, UINT là unsigned int, LPSTR là char *, v n
v n Vi c chọn lựa s d ng cách nào thực sự ph thu c vào n Nếu n thích s d ng char
* h n là LPSTR thì hãy s d ng cách đ nhưng cần phải ki m soát được vi c s d ng c a
mình cần n m rõ các ki u d li u trước khi thay ch ng ng m t ki u khác


B n chỉ cần n m v ng m t s nguyên t c và s hi u ý ngh a c a các tên này: LP là long
pointer. Trên môi trường Win32 phần long này không quan trọng và hoàn toàn c th qua
C n nếu n không hi u con tr là gì thì c l n nên học l i về C ho c qua ch ng và tiếp
t c


Tiếp đến là LPCSTR: long pointer const là m t h ng x u, t c là m t x u không th thay
đ i, ngoài ra gi a hai ki u LPSTR và LPCSTR c n c th c thêm m t ch T nhưng nếu n
không c ý đ nh s d ng các font Unicode trong chư ng trình thì n cũng chẳng c ý ngh a gì
đ c i t


<b>3.2 Ch ng trình c a sổ n giản </b>


<b>Ví d : chư ng trình gồm 1 c a s đ n giản trên Windows </b>


</div>
<span class='text_page_counter'>(13)</span><div class='page_container' data-page=13>

6


Tôi luôn mu n làm trước và học kỹ càng sau vì thế ở đ y tôi s trình ày đo n mã
chư ng trình t o ra m t c a s trước và giải thích sau:


#include <windows.h>


const char g_szClassName[] = "myWindowClass"; /* tên lớp c a s */



// Step 4: the Window Procedure


LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam,
LPARAM lParam)


{


switch(msg)
{


case WM_CLOSE:


DestroyWindow(hwnd);
break;


case WM_DESTROY:
PostQuitMessage(0);
break;


default:


// đ windows x lý các thông đi p c n l i


return DefWindowProc(hwnd, msg, wParam, lParam);
}


return 0;
}



int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)


{


WNDCLASSEX wc;
HWND hwnd;
MSG Msg;


</div>
<span class='text_page_counter'>(14)</span><div class='page_container' data-page=14>

7


wc.style = 0;


wc lpfnWndProc = WndProc; /* hàm x lý thông đi p c a s */
wc.cbClsExtra = 0;/* không cần thông tin thêm cho c a s */
wc.cbWndExtra = 0;


wc.hInstance = hInstance;


wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);


wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); /* màu nền */
/*wc.hbrBackground = GetStockObject(WHITE_BRUSH ; màu nền tr ng */
wc lpszMenuName = NULL; /* không c h th ng thực đ n */


wc lpszClassName = g_szClassName; /* tên lớp c a s */
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
/* đăng ký lớp c a s */



if(!RegisterClassEx(&wc))
{


MessageBox(NULL, "Window Registration Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);


return 0;
}


// Step 2: Creating the Window


// T o ra m t th nghi m c a lớp c a s cho ng d ng
hwnd = CreateWindowEx(


WS_EX_CLIENTEDGE,
g_szClassName,


"The title of my window",
WS_OVERLAPPEDWINDOW,


CW_USEDEFAULT, CW_USEDEFAULT, 440, 420,
NULL, NULL, hInstance, NULL);


if(hwnd == NULL)
{


</div>
<span class='text_page_counter'>(15)</span><div class='page_container' data-page=15>

8


return 0;
}



// Hi n th c a s


ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);


// Step 3: The Message Loop


// Step 3: T o v ng l p x lý thông đi p
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{


TranslateMessage(&Msg);
DispatchMessage(&Msg);
}


return Msg.wParam;
}


Hình 1 – C a s c a chư ng trình khi ch y


Đ y c l là m t chư ng trình windows đ n giản nh t mà n c th viết và ch c năng
c a chư ng trình đ n giản là t o ra m t c a s cũng r t đ n giản B n nên gõ chư ng trình và
iên d ch đ ch y th và hãy đảm ảo là không c l i gì xảy ra


Bước 1: Đăng ký Registering lớp c a s Window


M t lớp c a s Window Class ch a các thông tin về ki u c a s , ao gồm th t c
Window c a n th t c này ki m soát c a s khi n được t o ra và đáp ng l i các sự ki n
người d ng tác đ ng lên c a s , các icon lớn và nh c a c a s , và màu nền c a c a s Theo


cách này n c th đăng ký m t lớp và sau đ t o ra ao nhiêu c a s t y thích mà khơng
cần chỉ rõ t t cả các thu c tính đ thêm m t lần nào n a Hầu hết các thu c tính mà n thiết
lập trong lớp c a s window c th thay đ i được theo m t cách r t c ản th m c nếu
như n thích Và cần ch ý là lớp c a s này khơng liên quan gì tới khái ni m các lớp trong
C++.


const char g_szClassName[] = "myWindowClass";


</div>
<span class='text_page_counter'>(16)</span><div class='page_container' data-page=16>

9


WNDCLASSEX wc;


wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;


wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;


wc.cbWndExtra = 0;
wc.hInstance = hInstance;


wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = NULL;


wc.lpszClassName = g_szClassName;


wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);



if(!RegisterClassEx(&wc))
{


MessageBox(NULL, "Window Registration Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);


return 0;
}


Đ là đo n mã chư ng trình ch ng ta s d ng trong hàm WinMain đ đăng ký lớp c a
s c a ch ng ta Ch ng ta s điền đầy đ các thành viên c a c u tr c WNDCLASSEX và gọi
tới hàm RegisterClassEx


Các thành viên c a c u tr c ảnh hưởng đến lớp c a s gồm c :
c Size: kích thước c a c u tr c


style: Class Style CS_* , đ không nhầm lẫn với Window Style WS_* Thơng thường
thu c tính này được gán ng 0


lpfnWndProc: con tr tr tới th t c quản lý c a s cho lớp c a s này


c ClsExtra: Lượng d li u thêm được c p phát trong nhớ cho m i c a s thu c lo i
này Thông thường cũng được gán ng 0


hInstance: Quản lý m t th nghi m instance c a ng d ng tham s đầu tiên c a hàm
WinMain()).


</div>
<span class='text_page_counter'>(17)</span><div class='page_container' data-page=17>

10


hCursor: Con tr s xu t hi n khi con tr chu t di chuy n qua v ng c a s c a chư ng


trình


h rBackground: Tham s s d ng đ thiết lập mầu nền c a c a s


lpszMenuName: tên c a tài nguyên menu được s d ng cho các c a s c a lớp
lpszClassName: Tên đ đ nh danh lớp c a s


hIconSm: Icon nh 16x16 hi n th trên thanh task ar và g c trên ên trái c a c a s
B n không nên lo l ng nếu chưa hi u về các thu c tính này, ch ng s được giải thích ở
các phần tiếp theo c a tài li u này M t điều khác cần phải nhớ là không nên c nhớ nh ng
thu c tính này Tơi r t ít khi khơng mu n n i là khơng ao giờ nhớ các thu c tính cũng như
các tham s c a các hàm, điều đ hoàn toàn là m t c g ng lãng phí thời gian và cơng s c
Nếu như n iết các hàm n cần s d ng trong m t chư ng trình nào đ , hãy tra trong các
tài li u help Nếu n không c các file help hãy down ch ng về, các file ki u này trên m ng
không hề thiếu Cu i c ng thì n s iết các tham s c a các hàm mà n thường xuyên s
d ng


Tiếp đến ch ng ta gọi tới hàm RegisterClassEx và ki m tra xem hàm này c thành
công hay không, nếu như hàm trả về sai ch ng ta s hi n th m t thông áo th t i và dừng
chư ng trình


Bước 2: T o ra c a s chư ng trình


Khi đã đăng ký lớp c a s , ch ng ta c th t o ra các c a s trong chư ng trình Các
n nên tra các tham s c a hàm CreateWindowEx n luôn nên làm vậy khi làm vi c với
các hàm API mới , nhưng tơi s giải thích m t ch t ở đ y:


HWND hwnd;


hwnd = CreateWindowEx(


WS_EX_CLIENTEDGE,
g_szClassName,


"The title of my window",
WS_OVERLAPPEDWINDOW,


CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
NULL, NULL, hInstance, NULL);


Tham s đầu tiên WS_EX_CLIENTEDGE là ki u c a s mở r ng extended , trong
trường hợp này tham s này được s d ng đ t o thành m t đường viền chìm ên trong xung
quanh c a s C th đ t ng 0 nếu ch ng ta mu n khác Cũng nên thay đ i các giá tr khác
đ xem ch ng làm vi c như thế nào


</div>
<span class='text_page_counter'>(18)</span><div class='page_container' data-page=18>

11


Tham s ch ng ta s d ng WS_OVERLAPPEDWINDOW trong vai tr tham s
Window Style C khá ít các tham s ki u này do đ n nên ki m tra và thay đ i giá tr c a
ch ng đ xem kết quả họat đ ng như thế nào Ch ng ta s àn thêm về các tham s này sau


B n tham s tiếp theo CW_USEDEFAULT, CW_USEDEFAULT, 320, 240 là tọa đ
X và Y c a g c trên ên trái c a c a s và các kích thước dài r ng c a n Tôi đã thiết lập giá
tr c a X và Y là CW_USEDEFAULT đ windows tự chọn v trí đ đ t c a s chư ng trình
khi ch y Hãy nhớ là ên trái c a màn hình là m t giá tr 0 c a X và n tăng dần khi sang
phải Đỉnh c a màn hình tư ng ng với giá tr 0 c a Y tăng dần theo chiều đi xu ng Các đ n
v là các đi m ảnh, là đ n v nh nh t mà màn hình c th hi n th được t i đ ph n giải hi n
t i


Tiếp theo NULL, NULL, g_hInst, NULL ch ng ta c m t handle quản lý c a s cha
c a c a s được sinh ra, m t handle quản lý menu, m t handle cho th nghi m c a ng d ng


và m t con tr tr tới d li u c a s Trong windows các c a s trên màn hình được s p xếp
theo m t c u tr c ph n c p theo ki u các c a s cha và con Khi ch ng ta nhìn th y m t n t
trên m t c a s , n t đ là con và n được ch a trong c a s là cha c a n Trong ví d này
c a ch ng ta handle c a c a s cha là NULL vì ch ng ta khơng c c a s cha nào cả, đ y là
c a s chính ho c c a s ở c p cao nh t c a ch ng ta Menu cũng là NULL vì ch ng ta chưa
c menu chư ng trình nào Handle dành cho th nghi m c a chư ng trình được gán là giá tr
được truyền cho tham s đầu tiên c a hàm WinMain D li u c a s thường là ch ng ta
chẳng ao giờ s d ng ch ng) c th được s d ng đ g i các d li u khác tới c a s đang
được t o ra và cũng là NULL


Nếu n đang ăn khoăn về giá tr NULL í hi m này thì hãy yên t m vì n đ n giản
chỉ là 0 zero Thực sự trong C n được đ nh ngh a là void* 0 vì n được s d ng với các
con tr Vì thế cho nên n c th s g p các cảnh áo khi iên d ch chư ng trình nếu s d ng
NULL cho các giá tr ki u nguyên, t y thu c vào trình iên d ch và c p đ cảnh áo được
thiết lập với trình iên d ch B n c th qua các cảnh áo ho c đ n giản là s d ng giá tr 0
đ thay thế


Nguyên nh n s 1 mà mọi người khơng iết t i sao chư ng trình c a mình l i c l i là
do họ không ki m tra các giá tr trả về c a lời gọi hàm mà họ thực hi n trong chư ng trình
c a mình CreateWindow s trả về sai trong m t s trường hợp ngay cả khi n là m t lập
trình viên c nhiều kinh nghi m, chỉ đ n giản ởi vì c r t nhiều l i mà ch ng ta r t d t o ra
ch ng Cho tới khi n học được cánh nhanh ch ng xác đ nh các l i ki u như vậy, hãy tự cho
mình m t c h i đ c th tìm ra các l i trong chư ng trình, hãy ln ki m tra các giá tr trả
về khi gọi tới các hàm


if(hwnd == NULL)
{


MessageBox(NULL, "Window Creation Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);



return 0;
}


</div>
<span class='text_page_counter'>(19)</span><div class='page_container' data-page=19>

12


tham s cu i c ng c a hàm WinMain và sau đ cập nhật n đ đảm ảo là tự n được v l i
m t cách hợp l trên màn hình


ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);


Tham s nCmdShow là t y chọn, n c th đ n giản gán n là SW_SHOWNORMAL
m i khi ch ng ta làm vi c với n Tuy nhiên s d ng tham s được truyền vào hàm
WinMain s t o c h i cho các người d ng s d ng chư ng trình c a ch ng ta c th chỉ
đ nh họ mu n ho c không mu n c a s c a ch ng ta t đầu với kích thước c a s lớn nh t
ho c nh nh t B n s th y các t y chọn này trong các tham s c a các shortcut c a tới các
c a s


Bước 3: V ng l p x lý thông đi p


Đ y chính là trái tim c a tồn chư ng trình, hầu hết nh ng th mà chư ng trình c a
ch ng ta x lý là n m ở đ y


while(GetMessage(&Msg, NULL, 0, 0) > 0)
{


TranslateMessage(&Msg);
DispatchMessage(&Msg);
}



return Msg.wParam;


Hàm GetMessage l y m t thông đi p từ hàng đợi thông đi p c a ng d ng c a n
B t kỳ thời đi m nào người d ng di chuy n con chu t, gõ àn phím, click chu t trên menu
c a c a s chư ng trình, ho c làm t c m t thao tác nào đ i lo i như vậy, các thông đi p s
được sinh ra và thêm ch ng vào hàng đợi thông đi p c a chư ng trình B ng cách gọi tới hàm
GetMessage n đang yêu cầu thông đi p tiếp theo lo i kh i hàng đợi và trả n về cho
n x lý Nếu như không c thông đi p nào hàm GetMesage s chuy n sang locks Nếu
n không quen với thuật ng , điều đ c ngh a là n s đợi cho tới khi c m t thông đi p tiếp
theo đ x lý l y về cho chư ng trình


TranslateMessage thực hi n thêm m t s x lý trên các sự ki n àn phím chẳng h n
như sinh ra các thông đi p WM_CHAR c ng với các thông đi p WM_KEYDOWN Cu i
c ng DispatchMessage g i thông đi p tới c a s mà thông đi p cần được g i tới x lý theo
ki u hướng sự ki n Đ c th là c a s chính c a chư ng trình ho c c th là m t c a s
khác, ho c là m t điều khi n, và trong m t s trường hợp là m t c a s được t o ra ở hậu
trường ởi h th ng ho c m t chư ng trình khác Đ y khơng phải là điều mà các n cần phải
lo l ng vì t t cả nh ng gì ch ng ta àn tới là l y thông đi p và g i n đi, h th ng s x lý đ
đảm ảo thông đi p đ được g i đến đ ng n i s nhận n


Bước 4: Th t c c a s


Nếu như v ng l p thông đi p là trái tim c a chư ng trình thì th t c c a s là não
c a chư ng trình Đ y là n i mà t t cả các thông đi p được g i tới c a s c a ch ng ta được
x lý


</div>
<span class='text_page_counter'>(20)</span><div class='page_container' data-page=20>

13


{



switch(msg)
{


case WM_CLOSE:


DestroyWindow(hwnd);
break;


case WM_DESTROY:
PostQuitMessage(0);
break;


default:


return DefWindowProc(hwnd, msg, wParam, lParam);
}


return 0;
}


Th t c c a s được gọi tới đ x lý các thông đi p, tham s HWND là đ quản lý c a
s c a n, cũng chính là đ i tượng c a thông đi p Điều này là quan trọng ởi vì n c th
c hai ho c nhiều h n n a các c a s c ng lớp và ch ng s s d ng c ng m t th t c c a s
WndProc Sự khác nhau ở đ y là tham s hwnd s thay đ i t y thu c vào c a s là c a s
nào Chẳng h n khi ch ng ta l y về m t thông đi p WM_CLOSE ch ng ta s h y c a s Và
vì ch ng ta s d ng handle nhận được đ quản lý c a s qua tham s th nh t nên các c a s
khác s không ảnh hưởng, chỉ c c a s nhận thông đi p là s h y


WM_CLOSE được g i đến khi người d ng nh n chu t vào n t đ ng c a s ho c nh n


t hợp phím Alt+F4 Thao tác này s làm cho c a s h y theo m c đ nh, nhưng tôi mu n
x lý n m t cách d t khốt, vì điều này c th liên quan tới m t s thao tác khác chẳng h n
như đ ng các file d li u đang mở, ng t các kết n i c sở d li u, các kết n i m ng v n v n
trước khi thốt kh i chư ng trình


Khi ch ng ta gọi tới hàm DestroyWindow h th ng s g i thông đi p
WM_DESTROY tới c a s s h y , trong trường hợp này là c a s c a ch ng ta, và sau
đ h y t t cả các c a s con trước khi lo i c a s c a ch ng ta kh i h th ng Vì chỉ c
m t c a s trong chư ng trình c a ch ng ta nên cũng không c nhiều vi c phải làm và ch ng
ta mu n thoát kh i chư ng trình, vì thế hàm PostQuitMessage được gọi tới Hàm này s g i
thông đi p WM_QUIT tới v ng l p thông đi p Ch ng ta không ao nhận được thơng đi p
này vì n làm cho hàm GetMessage trả về FALSE, và như n s th y trong đo n mã v ng
l p x lý thông đi p c a ch ng ta, khi điều đ xảy ra ch ng ta dừng vi c x lý các thông đi p
và trả về giá tr cu i c ng, tham s wParam c a thông đi p WM_QUIT là giá tr được truyền
qua hàm PostQuitMessage Giá tr trả về chỉ thực sự c ích nếu chư ng trình c a ch ng ta
được thiết kế đ m t chư ng trình khác gọi và ch ng ta mu n trả về m t giá tr c th


Bước 5: không c ước 5


</div>
<span class='text_page_counter'>(21)</span><div class='page_container' data-page=21>

14


<b>3.3 Quản các thơng iệp </b>


Ví d : window_click.


Vậy là ch ng ta đã c m t c a s , nhưng n s không làm t c điều gì ngo i trừ
nh ng gì mà hàm DefWindowProc cho ph p n làm, chẳng h n như thay đ i kích thước,
ph ng to, thu nh , v n v n Quả là không th v tí nào


Trong phần tiếp theo tơi s hướng dẫn các n s a đ i nh ng gì ch ng ta đã viết đ t o


ra m t cái gì đ mới m


Trước tiên cần đảm ảo là n đã iên d ch và ch y chư ng trình simple_window thành
cơng, ch ng ta s copy n sang ví d mới và s a đ i mã nguồn code c a chư ng trình


Ch ng ta s thêm cho chư ng trình khả năng hi n th tên c a chư ng trình khi người
d ng kích chu t vào c a s c a chư ng trình Thực ch t c a khả năng mới này là ch ng ta s
tự x lý thông đi p nh n chu t c a người d ng, t t nhiên là trong hàm WndProc , từ:


LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam,
LPARAM lParam)


{


switch(msg)
{


case WM_CLOSE:


DestroyWindow(hwnd);
break;


case WM_DESTROY:
PostQuitMessage(0);
break;


default:


return DefWindowProc(hwnd, msg, wParam, lParam);
}



return 0;
}


Khi ch ng ta mu n x lý các thông đi p nh n chu t ch ng ta cần c thêm các handle:
WM_LBUTTONDOWN ho c WM_RBUTTONDOWN, WM_MBUTTONDOWN cho các
thao tác nh n chu t phải và gi a :


LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam,
LPARAM lParam)


{


switch(msg)
{


</div>
<span class='text_page_counter'>(22)</span><div class='page_container' data-page=22>

15


// <- we just added this stuff
break; // <-


case WM_CLOSE:
DestroyWindow(hwnd);
break;


case WM_DESTROY:
PostQuitMessage(0);
break;


default:



return DefWindowProc(hwnd, msg, wParam, lParam);
}


return 0;
}


Th tự x lý các thông đi p là quan trọng và cần nhớ là đ i với các thông đi p khác
ngoài WM_DESTROY và WM_QUIT cần c thêm c u l nh reak sau khi x lý xong thông
đi p


Trước tiên tôi s trình ày đo n mã l nh mà ch ng ta s thêm vào hi n th tên c a
chư ng trình c a ch ng ta và sau đ tơi s tích hợp đo n mã đ vào chư ng trình c a ch ng
ta Trong các phần sau c a chư ng trình tơi s chỉ cho các n đo n mã và đ các n tự tích
hợp đo n mã đ vào các chư ng trình Điều này vừa t t cho tôi: tôi s không phải gõ đi gõ l i
các đo n mã l nh và vừa t t cho các n: các n c c h i thực hành nh ng hi u iết c a
mình đ n ng cao kỹ năng thực hành C n nếu như n không ch c ch n hãy tra trong mã
nguồn chư ng trình đi k m với tài li u này


GetModuleFileName(hInstance, szFileName, MAX_PATH);


MessageBox(hwnd, szFileName, "This program is:", MB_OK |
MB_ICONINFORMATION);


Hàm WndProc c a ch ng ta y giờ s như sau:


LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam,
LPARAM lParam)


{



switch(msg)
{


case WM_LBUTTONDOWN:
// BEGIN NEW CODE


{


char szFileName[MAX_PATH];


</div>
<span class='text_page_counter'>(23)</span><div class='page_container' data-page=23>

16


GetModuleFileName(hInstance, szFileName, MAX_PATH);


MessageBox(hwnd, szFileName, "This program is:", MB_OK |
MB_ICONINFORMATION);


}


// END NEW CODE
break;


case WM_CLOSE:


DestroyWindow(hwnd);
break;


case WM_DESTROY:
PostQuitMessage(0);


break;


default:


return DefWindowProc(hwnd, msg, wParam, lParam);
}


return 0;
}


Hãy ch ý tới c p d u { và mới Các c p d u này là t u c khi ch ng ta khai áo các
iến trong c u l nh switch Bước tiếp theo t t nhiên là d ch chư ng trình, ch y th và xem kết
quả c a chư ng trình


Ch ng ta c th ch ý là ở đ y tôi đã s d ng hai iến khi gọi hàm
GetModuleFileName , tham s th nh t là m t handle tham chiếu tới m t chư ng trình đang
ch y, nhưng ch ng ta c th l y handle đ ở đ u ra Ở đ y m t l n n a ch ng ta l i s d ng
m t hàm API khác GetModuleHandle , thật may m n là đ i với hàm này nếu ch ng ta truyền
tham s là NULL vào thì kết quả trả về s là handle tr tới file được s d ng đ t o ra tiến
trình đã gọi hàm, đ chính xác là cái mà ch ng ta cần Và do đ ch ng ta c c u l nh:


HINSTANCE hInstance = GetModuleHandle(NULL);


Tham s th hai khi gọi hàm GetModuleFileName là m t con tr x u đ ch a đường
dẫn kết quả c a hàm tới chư ng trình c handle là tham s th nh t, ki u c a n là
LPTRSTR ho c LPSTR và do LPSTR hoàn toàn tư ng tự như char * nên ch ng ta khao áo
m t x u như sau:


char szFileName[MAX_PATH];



</div>
<span class='text_page_counter'>(24)</span><div class='page_container' data-page=24>

17


<b>3.4 Vòng p x thông iệp </b>


Nh ng kiến th c về v ng l p x lý thông đi p và c u tr c c a vi c g i m t thông đi p
là cần thiết đ viết t c ng d ng nào Cho đến thời đi m hi n t i ch ng ta mới xem x t m t
ch t về quá trình x lý thơng đi p, trong phần này tơi s trình ày với các n kỹ càng h n về
cả q trình x lý thơng đi p


Thế nào là m t thông đi p


M t thông đi p message là m t giá tr nguyên s Nếu n tra trong các file header
đ y là m t th i quen t t khi làm vi c với các hàm API n s th y các d ng khai áo sau:


#define WM_INITDIALOG 0x0110
#define WM_COMMAND 0x0111


#define WM_LBUTTONDOWN 0x0201


v n v n Các thông đi p được s d ng đ truyền thông hầu như mọi th trên h điều
hành windows ít nh t là t i các c p đ c ản Nếu n mu n m t c a s ho c m t điều khi n
là m t d ng c a s đ c i t thực hi n m t công vi c nào đ , n s phải g i cho n m t
thông đi p Nếu m t c a s khác mu n n làm điều gì đ n s g i tới cho n m t thông
đi p Nếu m t sự ki n xảy ra chẳng h n như người d ng gõ àn phím, di chuy n chu t, nh n
chu t lên m t utton, thì các thơng đi p s được h th ng h điều hành windows g i đến
cho các c a s ch u tác đ ng c a sự ki n đ Nếu n là m t trong các c a s như thế, n s
tiếp nhận và x lý thông đi p, c các hành vi thích hợp


M i m t thơng đi p c th c nhiều nh t là hai tham s , wParam và lParam Nguyên
ản wParam là 16 it và lParam là 32 it, nhưng trên các h th ng Win32 ch ng đều là 32 it


Không phải t t các thông đi p đều s d ng hai tham s này, và m i thông đi p s d ng ch ng
theo các cách khác nhau Chẳng h n thông đi p WM_CLOSE không s d ng cả hai tham s
trên, và n c th qua ch ng Thông đi p WM_COMMAND s d ng cả hai tham s trên,
wParam ch a hai giá tr , HIWORD wParam là thông đi p áo hi u nếu thích hợp và
LOWORD wParam là đ nh danh điều khi n ho c menu g i thông đi p lParam là HWND
window handle c a điều khi n g i thông đi p ho c NULL nếu như các thông đi p không
phải được g i đi từ m t điều khi n nào đ


HIWORD và LOWORD là các macro được đ nh ngh a ởi windows l y ra 2 yte cao
High Word c a m t giá tr 4 yte = 32 it 0xFFFF0000 và hai yte th p 0x0000FFFF
tư ng ng Trên các h th ng Win32 m t WORD là m t giá tr 16 it c n DWORD Dou le
WORD là m t giá tr 32 it


</div>
<span class='text_page_counter'>(25)</span><div class='page_container' data-page=25>

18


lParam đều ng 0 trong trường hợp này Điều này là do như ch ng ta đã n i trước ch ng
khơng c ý ngh a gì đ i với thông đi p WM_CLOSE


Các h p tho i Dialog


Khi n đã t đầu s d ng các h p tho i, n s cần g i các thông đi p tới các điều
khi n đ c th truyền thông với ch ng B n c th làm điều này ng cách trước hết l y
handle quản lý điều khi n ng hàm GetDlgItem và sau đ s d ng hàm SendMessage
ho c c th s d ng hàm SendDlgItemMessage hàm này kết hợp công vi c c a cả hai hàm
trên B n s cung c p cho hàm m t handle c a m t c a s và m t ID con và hàm s l y
handle con c a h p tho i và g i thông đi p tới cho n SendDlgItemMessage và m t vài
hàm API tư ng tự khác chẳng h n như GetDlgItemText s làm vi c trên t t cả các c a s
ch không chỉ với các h p tho i


Thế nào là hàng đợi thông đi p



Giả s n đang ận t i i với vi c x lý thông đi p WM_PAINT và đ t nhiên người
d ng thực hi n hàng lo t thao tác trên àn phím c a máy tính Điều gì s xảy ra B n s
ngăt vi c đang v đ x lý các thao tác àn phím c a người d ng ho c các thao tác đ s
qua T t cả các cách giải quyết như vậy đều c v n đề, giải pháp ở đ y là s d ng m t hàng
đợi đ lưu các thông điêp cần x lý, khi các thông đi p được g i đến ch ng s được thêm vào
hàng đợi và khi các thông đi p được x lý ch ng s được lo i kh i hàng đợi Và đ đảm
ảo các thông đi p không qua nếu như n đang ận x lý m t thông đi p nào đ , các
thông đi p khác s được chờ trong hàng đợi cho tới khi tới lượt ch ng được x lý


Thế nào là m t v ng l p thông đi p v ng l p x lý thông đi p – Message Loop)
while(GetMessage(&Msg, NULL, 0, 0) > 0)


{


TranslateMessage(&Msg);
DispatchMessage(&Msg);
}


1. V ng l p thông đi p gọi tới hàm GetMessage , hàm này s ki m tra hàng đợi
thông đi p c a n Nếu như hàng đợi thông đi p là r ng chư ng trình c a n về c ản
s dừng và đợi cho tới khi c m t thông đi p mới tr ng thái Block


2. Khi m t sự ki n xảy ra làm cho m t thông đi p được thêm vào hàng đợi
chẳng h n như h th ng ghi nhận m t sự ki n nh n chu t hàm GetMessage s trả về
m t giá tr nguyên dư ng chỉ ra r ng c m t thông đi p cần x lý, và các thông tin về
thông đi p đ s được điền vào c u tr c MSG truyền cho hàm Hàm s trả về 0 nếu như
thông đi p là WM_QUIT và là m t giá tr m nếu như c l i xảy ra


3. Ch ng ta nhận được thông đi p qua iến Msg và truyền cho hàm


TranslateMessage , hàm này thực hi n x lý thêm m t ch t, d ch các thông tin c a thông
đi p thành các thông đi p ký tự Bước này thực sự không t u c nhưng m t s thông
đi p s không làm vi c được nếu không c ước này


</div>
<span class='text_page_counter'>(26)</span><div class='page_container' data-page=26>

19


Window Procedure c a c a s đ Sau đ n s gọi tới hàm x lý thông đi p c a c a s ,
g i các tham s : handle c a c a s , thông đi p và các tham s wParam, lParam


5. Trong hàm x lý thông đi p n s ki m tra thông đi p và các tham s c a n
và làm t c điều gì mà n thích với ch ng Nếu n không mu n x lý các thông đi p
m t cách chi tiết c th , n hầu như chỉ vi c gọi tới hàm DefWindowProc , hàm này s
thực hi n các hành đ ng m c đ nh cho n điều này thường c ngh a là chẳng làm gì cả


6. Sau khi n đã kết th c vi c x lý thông đi p, hàm x lý thông đi p c a n trả
về, hàm DispatchMessage trả về và ch ng ta qua trở l i đầu v ng l p


Đ y là m t khái ni m cực kỳ quan trọng c a các chư ng trình trên Windows Th t c
x lý thông đi p c a n không được gọi m t cách thần í ởi h th ng, mà chính n đã gọi
tới ch ng m t cách gián tiếp thông qua vi c gọi tới hàm DitpatchMessage Nếu như n
mu n, n c th s d ng hàm GetWindowLong trên handle c a c a s đích c a thơng đi p
đ tìm ra th t c x lý c a s c a n và gọi tới hàm đ m t cách trực tiếp:


while(GetMessage(&Msg, NULL, 0, 0) > 0)
{


WNDPROC fWndProc = (WNDPROC)GetWindowLong(Msg.hwnd,
GWL_WNDPROC);


fWndProc(Msg.hwnd, Msg.message, Msg.wParam, Msg.lParam);


}


Tôi đã th cách đ với đo n mã chư ng trình trước c a ch ng ta và n ho t đ ng t t,
tuy nhiên c r t nhiều v n đề chẳng h n như các chuy n đ i Unicode/ANSI, các lời gọi tới
các điều khi n thời gian v n v n mà hàm này không ph hợp, và khả năng r t cao là n s
reak với hầu hết các chư ng trình trừ các chư ng trình đ n giản Vì thế khơng nên th d ng
hàm này, trừ khi n chỉ mu n th n


Ch ý là ch ng ta s d ng hàm GetWindowLong đ l y th t c x lý c a s c a c a
s T i sao ch ng ta không đ n giản là gọi tới hàm WndProc m t cách trực tiếp V ng l p
các thông đi p c a ch ng ta ch u trách nhi m đáp ng cho t t cả các c a s trong chư ng
trình c a ch ng ta, điều này ao gồm cả các th chẳng h n như các n t utton và các h p
danh sách với các hàm x lý thông đi p c a ch ng, vì thế ch ng ta cần đảm ảo là ch ng ta
gọi đến đ ng hàm x lý c a s c a các thành phần đ đ y thực sự là m t ví d c a khái ni m
đa th trong lập trình hướng đ i tượng Vì các c a s c th s d ng chung m t hàm x lý
thông đi p nên tham s đầu tiên handle c a c a s được d ng đ chỉ cho hàm x lý thông
đi p iết c a s nào là dành cho thông đi p nào


</div>
<span class='text_page_counter'>(27)</span><div class='page_container' data-page=27>

20


Ch ý: GetMessage s trả về -1 nếu như g p m t l i B n cần nhớ kỹ điều này nếu
không c th chư ng trình s g p tr c tr c, m c d hàm GetMessage c ki u BOOL song n
vẫn c th trả về m t giá tr không phải là TRUE hay FALSE vì BOOL c ngh a là UINT
unsigned int Các ví d sau c v s làm vi c t t:


while(GetMessage(&Msg, NULL, 0, 0))
while(GetMessage(&Msg, NULL, 0, 0) != 0)
while(GetMessage(&Msg, NULL, 0, 0) == TRUE)


Thực tế t t cả các trường hợp đ đều sai B n c th ch ý là tôi vẫn s d ng trường hợp


1 cho t t cả các ví d cho tới thời đi m này, và như tôi đã đề cập n vẫn làm vi c t t khi mà
hàm GetMessage không ao giờ trả về FALSE Tuy nhiên không th đảm ảo là hàm
GetMessage không g p l i trong t t cả các trường hợp và n nên s d ng cách viết như
sau:


while(GetMessage(&Msg, NULL, 0, 0) > 0)


<b> ài tập </b>


<b> ài tập 1 Viết chư ng trình mơ ph ng chư ng trình máy tính với các ch c năng tính tốn </b>


đ n giản trên Windows


</div>
<span class='text_page_counter'>(28)</span><div class='page_container' data-page=28>

21


<b>Ch ng 2: Hệ thống i và th mục </b>


<b>1 Truy cập và s ụng hệ thống i trên môi tr ờng Win ows </b>
<b>1 1 Hệ thống i và th mục của Win ows </b>


Windows h trợ n h th ng file, thư m c khác nhau trên các thiết phần c ng c a
h th ng, nhưng hi n nay chỉ c n NTFS là được Microsoft tập trung đ nh hướng phát tri n


H th ng file NTFS New Technology File System là h th ng file hi n đ i nh t h
trợ các tên file dài, khả năng an toàn ảo mật, ch u l i, mã h a, n n, các thu c tính mở r ng
và h trợ kích thước file và volume lớn Các h th ng đ a không h trợ NTFS và Windows
9x cũng không h trợ đ nh d ng này


H th ng FAT File Allocation Ta le – FAT và FAT32 là h th ng được phát tri n
lên từ h điều hành MS-DOS và Windows 3 1 FAT hay FAT16 FAT32 được đưa ra từ



<b>3 Quản i và th mục n ng cao </b>
<b> ài tập </b>


<b> ài tập 1 Viết chư ng trình mơ ph ng tìm kiếm file. </b>


<b> ài tập 2 Viết chư ng trình li t kê t t cả các thơng tin về các file và thư m c trong m t thư </b>


</div>
<span class='text_page_counter'>(29)</span><div class='page_container' data-page=29>

22


<b>Ch ng 3 Hệ thống CSDL R gistry </b>
<b>1 hái niệm và vai trò của CSDL R gistry </b>
<b>1.1 Các kh a, các hiv </b>


Registry là n i lưu tr t t cả các các lo i c u tr c d li u C u hình h th ng Windows,
c u hình phần c ng máy tính, c u hình thơng tin về các chư ng trình ng d ng dựa trên
Win32, và các thiết lập người d ng khác đều được lưu trong Registry


Ví d , t c m t phần c ng máy tính nào thay đ i đều làm ch c năng Plug and Play
C m và ch y khởi t o ngay và làm thay đ i ln c u hình trong Registry


Registry lưu tr t t cả các thiết lập về c u tr c nhớ, phần c ng, thiết ngo i vi, và
các thành phần liên quan đến m ng B n s tìm th y ở đ nhiều h n nh ng thiết lập cần thiết
trong các t p khởi t o an đầu


</div>
<span class='text_page_counter'>(30)</span><div class='page_container' data-page=30>

23


Các t p Registry c a Windows
Registry hi n t i ao gồm 3 t p chính:
1 T p USER DAT



D ng đ lưu tr nh ng xác lập người s d ng đ i với các phần mềm
2 T p SYSTEM DAT


D ng đ lưu tr nh ng xác lập liên quan tới máy tính và phần c ng
3 T p Policy pol


System policies được thiết kế đ chu n cho vi c ghi đ t c thiết lập đã được ch a
trong 2 thành phần registry khác nhau


System policies c th ch a d li u sung đ c trưng tới m ng hay môi trường t hợp
như đã được cài đ t ởi network administrator Bản th n System policies cũng đã được ch a
trong t p Policy pol Không như SYSTEM DAT và USER DAT, Policy pol không phải là
thành phần t u c c a phần cài đ t Windows


Các kh a chính trong m t CSDL Registry:


+ HKEY_LOCAL_MACHINE ch a các thơng tin về c u hình vật lý c a h th ng c ng
với các phần mềm đã được cài đ t trên h th ng


+ HKEY_USERS: ch a các thông tin c u hình c a tài khoản người d ng


+ HKEY_CURRENT_CONFIG: ch a các thông tin thiết lập c a h th ng hi n t i
chẳng h n như đ ph n giải màn hình hay font ch


+ HKEY_CLASS_ROOT: ch a các thông tin ánh x từ các ki u file sang các ng d ng
mở ch ng


HKEY_CURRENT_USER: ch a các thông tin về các tài khoản trên h th ng, chẳng
h n như các iến môi trường, các máy in và các t y chọn ng d ng khác



<b>1.2 Các kiểu iệu </b>


</div>
<span class='text_page_counter'>(31)</span><div class='page_container' data-page=31>

24


<b>Ph ng pháp </b> <b>Thiết ập </b>


Control Panel Phần lớn thiết lập h th ng SYSTEM Ví d n s d ng Display
Properties đ s a các thành phần c a m c appearance


System Policy Editor Thiết lập người d ng, vài thiết lập h th ng
Các chư ng trình ti n ích th 3 Thiết lập chi tiết ng d ng


B n c th đã s d ng Registry Editor đ thay đ i Registry ng tay Tôi thường d ng
Norton Registry Editor vì n c n c thêm ch c năng khác, ví d như tìm và thay thế đ i với
các thành phần c a Registry


Từ các phần mềm Registry Editor trên, ta nhận th y registry được trí thành các
nhánh lớn T i m i nhánh c các khoá SUBKEY T i các SUBKEY d li u được lưu ở các
d ng:


1 String D ng chu i
2. Numeric D ng s
3 Binary D ng nh ph n


4 Expanded String D ng chu i mở r ng
5 MultiString D ng chu i t ng hợp


Nếu n d ng Registry Editor - REGEDIT EXE thì s gọi tên khác là DWORD



<b>2 Quản CSDL R gistry </b>


Khi lập trình đ i với Registry, n phải thực hi n hết s c thận trọng, sao lưu các t p này
thường xuyên đ tránh l i đáng tiếc, phải m t công cài l i thì cũng r t m t thời gian S d ng
các hàm API đ i với Registry cũng xin hết s c thận trọng


<b>2.1 Thay ổi kh a </b>


Đ thay đ i giá tr c a m t kh a trong CSDL Registry ch ng ta s d ng hàm LONG
RegSetValueEx(HKEY hKey, LPCTSTR lpValueName, DWORD reserved, DWORD
dwType, CONST BYTE * lpData, CONST cbData).


<b>2 2 Thêm m i kh a </b>


</div>
<span class='text_page_counter'>(32)</span><div class='page_container' data-page=32>

25


<b>2.3 Liệt kê các kh a </b>


Hàm li t kê các kh a trong CSDL Registry là hàm LONG RegEnumKeyEx(HKEY
hKey, DWORD dwIndex, LPTSTR lpName, LPDWORD lpcbName, LPDWORD
lpReserved, LPTSTR lpClass, LPDWORD lpcbClass, PFILETIME lpftLastWriteTime).


<b>3 Can thiệp Win ows qua R gistry </b>


Hầu như t t cả các thay đ i, thiết lập c a Windows đều c th được thực hi n thông qua
vi c thiết lập các giá tr trong CSDL Registry, v n đề c t lõi là ch ng ta cần n m được kh a
và giá tr cần thay đ i tư ng ng


<b>3.1 Thay ổi giao iện </b>



Đ ngăn c m không cho người d ng thay đ i Wallpaper ch ng ta c th thay đ i giá tr
kh a: HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/policies/ActiveDeskto
p với giá tr DWORD là 1


Đ chỉ đ nh file Wallpaper c a Windows ta c th s a các kh a
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\


System với các kh a là Wallpaper, WallpaperStyle và giá tr ki u REG_SZ String là đường
dẫn tới file ảnh


<b>3 2 Thay ổi các thiết ập ối v i các ổ a </b>


Đ thay đ i thiết lập với các đ a ta thực hi n với các khóa
HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices c tên là MountedDevices như hình
sau:


<b>3 3 Thay ổi các thiết ập v i ng ời ng </b>


Các iến môi trường c a m t người d ng n m trong phần
HKEY_CURRENT_USER\Environment , c n cho cả h th ng n m trong phần
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session


Manager\Environment .


<b> ài tập </b>


<b> ài tập 1 Viết chư ng trình thay đ i giao di n Windows ng cách s d ng can thi p qua </b>


Registry.



<b> ài tập 2: Viết chư ng trình thay đ i các iến môi trường c a Windows ng cách s d ng </b>


</div>
<span class='text_page_counter'>(33)</span><div class='page_container' data-page=33>

26


<b>Ch ng 4 Quản các tiến trình và u ng </b>
<b>1 Các tiến trình và u ng trên Win ows </b>


T t cả các tiến trình process c a Windows đều c m t ho c nhiều luồng thread và
luồng chính là đ n v thực thi c sở nh t c a Windows Các luồng được lập l ch dựa trên các
nh n t : sự sẵn sàng c a các tài nguyên như CPU và nhớ vật lý, đ ưu tiên Windows h
trợ kiến tr c đa x lý đ i x ng SMP Symmetric MultiProcessing t đầu từ phiên ản NT4,
do đ các luồng c th ch y trên cac CPU riêng r trong c ng m t h th ng


Trên quan đi m c a lập trình viên m i tiến trình s ao gồm các tài nguyên:
+ M t ho c nhiều luồng


+ M t không gian nhớ ảo riêng.


+ M t ho c nhiều đo n mã, ao gồm c a các đo n mã trong các file DLL
+ M t ho c nhiều ph n đo n d li u ch a các d li u toàn c c


+ Các giá tr iến môi trường
+ V ng nhớ Heap


+ Các tài nguyên khác chẳng h n như các handle và các heap đã mở sẵn


M i luồng trong m t tiến trình s chia s mã chư ng trình, các iến tồn c c, các iến
môi trường, các tài nguyên M i luồng s được lập l ch m t cách riêng r và c các thành
phần sau:



+ M t ngăn xếp các lời gọi tới các th t c, các ng t, các quản lý i t l , và nhớ
+ M t mảng TLS Threa Local Storage các con tr đ c th c p phát nhớ lưu tr
d li u cho luồng


+ M t tham s trên stack, từ l c t đầu t o ra luồng, được s d ng riêng cho m i
luồng


</div>
<span class='text_page_counter'>(34)</span><div class='page_container' data-page=34>

27


<b>2 Các thao tác v i tiến trình </b>
<b>2 1 Tạo tiến trình </b>


Hàm c ản đ quản lý các tiến trình c a Windows là hàm CreateProcess , hàm này t o
ra m t tiến trình với m t luồng đ n Tham s mà hàm cần là tên file chư ng trình s thực
hi n Ch ng ta c th th y c nhiều đề cập tới khái ni m tiến trình cha, tiến trình con nhưng
thực sự thì quan h này không được quản lý ởi Windows Windows đ n thuần chỉ tham
chiếu tới các tiến trình t i ra m t tiến trình con mà n là tiến trình cha


Hàm CreateProcess c 10 tham s : BOOL CreateProcess (
LPCTSTR lpApplicationName,


LPTSTR lpCommandLine,


LPSECURITY_ATTRIBUTES lpsaProcess,
LPSECURITY_ATTRIBUTES lpsaThread,
BOOL bInheritHandles,


</div>
<span class='text_page_counter'>(35)</span><div class='page_container' data-page=35>

28


LPCTSTR lpCurDir,



LPSTARTUPINFO lpStartupInfo,


LPPROCESS_INFORMATION lpProcInfo)


<b>2 2 ết th c và thốt kh i một tiến trình </b>


Sau khi tiến trình kết th c, tiến trình, hay chính xác h n là m t luồng ch y trong tiến
trình s gọi tới hàm ExitProcess đ kết th c tiến trình Hàm này khơng trả về giá tr mà thay
vào đ s kết th c t t cả các luồng c a tiến trình Hàm c th gọi tới đ l y mã kết th c m t
tiến trình là GetExitCodeProcess


<b>2 3 Các thao tác v i iến môi tr ờng của Win ows </b>


Đ thao tác với các iến môi trường c a Windows ta d ng hai hàm sau:
DWORD GetEnvironmentVariable (


LPCTSTR lpName,
LPTSTR lpValue,
DWORD cchValue)


BOOL SetEnvironmentVariable (
LPCTSTR lpName,


LPCTSTR lpValue)


<b>2 4 V ụ Ghi nhật k thời gian th c hiện của các tiến trình </b>


#include "EvryThng.h"



int _tmain (int argc, LPTSTR argv [])
{


STARTUPINFO StartUp;


PROCESS_INFORMATION ProcInfo;


union { /* Structure required for file time arithmetic. */
LONGLONG li;


FILETIME ft;


} CreateTime, ExitTime, ElapsedTime;
FILETIME KernelTime, UserTime;


SYSTEMTIME ElTiSys, KeTiSys, UsTiSys, StartTimeSys, ExitTimeSys;
LPTSTR targv = SkipArg (GetCommandLine ());


OSVERSIONINFO OSVer;
BOOL IsNT;


HANDLE hProc;


</div>
<span class='text_page_counter'>(36)</span><div class='page_container' data-page=36>

29


GetVersionEx (&OSVer);


IsNT = (OSVer.dwPlatformId == VER_PLATFORM_WIN32_NT);
/* NT (all versions) returns VER_PLATFORM_WIN32_NT. */
GetStartupInfo (&StartUp);



GetSystemTime (&StartTimeSys);


/* Execute the command line; wait for process to complete. */
CreateProcess (NULL, targv, NULL, NULL, TRUE,


NORMAL_PRIORITY_CLASS, NULL, NULL, &StartUp, &ProcInfo);


/* Assure that we have all REQUIRED access to the process. */
DuplicateHandle (GetCurrentProcess (), ProcInfo.hProcess,
GetCurrentProcess (), &hProc,


PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, 0);
WaitForSingleObject (hProc, INFINITE);


GetSystemTime (&ExitTimeSys);


if (IsNT) { /* W NT. Elapsed, Kernel, & User times. */
GetProcessTimes (hProc, &CreateTime.ft,


&ExitTime.ft, &KernelTime, &UserTime);
ElapsedTime.li = ExitTime.li - CreateTime.li;


FileTimeToSystemTime (&ElapsedTime.ft, &ElTiSys);
FileTimeToSystemTime (&KernelTime, &KeTiSys);
FileTimeToSystemTime (&UserTime, &UsTiSys);
_tprintf (_T ("Real Time: %02d:%02d:%02d:%03d\n"),
ElTiSys.wHour, ElTiSys.wMinute, ElTiSys.wSecond,
ElTiSys.wMilliseconds);



_tprintf (_T ("User Time: %02d:%02d:%02d:%03d\n"),
UsTiSys.wHour, UsTiSys.wMinute, UsTiSys.wSecond,
UsTiSys.wMilliseconds);


_tprintf (_T ("Sys Time: %02d:%02d:%02d:%03d\n"),
KeTiSys.wHour, KeTiSys.wMinute, KeTiSys.wSecond,
KeTiSys.wMilliseconds);


</div>
<span class='text_page_counter'>(37)</span><div class='page_container' data-page=37>

30


/* Windows 9x and CE. Elapsed time only. */
...


}


CloseHandle (ProcInfo.hThread); CloseHandle (ProcInfo.hProcess);
CloseHandle (hProc);


return 0;
}


<b>3 Quản u ng thr a trên Win ows </b>
<b>3 1 Các khái niệm c ản </b>


Trong phần trước ch ng ta đã xem x t cách th c m t luồng thực hi n kết th c m t tiến
trình. Các luồng trong m t tiến trình chia s chung d li u và mã l nh, vì thế về ản ch t các
luồng đ cũng c v ng nhớ riêng c a ch ng Windows đáp ng điều này ng m t s cách
sau:


+ M i luồng c m t stack c a riêng n cho các lời gọi hàm và các x lý khác


+ Lời gọi tiến trình c th truyền m t iến, con tr , tới thời gian t o ra luồng
+ M i luồng c th c p phát TLS c a riêng n


<b>3 2 ơ hình oss Work r và các mơ hình khác </b>


L nh grepMT minh họa cho mơ hình Boss/Worker Luồng oss luồng chính s gán
các tác v cho luồng worker đ thực hi n M i luồng worker s được cho m t file đ tìm kiếm
và worker s trả về giá tr c a n cho oss thread Xem thêm ví d s p xếp tr n đ hi u rõ mơ
hình này.


<b>3 3 ộ nh ành cho u ng </b>


</div>
<span class='text_page_counter'>(38)</span><div class='page_container' data-page=38>

31


<b>3 4 Độ u tiên và các trạng thái của u ng </b>


Các luồng thu c về nh n c a Windows luôn c đ ưu tiên cao nh t khi sẵn sàng đ thực
hi n M t luồng được coi là không sẵn sàng đ thực hi n nếu n ở tr ng thái chờ, treo, hay
lock ởi m t lý do nào đ


<b>4 ột số v ụ về tiến trình và u ng </b>
<b>4 1 Tìm kiếm song song v i các tiến trình </b>


#include "EvryThng.h"


int _tmain (DWORD argc, LPTSTR argv [])


/* Create a separate process to search each file on the
command line. Each process is given a temporary file,
in the current directory, to receive the results. */


{


HANDLE hTempFile;


SECURITY_ATTRIBUTES StdOutSA = /* SA for inheritable handle. */
{sizeof (SECURITY_ATTRIBUTES), NULL, TRUE};


TCHAR CommandLine [MAX_PATH + 100];
STARTUPINFO StartUpSearch, StartUp;
PROCESS_INFORMATION ProcessInfo;
DWORD iProc, ExCode;


HANDLE *hProc; /* Pointer to an array of proc handles. */
typedef struct {TCHAR TempFile [MAX_PATH];} PROCFILE;
PROCFILE *ProcFile; /* Pointer to array of temp file names. */
GetStartupInfo (&StartUpSearch);


GetStartupInfo (&StartUp);


ProcFile = malloc ((argc - 2) * sizeof (PROCFILE));
hProc = malloc ((argc - 2) * sizeof (HANDLE));


/* Create a separate "grep" process for each file. */
for (iProc = 0; iProc < argc - 2; iProc++) {


_stprintf (CommandLine, _T ("%s%s %s"),
_T ("grep "), argv [1], argv [iProc + 2]);
GetTempFileName (_T ("."), _T ("gtm"), 0,


</div>
<span class='text_page_counter'>(39)</span><div class='page_container' data-page=39>

32



CreateFile (ProcFile [iProc].TempFile,
GENERIC_WRITE,


FILE_SHARE_READ | FILE_SHARE_WRITE, &StdOutSA,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
StartUpSearch.dwFlags = STARTF_USESTDHANDLES;


StartUpSearch.hStdOutput = hTempFile;
StartUpSearch.hStdError = hTempFile;


StartUpSearch.hStdInput = GetStdHandle (STD_INPUT_HANDLE);


/* Create a process to execute the command line. */
CreateProcess (NULL, CommandLine, NULL, NULL,


TRUE, 0, NULL, NULL, &StartUpSearch, &ProcessInfo);
/* Close unwanted handles. */


CloseHandle (hTempFile); CloseHandle (ProcessInfo.hThread);
hProc [iProc] = ProcessInfo.hProcess;


}


/* Processes are all running. Wait for them to complete. */


for (iProc = 0; iProc < argc - 2; iProc += MAXIMUM_WAIT_OBJECTS)
WaitForMultipleObjects ( /* Allows a large # of processes */


min (MAXIMUM_WAIT_OBJECTS, argc - 2 - iProc),


&hProc [iProc], TRUE, INFINITE);


/* Result files sent to std output using "cat." */
for (iProc = 0; iProc < argc - 2; iProc++) {


if (GetExitCodeProcess(hProc [iProc], &ExCode) && ExCode==0) {
/* Pattern was detected -- List results. */


if (argc > 3) _tprintf (_T ("%s:\n"), argv [iProc + 2]);
fflush (stdout); /* Multiple processes use stdout. */
_stprintf (CommandLine, _T ("%s%s"),


_T ("cat "), ProcFile [iProc].TempFile);


</div>
<span class='text_page_counter'>(40)</span><div class='page_container' data-page=40>

33


CloseHandle (ProcessInfo.hThread);
}


CloseHandle (hProc [iProc]);


DeleteFile (ProcFile [iProc].TempFile);
}


free (ProcFile);
free (hProc);
return 0;
}


<b>4 2 Thuật toán s p xếp trộn ng a u ng </b>



#include "EvryThng.h"


#define DATALEN 56 /* Key: 8 bytes; Data: 56 bytes. */
#define KEYLEN 8


typedef struct _RECORD {


CHAR Key [KEYLEN]; TCHAR Data [DATALEN];
} RECORD;


#define RECSIZE sizeof (RECORD)
typedef RECORD * LPRECORD;


typedef struct _THREADARG { /* Thread argument */
DWORD iTh; /* Thread number: 0, 1, 2, ... */
LPRECORD LowRec; /* Low record */


LPRECORD HighRec; /* High record */
} THREADARG, *PTHREADARG;


static int KeyCompare (LPCTSTR, LPCTSTR);


static DWORD WINAPI ThSort (PTHREADARG pThArg);
static DWORD nRec; /* Total number of records to be sorted. */
static HANDLE * ThreadHandle;


int _tmain (int argc, LPTSTR argv [])
{



HANDLE hFile;


</div>
<span class='text_page_counter'>(41)</span><div class='page_container' data-page=41>

34


DWORD FsLow, nRead, LowRecNo, nRecTh, NPr, ThId, iTh;
BOOL NoPrint;


int iFF, iNP;


PTHREADARG ThArg;
LPTSTR StringEnd;


iNP = Options (argc, argv, _T ("n"), &NoPrint, NULL);
iFF = iNP + 1;


NPr = _ttoi (argv [iNP]); /* Number of threads. */


hFile = CreateFile (argv [iFF], GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);


FsLow = GetFileSize (hFile, NULL);


nRec = FsLow / RECSIZE; /* Total number of records. */
nRecTh = nRec / NPr; /* Records per thread. */


/* Allocate thread args and handle array


and space for the file. Read the complete file. */


ThArg = malloc (NPr * sizeof (THREADARG)); /* Thread args. */


ThreadHandle = malloc (NPr * sizeof (HANDLE));


pRecords = malloc (FsLow + sizeof (TCHAR));
ReadFile (hFile, pRecords, FsLow, &nRead, NULL);
CloseHandle (hFile);


LowRecNo = 0; /* Create the sorting threads. */
for (iTh = 0; iTh < NPr; iTh++) {


ThArg [iTh].iTh = iTh;


ThArg [iTh].LowRec = pRecords + LowRecNo;


ThArg [iTh].HighRec = pRecords + (LowRecNo + nRecTh);
LowRecNo += nRecTh;


</div>
<span class='text_page_counter'>(42)</span><div class='page_container' data-page=42>

35


for (iTh = 0; iTh < NPr; iTh++) /* Run all sort threads. */
ResumeThread (ThreadHandle [iTh]);


WaitForSingleObject (ThreadHandle [0], INFINITE);


for (iTh = 0; iTh < NPr; iTh++) CloseHandle (ThreadHandle [iTh]);


StringEnd = (LPTSTR) pRecords + FsLow;
*StringEnd = '\0';


if (!NoPrint) printf ("\n%s", (LPCTSTR) pRecords);
free (pRecords);



free (ThArg);


free (ThreadHandle);
return 0;


} /* End of _tmain. */


static VOID MergeArrays (LPRECORD, LPRECORD);
DWORD WINAPI ThSort (PTHREADARG pThArg)
{


DWORD GrpSize = 2, RecsInGrp, MyNumber, TwoToI = 1;
LPRECORD First;


MyNumber = pThArg->iTh;
First = pThArg->LowRec;


RecsInGrp = pThArg->HighRec - First;


qsort (First, RecsInGrp, RECSIZE, KeyCompare);


while ((MyNumber % GrpSize) == 0 && RecsInGrp < nRec) {
/* Merge with the adjacent sorted array. */


WaitForSingleObject (


ThreadHandle [MyNumber + TwoToI], INFINITE);
MergeArrays (First, First + RecsInGrp);



RecsInGrp *= 2;
GrpSize *= 2;
TwoToI *= 2;
}


</div>
<span class='text_page_counter'>(43)</span><div class='page_container' data-page=43>

36


return 0; /* Suppress a warning message. */
}


static VOID MergeArrays (LPRECORD p1, LPRECORD p2)
{


DWORD iRec = 0, nRecs, i1 = 0, i2 = 0;
LPRECORD pDest, p1Hold, pDestHold;


nRecs = p2 - p1;


pDest = pDestHold = malloc (2 * nRecs * RECSIZE);
p1Hold = p1;


while (i1 < nRecs && i2 < nRecs) {


if (KeyCompare ((LPCTSTR) p1, (LPCTSTR) p2) <= 0) {
memcpy (pDest, p1, RECSIZE);


i1++; p1++; pDest++;
}


else {



memcpy (pDest, p2, RECSIZE);
i2++; p2++; pDest++;


}
}


if (i1 >= nRecs) memcpy (pDest, p2, RECSIZE * (nRecs - i2));
else memcpy (pDest, p1, RECSIZE * (nRecs - i1));


memcpy (p1Hold, pDestHold, 2 * nRecs * RECSIZE);
free (pDestHold);


return;
}


<b> ài tập </b>


<b> ài tập 1 Viết chư ng trình hi n th t t cả các thơng tin về tiến trình và luồng c a m t tiến </b>


</div>
<span class='text_page_counter'>(44)</span><div class='page_container' data-page=44>

37


<b>Ch ng 5 Các ch vụ của Win ows </b>
<b>1 Tổng quan về ch vụ trên Win ows </b>


Các d ch v c a Windows, an đầu được gọi là các d ch v NT, cung c p khả năng
quản lý đ i h i các chư ng trình theo ki u server phải được ch y trên d ng l nh, ho c vào
thời đi m h th ng khởi đ ng, trước khi t c người d ng nào đăng nhập, và cũng c th
thực hi n t m dừng, khôi ph c, kết th c Các d ch v được đưa ra nh m đáp ng yêu cầu này



Đ quản lý các d ch v ch ng ta c th d ng công c Service Control Manager đượ
cung c p sẵn ởi Windows, công c này s thực hi n a ước đ quản lý m t d ch v :


+ Gọi tới hàm main c a d ch v


+ Chuy n đ i từ hàm main sang hàm ServiceMain


+ Ghi các con tr quản lý đ c th đáp ng l i các l nh từ SCM


<b>2 Các thành phần của một ch vụ </b>
<b>2 1 Hàm main </b>


Hàm này được gọi ởi SCM, c nhi m v là khai áo d ch v với SCM và t đầu thực
hi n công vi c c a m t d ch v


<b>2 2 Hàm S rvic ain </b>


Hàm ServiceMain() là m t d ng tư ng tự như hàm main với các tham s tư ng tự, n
thực hi n các tác v chính c a m t d ch v


<b>2 3 iểm soát ch vụ qua các Han r </b>


Đ ki m soát d ch v , ch ng ta s d ng các hàm sau:
DWORD WINAPI HandlerEx (


</div>
<span class='text_page_counter'>(45)</span><div class='page_container' data-page=45>

38


LPVOID lpEventData,
LPVOID lpContext)



<b>3 V u ch vụ n giản trên Win ows </b>


#include "EvryThng.h"
#include "ClntSrvr.h"


#define UPDATE_TIME 1000 /* One second between updates. */


VOID LogEvent (LPCTSTR, DWORD, BOOL);


void WINAPI ServiceMain (DWORD argc, LPTSTR argv []);


VOID WINAPI ServerCtrlHandlerEx(DWORD, DWORD, LPVOID, LPVOID);
void UpdateStatus (int, int); /* Calls SetServiceStatus. */


int ServiceSpecific (int, LPTSTR *); /* Former main program. */
volatile static BOOL ShutDown = FALSE, PauseFlag = FALSE;
static SERVICE_STATUS hServStatus;


static SERVICE_STATUS_HANDLE hSStat; /* Handle to set status. */


static LPTSTR ServiceName = _T ("SocketCommandLineService");
static LPTSTR LogFileName = _T ("CommandLineServiceLog.txt");


/* Main routine that starts the service control dispatcher. */
VOID _tmain (int argc, LPTSTR argv [])


{


SERVICE_TABLE_ENTRY DispatchTable [] =
{



{ ServiceName, ServiceMain },
{ NULL, NULL }


};


StartServiceCtrlDispatcher (DispatchTable);
return 0;


}


</div>
<span class='text_page_counter'>(46)</span><div class='page_container' data-page=46>

39


{


DWORD i, Context = 1;


/* Set the current directory and open a log file, appending to
an existing file. */


/* Set all server status data members. */


hServStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
hServStatus.dwCurrentState = SERVICE_START_PENDING;
hServStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |


SERVICE_ACCEPT_SHUTDOWN |
SERVICE_ACCEPT_PAUSE_CONTINUE;


hServStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIF0C_ERROR;


hServStatus.dwServiceSpecificExitCode = 0;


hServStatus.dwCheckPoint = 0;


hServStatus.dwWaitHint = 2 * CS_TIMEOUT;


hSStat = RegisterServiceCtrlHandlerEx (ServiceName,
ServerCtrlHandler, &Context);


SetServiceStatus (hSStat, &hServStatus);


/* Start service-specific work; generic work is complete. */
if (ServiceSpecific (argc, argv) != 0) {


hServStatus.dwCurrentState = SERVICE_STOPPED;
hServStatus.dwServiceSpecificExitCode = 1;


/* Server initialization failed. */
SetServiceStatus (hSStat, &hServStatus);
return;


}


/* We will only return here when the ServiceSpecific function
completes, indicating system shutdown. */


UpdateStatus (SERVICE_STOPPED, 0);
return;


</div>
<span class='text_page_counter'>(47)</span><div class='page_container' data-page=47>

40



void UpdateStatus (int NewStatus, int Check)
/* Set a new service status and checkpoint --
either specific value or increment. */
{


if (Check < 0) hServStatus.dwCheckPoint++;
else hServStatus.dwCheckPoint = Check;


if (NewStatus >= 0) hServStatus.dwCurrentState = NewStatus;
SetServiceStatus (hSStat, &hServStatus);


return;
}


/* Control handler function, invoked by the SCM to run */
/* in the same thread as the main program. */


/* The last three parameters are not used, and the pre-NT5 */
/* handlers would also work in this example. */


VOID WINAPI ServerCtrlHandlerEx (DWORD Control, DWORD EventType,
LPVOID lpEventData, LPVOID lpContext)


{


swsitch (Control) {


case SERVICE_CONTROL_SHUTDOWN:
case SERVICE_CONTROL_STOP:



ShutDown = TRUE; /* Set the global shutdown flag. */
UpdateStatus (SERVICE_STOP_PENDING, -1);
break;


case SERVICE_CONTROL_PAUSE:


PauseFlag = TRUE; /* Interrogated periodically. */
break;


case SERVICE_CONTROL_CONTINUE:
PauseFlag = FALSE;


break;


case SERVICE_CONTROL_INTERROGATE:
break;


default:


</div>
<span class='text_page_counter'>(48)</span><div class='page_container' data-page=48>

41


break;
}


UpdateStatus (-1, -1); /* Increment checkpoint. */
return;


}



/* This is the service-specific function, or "main," and is
called from the more generic ServiceMain.


In general, you can take any server, such as ServerNP.c, and
rename "main" as "ServiceSpecific"; putting code right here.
But some changes are required to update status. */


int ServiceSpecific (int argc, LPTSTR argv [])
{


UpdateStatus (-1, -1); /* Increment the checkpoint. */
/* ... Initialize system ... */


/* Be sure to update the checkpoint periodically. */


return 0;
}


<b>4 Quản các ch vụ của Win ows </b>


<b>4 1 Các ph ng pháp kiểm soát các ch vụ của Win ows </b>


Đ quản lý các d ch v c a Windows ta c hai cách: m t là d ng công c SCM, hai là
gõ trực tiếp các l nh trên d ng l nh


<b>4 2 V ụ Điều khiển các ch vụ của Win ows </b>


#include "EvryThng.h"


static SC_HANDLE hScm;


static BOOL Debug;


int _tmain (int argc, LPTSTR argv [])
{


BOOL Exit = FALSE;


</div>
<span class='text_page_counter'>(49)</span><div class='page_container' data-page=49>

42


DWORD i, LocArgc; /* Local argc. */


TCHAR argstr [MAX_ARG] [MAX_COMMAND_LINE];
LPTSTR pArgs [MAX_ARG];


/* Prepare the local "argv" array as pointers to strings. */
for (i = 0; i < MAX_ARG; i++) pArgs [i] = argstr [i];


/* Open the SC Control Manager on the local machine. */


hScm = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS);


/* Main command processing loop. */


_tprintf (_T ("\nWindows Service Management"));
while (!Exit) {


_tprintf (_T ("\nSM$"));


_fgetts (Command, MAX_COMMAND_LINE, stdin);
... Similar to JobShell ...



if (_tcscmp (argstr [0], _T ("create")) == 0) {
Create (LocArgc, pArgs, Command);
}


... Similarly for all commands ...
}


CloseServiceHandle (hScm);
return 0;


}


int Create (int argc, LPTSTR argv [], LPTSTR Command)
{


/* Create a new service as a "demand start" service:
argv [1]: service Name


argv [2]: display Name
argv [3]: binary executable */
SC_HANDLE hSc;


</div>
<span class='text_page_counter'>(50)</span><div class='page_container' data-page=50>

43


hSc = CreateService (hScm, argv [1], argv [2],


SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
Executable, NULL, NULL, NULL, NULL, NULL);



return 0;
}


/* Delete a service -- argv [1]: ServiceName to delete. */


int Delete (int argc, LPTSTR argv [], LPTSTR Command)
{


SC_HANDLE hSc;


hSc = OpenService (hScm, argv [1], DELETE);
DeleteService (hSc);


CloseServiceHandle (hSc);
return 0;


}


/* Start a named service -- argv [1]: service name to start. */
int Start (int argc, LPTSTR argv [], LPTSTR Command)
{


SC_HANDLE hSc;


TCHAR WorkingDir [MAX_PATH + 1];
LPTSTR pWorkingDir = WorkingDir;


LPTSTR argvStart [] = {argv [1], WorkingDir};



GetCurrentDirectory (MAX_PATH + 1, WorkingDir);


hSc = OpenService(hScm, argv [1], SERVICE_ALL_ACCESS);
/* Start the service with one arg, the working directory. */


/* Note: The service name agrees, by default, with the name */
/* associated with the handle, hSc, by OpenService. */
/* But, the ServiceMain function does not verify this. */
StartService (hSc, 2, argvStart);


</div>
<span class='text_page_counter'>(51)</span><div class='page_container' data-page=51>

44


return 0;
}


/* Control a named service. argv [1]: service name to control.
argv [2]: Control command: stop, pause, resume, interrogate. */
static LPCTSTR Commands [] =


{"stop," "pause," "resume," "interrogate," "user"};
static DWORD Controls [] = {


SERVICE_CONTROL_STOP, SERVICE_CONTROL_PAUSE,


SERVICE_CONTROL_CONTINUE, SERVICE_CONTROL_INTERROGATE,
128};


int Control (int argc, LPTSTR argv [], LPTSTR Command)
{



SC_HANDLE hSc;


SERVICE_STATUS ServiceStatus;
DWORD dwControl, i;


BOOL Found = FALSE;


for (i= 0; i < sizeof (Controls)/sizeof (DWORD) && !Found; i++)
Found = (_tcscmp (Commands [i], argv [2]) == 0);


if (!Found) {


_tprintf (_T ("\nIllegal Control Command %s"), argv [1]);
return 1;


}


dwControl = Controls [i - 1];
hSc = OpenService(hScm, argv [1],


SERVICE_INTERROGATE | SERVICE_PAUSE_CONTINUE |
SERVICE_STOP | SERVICE_USER_DEFINED_CONTROL |
SERVICE_QUERY_STATUS);


ControlService (hSc, dwControl, &ServiceStatus);


</div>
<span class='text_page_counter'>(52)</span><div class='page_container' data-page=52>

45


printf (_T ("Status from QueryServiceStatus\n"));
printf (_T ("Service Status\n"));



... Print all other status information ...
}


if (hSc != NULL) CloseServiceHandle (hSc);
return 0;


}


<b> ài tập </b>


</div>
<span class='text_page_counter'>(53)</span><div class='page_container' data-page=53>

46


<b>Ch ng 6 Lập trình Sock t </b>


<b>1 hái niệm sock ts trên Win ows </b>


Socket: là m t thực th logic đ i di n cho kết n i gi a các máy tính trên m t h th ng
m ng T t cả các truyền thông gi a các máy tính trên m t h th ng m ng được thực hi n
thông qua socket C hai mô hình lập trình m ng: mơ hình client/server và mơ hình peer 2
peer m ng ngang hàng


Theo mơ hình client/server:


Server: mở m t d ch v ng cách t o ra m t đ i tượng ServerSocket với tham s là đ a
chỉ c ng đ kết n i, sau đ nhận kết n i từ phía client ng cách s d ng hàm accept , l y
các luồng d li u vào/ra c a client đ thực hi n truyền d li u, thực hi n các x lý cần thiết,
trả kết quả cho client và đ ng kết n i tới client, d ch v kết th c


<b>2 Các hàm sock ts ph a s rv r </b>



Các hàm socket phía server mà ch ng ta cần quan t m gồm c :
int bind (


SOCKET s,


const struct sockaddr *saddr,
int namelen);


int listen (SOCKET s, int nQueueSize);
SOCKET accept (


SOCKET s,


LPSOCKADDR lpAddr,
LPINT lpAddrLen);


<b>V ụ </b>


struct sockaddr_in SrvSAddr; /* Server address struct. */
struct sockaddr_in ConnectAddr;


SOCKET SrvSock, sockio;
...


SrvSock = socket (AF_INET, SOCK_STREAM, 0);
SrvSAddr.sin_family = AF_INET;


SrvSAddr.sin_addr.s_addr = htonl (INADDR_ANY);
SrvSAddr.sin_port = htons (SERVER_PORT);


bind (SrvSock, (struct sockaddr *) &SrvSAddr,
sizeof SrvSAddr);


listen (SrvSock, 5);


</div>
<span class='text_page_counter'>(54)</span><div class='page_container' data-page=54>

47


sockio = accept (SrvSock,


(struct sockaddr *) &ConnectAddr, &AddrLen);
... Receive requests and send responses ...


shutdown (sockio);
closesocket (sockio);


<b>3 Các hàm sock ts ph a c i nt </b>


Các hàm socket phía client cần phải quan t m là:
int connect (


SOCKET s,


LPSOCKADDR lpName,
int nNameLen);


int send (
SOCKET s,


const char * lpBuffer,
int nBufferLen,


int nFlags);
Ví d :


SOCKET ClientSock;
...


ClientSock = socket (AF_INET, SOCK_STREAM, 0);
memset (&ClientSAddr, 0, sizeof (ClientSAddr));
ClientSAddr.sin_family = AF_INET;


ClientSAddr.sin_addr.s_addr = inet_addr (argv [1]);
ClientSAddr.sin_port = htons (SERVER_PORT);
ConVal = connect (ClientSock,


(struct sockaddr *) &ClientSAddr,
sizeof (ClientSAddr));


<b>4 ng ụng mang n giản </b>
<b>4.1 Ph a s rv r </b>


#define _NOEXCLUSIONS
#include "EvryThng.h"


#include "ClntSrvr.h" /* Defines request and response records. */


</div>
<span class='text_page_counter'>(55)</span><div class='page_container' data-page=55>

48


/* Server's socket address structure. */


struct sockaddr_in ConnectSAddr; /* Connected socket. */


WSADATA WSStartData; /* Socket library data structure. */


typedef struct SERVER_ARG_TAG { /* Server thread arguments. */
volatile DWORD number;


volatile SOCKET sock;
volatile DWORD status;


/* Explained in main thread comments. */
volatile HANDLE srv_thd;


HINSTANCE dlhandle; /* Shared library handle. */
} SERVER_ARG;


volatile static ShutFlag = FALSE;
static SOCKET SrvSock, ConnectSock;


int _tmain (DWORD argc, LPCTSTR argv [])
{


/* Server listening and connected sockets. */
BOOL Done = FALSE;


DWORD ith, tstatus, ThId;


SERVER_ARG srv_arg [MAX_CLIENTS];
HANDLE hAcceptTh = NULL;


HINSTANCE hDll = NULL;



/* Initialize the WSA library, Ver 2.0, although 1.1 will work. */
WSAStartup (MAKEWORD (2, 0), &WSStartData);


/* Open command library DLL if specified on command line. */
if (argc > 1) hDll = LoadLibrary (argv [1]);


/* Initialize thread arg array. */


for (ith = 0; ith < MAX_CLIENTS; ith++) {
srv_arg [ith].number = ith;


srv_arg [ith].status = 0; srv_arg [ith].sock = 0;


</div>
<span class='text_page_counter'>(56)</span><div class='page_container' data-page=56>

49


}


/* Follow standard server socket/bind/listen/accept sequence. */
SrvSock = socket (AF_INET, SOCK_STREAM, 0);


SrvSAddr.sin_family = AF_INET;


SrvSAddr.sin_addr.s_addr = htonl ( INADDR_ANY );
SrvSAddr.sin_port = htons ( SERVER_PORT );
bind (SrvSock, (struct sockaddr *) &SrvSAddr,
sizeof SrvSAddr);


listen (SrvSock, MAX_CLIENTS);


/* Main thread becomes listening/connecting/monitoring thread. */


/* Find an empty slot in the server thread arg array. */


/* status values: 0 -- slot is free; 1 -- thread stopped;
2 -- thread running; 3 -- stop entire system. */
while (!ShutFlag) {


for (ith = 0; ith < MAX_CLIENTS && !ShutFlag; ) {
if (srv_arg [ith].status==1 || srv_arg [ith].status==3) {
/* Thread stopped, normally or by shutdown request. */
WaitForSingleObject (srv_arg[ith].srv_thd INFINITE);
CloseHandle (srv_arg[ith].srv_thd);


if (srv_arg [ith].status == 3) ShutFlag = TRUE;
else srv_arg [ith].status = 0;


/* Free thread slot. */
}


if (srv_arg [ith].status == 0 || ShutFlag) break;
ith = (ith + 1) % MAX_CLIENTS;


if (ith == 0) Sleep (1000);
/* Break the polling loop. */


/* Alternative: use an event to signal a free slot. */
}


/* Wait for a connection on this socket. */


/* Separate thread so we can poll the ShutFlag flag. */



</div>
<span class='text_page_counter'>(57)</span><div class='page_container' data-page=57>

50


while (!ShutFlag) {


tstatus = WaitForSingleObject (hAcceptTh, CS_TIMEOUT);
if (tstatus == WAIT_OBJECT_0) break;


/* Connection made. */
}


CloseHandle (hAcceptTh);


hAcceptTh = NULL; /* Prepare for next connection. */
}


_tprintf (_T ("Server shutdown. Wait for all srvr threads\n"));
/* Terminate the accept thread if it is still running.


* See the Web site for more detail on this shutdown logic. */
if (hDll != NULL) FreeLibrary (hDll);


if (hAcceptTh != NULL) TerminateThread (hAcceptTh, 0);
/* Wait for any active server threads to terminate. */


for (ith = 0; ith < MAX_CLIENTS; ith++)
if (srv_arg [ith].status != 0) {


WaitForSingleObject (srv_arg[ith].srv_thd, INFINITE);
CloseHandle (srv_arg[ith].srv_thd);



}


shutdown (SrvSock, 2);
closesocket (SrvSock);
WSACleanup ();
return 0;


}


static DWORD WINAPI AcceptTh (SERVER_ARG * pThArg)
{


/* Accepting thread that allows the main thread to poll the */
/* shutdown flag. This thread also creates the server thread. */
LONG AddrLen, ThId;


AddrLen = sizeof (ConnectSAddr);


</div>
<span class='text_page_counter'>(58)</span><div class='page_container' data-page=58>

51


(struct sockaddr *) &ConnectSAddr, &AddrLen);
/* A new connection. Create a server thread. */
pThArg->status = 2;


pThArg->srv_thd =


(HANDLE) _beginthreadex (NULL, 0, Server, pThArg, 0, &ThId);
return 0; /* Server thread remains running. */



}


static DWORD WINAPI Server (SERVER_ARG * pThArg)
/* Server thread function. Thread created on demand. */
{


/* Each thread keeps its own request, response,
and bookkeeping data structures on the stack. */
/* ... Standard declarations from serverNP omitted ... */
SOCKET ConnectSock;


int Disconnect = 0, i;


int (*dl_addr)(char *, char *);


char *ws = " \0\t\n"; /* White space. */


GetStartupInfo (&StartInfoCh);
ConnectSock = pThArg->sock;
/* Create a temp file name. */


sprintf (TempFile, "%s%d%s", "ServerTemp",
pThArg->number, ".tmp");


while (!Done && !ShutFlag) { /* Main command loop. */


Disconnect = ReceiveRequestMessage (&Request, ConnectSock);
Done = Disconnect || (strcmp (Request.Record, "$Quit") == 0)
|| (strcmp (Request.Record, "$ShutDownServer") == 0);
if (Done) continue;



/* Stop this thread on "$Quit" or "$ShutDownServer". */
hTmpFile = CreateFile (TempFile,


GENERIC_READ | GENERIC_WRITE,


</div>
<span class='text_page_counter'>(59)</span><div class='page_container' data-page=59>

52


/* Check for a DLL command. For simplicity, shared */
/* library commands take precedence over process
commands. First, extract the command name. */


i = strcspn (Request.Record, ws); /* Length of token. */
memcpy (sys_command, Request.Record, i);


sys_command [i] = '\0';


dl_addr = NULL; /* Will be set if GetProcAddress succeeds. */
if (pThArg->dlhandle != NULL) { /* Try server "in process." */
dl_addr = (int (*)(char *, char *))


GetProcAddress (pThArg->dlhandle, sys_command);
if (dl_addr != NULL) __try {


/* Protect server process from exceptions in DLL. */
(*dl_addr) (Request.Record, TempFile);


} __except (EXCEPTION_EXECUTE_HANDLER {
ReportError (_T ("Exception in DLL"), 0, FALSE);
}



}
}


if (dl_addr == NULL) { /* No in-process support. */
/* Create a process to carry out the command. */
/* ... Same as in serverNP ... */


}


/* ... Same as in serverNP ... */


} /* End of main command loop. Get next command. */


/* End of command loop. Free resources; exit from the thread. */


_tprintf (_T ("Shutting down server# %d\n"), pThArg->number);
shutdown (ConnectSock, 2);


</div>
<span class='text_page_counter'>(60)</span><div class='page_container' data-page=60>

53


pThArg->status = 1;


if (strcmp (Request.Record, "$ShutDownServer") == 0) {
pThArg->status = 3;


ShutFlag = TRUE;
}


return pThArg->status;


}


<b>4.2 Ph a c i nt </b>


#define _NOEXCLUSIONS /* Required to include socket definitions. */
#include "EvryThng.h"


#include "ClntSrvr.h" /* Defines request and response records. */
/* Message functions for request and response. */


/* ReceiveResponseMessage also prints the received messages. */
static DWORD SendRequestMessage (REQUEST *, SOCKET);
static DWORD ReceiveResponseMessage (RESPONSE *, SOCKET);


struct sockaddr_in ClientSAddr; /* Clients's socket address. */


int _tmain (DWORD argc, LPTSTR argv [])
{


SOCKET ClientSock = INVALID_SOCKET;
REQUEST Request; /* See ClntSrvr.h. */
RESPONSE Response; /* See ClntSrvr.h. */


WSADATA WSStartData; /* Socket library data structure. */
BOOL Quit = FALSE;


DWORD ConVal, j;


TCHAR PromptMsg [] = _T ("\nEnter Command> ");
TCHAR Req [MAX_RQRS_LEN];



TCHAR QuitMsg [] = _T ("$Quit");
/* Request: shut down client. */


TCHAR ShutMsg [] = _T ("$ShutDownServer");
/* Stop all threads. */


</div>
<span class='text_page_counter'>(61)</span><div class='page_container' data-page=61>

54


/* Initialize the WSA library, Ver 2.0, although 1.1 will work. */
WSAStartup (MAKEWORD (2, 0), &WSStartData);


/* Connect to the server. */


/* Follow the standard client socket/connect sequence. */
ClientSock = socket (AF_INET, SOCK_STREAM, 0);
memset (&ClientSAddr, 0, sizeof (ClientSAddr));
ClientSAddr.sin_family = AF_INET;


if (argc >= 2)


ClientSAddr.sin_addr.s_addr = inet_addr (argv [1]);
else


ClientSAddr.sin_addr.s_addr = inet_addr (DefaultIPAddr);
ClientSAddr.sin_port = htons (SERVER_PORT);


/* Defined as 1070. */
connect (ClientSock,



(struct sockaddr *) &ClientSAddr, sizeof (ClientSAddr));
/* Main loop to prompt user, send request, receive response. */
while (!Quit) {


_tprintf (_T ("%s"), PromptMsg);


/* Generic input, but command to server must be ASCII. */
_fgetts (Req, MAX_RQRS_LEN-1, stdin);


for (j = 0; j <= _tcslen (Req); j++)
Request.Record [j] = Req [j];


/* Get rid of the new line at the end. */


Request.Record [strlen (Request.Record) - 1] = '\0';
if (strcmp (Request.Record, QuitMsg) == 0 ||


strcmp (Request.Record, ShutMsg) == 0) Quit = TRUE;
SendRequestMessage (&Request, ClientSock);


ReceiveResponseMessage (&Response, ClientSock);
}


shutdown (ClientSock, 2); /* Disallow sends and receives. */
closesocket (ClientSock);


</div>
<span class='text_page_counter'>(62)</span><div class='page_container' data-page=62>

55


_tprintf (_T ("\n****Leaving client\n"));
return 0;



}


<b>5. Windows Sockets 2.0 </b>


Là phiên ản mới nh t c a Windows cho lập trình m ng theo mơ hình socket


<b> ài tập </b>


<b> ài tập 1 Viết chư ng trình client/server cho ph p client nhập vào m t x u, g i sang server, </b>


</div>
<span class='text_page_counter'>(63)</span><div class='page_container' data-page=63>

56


<b>Ch ng 7: Th viện iên kết ộng </b>


Các thư vi n liên kết đ ng Dynamic-link Li araries là m t trong các phần t quan trọng
nh t c a h điều hành Windows Hầu hết các thao tác truy cập đ a c ng trên Windows đều
được thực hi n ởi các chư ng trình ho c các file liên kết đ ng Cho đến thời đi m này ch ng
ta đã viết r t nhiều các chư ng trình và y giờ là l c ch ng ta xem x t vi c viết các thư vi n
liên kết đ ng R t nhiều nguyên t c trong vi c viết các chư ng trình cũng được áp d ng trong
vi c viết các thư vi n song c m t s thay đ i quan trọng.


<b>7.1. hái niệm và ứng ụng của th viện iên kết ộng </b>


Như các n th y m t chư ng trình trên Windows là m t file ch y thường t o ra m t
ho c m t s c a s chư ng trình và s d ng m t v ng l p thông đi p đ nhận các thông tin
input từ người d ng Các thư vi n liên kết đ ng thường không phải là các file ch y trực tiếp
và ch ng thường không nhận các thông đi p Ch ng thường là các file riêng i t ch a các
hàm c th được gọi ởi các chư ng trình và các thư vi n khác đ thực hi n m t công vi c c
th nào đ M t thư vi n liên kết đ ng thường được n p vào m t nhớ đ thực hi n khi m t


module chư ng trình khác gọi tới m t hàm trong thư vi n


Thuật ng liên kết đ ng dynamic link đề cập tới quá trình mà Windows s d ng đ
liên kết m t lời gọi hàm trong m t module chư ng trình với các hàm thực sự n m trong m t
thư vi n liên kết đ ng Các liên kết t nh được thực hi n khi trình iên d ch tiến hành ước liên
kết link các file o ject o j , các thư vi n run-time * li và s d ng m t chư ng trình iên
d ch tài nguyên đ t o thành m t file ch y exe Quá trình liên kết đ ng không di n ra vào l c
iên d ch và liên kết chư ng trình mà di n ra vào l c chư ng trình ch y


<b>7 2 Hệ thống th viện iên kết ộng của Win ows </b>


Các thư vi n Kernel32 dll, user32 dll và gdi32 dll, r t nhiều các file điều khi n khác
chẳng h n như key oard drv, system drv và mouse drv cũng như các trình điều khi n card
màn hình và máy in đều là các thư vi n liên kết đ ng Các thư vi n này đều alf các thư vi n
mà hầu hết các chư ng trình trên Windows đều s d ng


M t vài thư vi n liên kết đ ng chẳng h n như các font ch được gọi là các thư vi n tài
nguyên resource only Các thư vi n này chỉ ch a d li u thường là dưới d ng các tài
nguyên và khơng ch a mã chư ng trình Do đ m t trong các m c đích c a các thư vi n liên
kết đ ng là cung c p các hàm và các tài nguyên c th được s d ng ởi các chư ng trình
khác Trong các h điều hành ngày xưa ki u như DOS chỉ c h điều hành mới ch a các th
t c mà các chư ng trình khác c th gọi đến đ hoàn thành m t công vi c gì đ Trên
Windows quá trình m t module chư ng trình gọi tới m t hàm trong m t module chư ng trình
khác là r t thường xuyên B ng cách viết các Dll ch ng ta c thêm các mở r ng cho h điều
hành


M c d m t module thư vi n liên kết đ ng c th c t c phần tên mở r ng nào
chẳng h n như exe hay com nhưng phần tên mở r ng chu n c a các thư vi n liên kết đ ng
trên Windows là dll Chỉ c các thư vi n liên kết đ ng c phần tên mở r ng là dll mới được
tự đ ng n p vào nhớ ởi Windows các thư vi n c phần tên mở r ng khác s được n p


thông qua vi c gọi tới các hàm LoadLi rary ho c LoadLi raryEx


</div>
<span class='text_page_counter'>(64)</span><div class='page_container' data-page=64>

57


các hàm này vào m t thư vi n liên kết t nh * li sau đ thêm vào m i module chư ng trình
trong quá trình iên d ch các chư ng trình này Tuy nhiên cách tiếp cận đ s là lãng phí vì
m i chư ng trình s ch a các đo n mã gi ng nhau và h n n a nếu ch ng ta thay đ i m t hàm
nào đ trong thư vi n ch ng ta s phải liên kết l i t t cả các chư ng trình c s d ng thư vi n
đ Nhưng nếu ch ng ta cho t t cả các hàm đ vào m t thư vi n liên kết đ ng chẳng h n như
account dll chẳng h n thì s giải quyết được cả hai v n đề trên Chỉ c module cần thiết ch a
t t cả các mã c a các hàm được s d ng ởi t t cả các chư ng trình điều này s đ i h i ít
không gian đ a c ng h n và đồng thời đ i h i ít nhớ h n khi nhiều chư ng trình c ng ch y
đồng thời, h n n a ch ng ta c th thay đ i các cài đ t c a các hàm trong thư vi n mà không
cần thiết phải liên kết l i thư vi n với các chư ng trình


Các thư vi n liên kết đ ng cũng c th là cá sản ph m thư ng m i, hi n nay c r t nhiều
hãng chuyên cung c p các hàm thư vi n dành cho phát tri n m t lo i sản ph m phần mềm nào
đ chẳng h n như DirectX là m t tập các thư vi n liên kết đ ng dành cho vi c viết các
chư ng trình đồ họa cao c p


<b>Th viện một ời ngàn n wor , many m anings </b>


M t phần các nhầm lẫn đ i với các thư vi n liên kết đ ng là vi c s d ng c a thuật ng
thư vi n li rary trong m t s các khung cảnh khác nhau Bên c nh các thư vi n liên kết
đ ng ch ng ta c n n i đến các thư vi n đ i tượng và các thư vi n import


M t thư vi n đ i tượng là m t file c phần mở r ng là li ch a các đo n mã chư ng
trình s được thêm vào file exe trong quá trình liên kết t nh Chẳng h n trong VC++ thư vi n
đ i tượng run-time thường liên kết với các chư ng trình là li c li



M t thư vi n import là m t d ng đ c i t c a các file thư vi n đ i tượng Gi ng như các
thư vi n đ i tượng các thư vi n import c phần mở r ng là li và được s d ng ởi trình iên
d ch đ giải quyết các lời gọi hàm trong các chư ng trình c a ch ng ta viết ra Tuy nhiên các
thư vi n import này không ch a các mã chư ng trình Thay vào đ ch ng cung c p cho trình
liên kết các thông tin cần thiết đ thiết lập các ảng chuy n relocation ta le trong file exe đ
thực hi n các liên kết đ ng Các file kernel32 li , user32 li , gdi32 li đi k m với các trình
iên d ch c a Microsoft đều là các thư vi n import Nếu ch ng ta gọi tới m t hàm chẳng h n
nhưu Rectangle thì file gdi32 li s áo cho trình liên kết iết r ng đ là m t hàm trong thư
vi n liên kết đ ng gdi32 dll Thông tin này s được ch a trong file chư ng trình * exe đ
Windows c th thực hi n các liên kết đ ng khi chư ng trình c a ch ng ta được thực hi n


Các thư vi n đ i tượng và các thư vi n import đều được s d ng trong quá trình phát
tri n các chư ng trình Các thư vi n liên kết đ ng được s d ng trong quá trình chư ng trình
ch y M t thư vi n liên kết đ ng phải sẵn c trên đ a đ chư ng trình c th s d ng n khi
ch y Khi Windows cần n p m t module DLL trước khi ch y m t chư ng trình đ i h i s
d ng hàm trong n file thư vi n phải n m c ng thư m c với file exe, trong thư m c hi n thời,
trong thư m c system c a h điều hành ho c n m trong thư m c c trong iến môi trường
PATH c a h điều hành h điều hành s tiến hành tìm kiếm thư vi n theo th tự đ


<b>7.3. Các c tạo một th viện DLL </b>


</div>
<span class='text_page_counter'>(65)</span><div class='page_container' data-page=65>

58


Ch ng ta s t o m t m t thư vi n liên kết đ ng là edrli dll Easy drawing routine
Hàm thư vi n này s chỉ ch a m t hàm đ n giản đ thực hi n công vi c v ra m t x u trong
ng d ng demo c a ch ng ta


Đ t o ra m t thư vi n liên kết đ ng ch ng ta cần c m t cách tiếp cận khác so với cách
mà ch ng ta vẫn d ng đ viết các ng d ng VC++ ph n i t gi a các khái ni m workspace
và project M t project thường là m t ng d ng ho c m t thư vi n liên kết đ ng M t


workspace c th gồm nhiều project Cho đến thời đi m này ch ng ta mới chỉ viết các
workspace chỉ c 1 project Trong phần này ch ng ta s t o m t workspace c hai project,
m t cho vi c t o dll và m t cho vi c gọi tới file dll đ


Các ước t o ng d ng với Visual Studio NET 2003 như sau:


1. T o 1 Solution Dll1 chẳng h n r ng Blank Solution


2. Thêm m t project ch a file dll cho ng d ng chọn New  Project 
Win32 Project và gõ tên c a Project là SimpleDll


3. Trong h p tho i Application Setting chọn DLL Application Type và
chọn m c Empty


4. Thêm file mã nguồn cho Project và gõ n i dung c a file dll vào:


/*---


simpledll.h header file


---*/


#ifdef __cplusplus


#define EXPORT extern "C" __declspec (dllexport)


#else


#define EXPORT __declspec (dllexport)



#endif


EXPORT BOOL CALLBACK EdrCenterTextA (HDC, PRECT, PCSTR) ;
EXPORT BOOL CALLBACK EdrCenterTextW (HDC, PRECT, PCWSTR) ;


#ifdef UNICODE


#define EdrCenterText EdrCenterTextW


#else


#define EdrCenterText EdrCenterTextA


</div>
<span class='text_page_counter'>(66)</span><div class='page_container' data-page=66>

59


/*---


simpledll.c -- Easy Drawing Routine Library module


(c) Charles Petzold, 1998


---*/


#include <windows.h>


#include "simpledll.h"


int WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID
pvReserved)



{


return TRUE ;
}


EXPORT BOOL CALLBACK EdrCenterTextA (HDC hdc, PRECT prc, PCSTR
pString)


{


int iLength ;
SIZE size ;


iLength = lstrlenA (pString) ;


GetTextExtentPoint32A (hdc, pString, iLength, &size) ;
return TextOutA (hdc, (prc->right - prc->left - size.cx) / 2,
(prc->bottom - prc->top - size.cy) / 2,


pString, iLength) ;
}


EXPORT BOOL CALLBACK EdrCenterTextW (HDC hdc, PRECT prc, PCWSTR
pString)


{


</div>
<span class='text_page_counter'>(67)</span><div class='page_container' data-page=67>

60


iLength = lstrlenW (pString) ;



GetTextExtentPoint32W (hdc, pString, iLength, &size) ;
return TextOutW (hdc, (prc->right - prc->left - size.cx) / 2,
(prc->bottom - prc->top - size.cy) / 2,


pString, iLength) ;
}


5. T o m t Project Win32 Project, sau đ chọn ki u Project là
Application, t o file c cho ng d ng và gõ n i dung ng d ng vào như sau:


#include <windows.h>


#include "..\\SimpleDll\\simpledll.h"


LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;


int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)


{


static TCHAR szAppName[] = TEXT ("StrProg") ;
HWND hwnd ;


MSG msg ;


WNDCLASS wndclass ;


wndclass.style = CS_HREDRAW | CS_VREDRAW ;


wndclass.lpfnWndProc = WndProc ;


wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;


wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;


wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;


wndclass.lpszClassName = szAppName ;


if (!RegisterClass (&wndclass))
{


</div>
<span class='text_page_counter'>(68)</span><div class='page_container' data-page=68>

61


return 0 ;
}




hwnd = CreateWindow (szAppName, TEXT ("DLL Demonstration Program"),
WS_OVERLAPPEDWINDOW,


CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,


NULL, NULL, hInstance, NULL) ;


ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;




while (GetMessage (&msg, NULL, 0, 0))
{


TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}


return msg.wParam ;
}


LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM
wParam, LPARAM lParam)


{


HDC hdc ;


PAINTSTRUCT ps ;
RECT rect ;


switch (message)
{



case WM_PAINT:


hdc = BeginPaint (hwnd, &ps) ;


GetClientRect (hwnd, &rect) ;
EdrCenterText (hdc, &rect,


</div>
<span class='text_page_counter'>(69)</span><div class='page_container' data-page=69>

62




EndPaint (hwnd, &ps) ;
return 0 ;




case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;


}


return DefWindowProc (hwnd, message, wParam, lParam) ;
}


6. Đ t chế đ d ch là Project th hai ph thu c dependencies vào Project
th nh t và thư m c Output c ng t m c a hai Project là /Release


7. D ch và ch y chư ng trình



Ở đ y ch ng ta c hai phiên ản c a m t hàm trong thư vi n liên kết đ ng được s
d ng, điều này cho ph p d ng các hàm c h trợ Unicode trong trường hợp h th ng c h trợ
và ngược l i s d ng m t hàm không c Unicode, thường tên c a hàm s c thêm ch W nếu
c h trợ Unicode và A nếu không


Đồng thời ch ng ta cũng th y trong mã c a thư vi n c m t hàm DllMain, hàm này c
vai tr tư ng tự như hàm WinMain trong m t chư ng trình Tác d ng c a hàm DllMain là
khởi t o và thu hồi nhớ và nh ng th liên quan khác, ch ng ta s àn tới v n đề này ở cu i
chư ng, hi n t i chỉ cần return TRUE là n


Điều í n c n l i c l là ở đ nh danh EXPORT Các hàm trong m t thư vi n liên kết
đ ng được s d ng ởi các ng d ng khác phải được xu t kh u Điều này không liên quan tới
các v n đề thư ng m i thông thường mà chỉ là m t chỉ th đảm ảo trình iên d ch s thêm tên
hàm vào thư vi n import simpledll li đ trình liên kết c th đưa các thơng tin ph hợp vào
chư ng trình file * exe đ c th n p các thư vi n dll khi chư ng trình ch y Đ nh danh
EXPORT c n ao gồm chỉ đ nh lớp ch a __declspec dllexport và m t chỉ th tiền x lý if
extern C đ đề ph ng trường hợp file header được iên d ch theo ki u C++ Điều này ngăn
ch n trình iên d ch kh i các l i tr ng tên c a các hàm C++ và cho ph p các thư vi n liên kết
đ ng c th được s d ng ởi cả các chư ng trình C và C++


<b>Điểm vào và iểm thoát của th viện Entry an Exit Point) </b>


Hàm DllMain được gọi đến khi thư vi n liên kết đ ng lần đầu tiên được n p vào nhớ
đ thực hi n và khi n kết th c nhi m v lo i kh i nhớ Tham s đầu tiên c a hàm
DllMain là handle tới instance c a thư vi n Nếu như thư vi n c s d ng các tài nguyên đ i
h i m t handle instance chẳng h n như các h p tho i , ch ng ta nên lưu l i hInstance vào
m t iến toàn c c Tham s cu i c ng c a hàm DllMain được d trự dành cho h th ng s
d ng



</div>
<span class='text_page_counter'>(70)</span><div class='page_container' data-page=70>

63


n p nhiều lần và ch y đồng thời trên Windows M i lần chư ng trình được n p n được xem
như là m t tiến trình process riêng r


Giá tr c a tham s fdwReason ng DLL_PROCESS_ATTACH chỉ ra r ng thư vi n
liên kết đ ng đã được ánh x vào v ng đ a chỉ c a m t tiến trình Đ y là m t đầu m i cho
ph p thư vi n thực hi n t c khởi t o nào đ i h i được ph c v cho các yêu cầu tiếp theo
c a tiến trình Các khởi t o ki u này c th là c p phát nhớ chẳng h n Trong thời gian tiến
trình đang ch y, DllMain được gọi với m t tham s DLL_PROCESS_ATTACH chỉ m t lần
trong cả thời gian tồn t i c a process đ B t c m t tiến trình nào khác s d ng c ng file
DLL s gọi đến hàm DllMain với m t giá tr tham s DLL_PROCESS_ATTACH


Nếu như vi c khởi t o là thành công DllMain s trả về m t giá tr khác 0, giá tr trả về là
0 s làm cho Windows khơng ch y chư ng trình


Nếu giá tr c a fdwReason ng DLL_PROCESS_DETACH thì c ngh a là chư ng
trình khơng cần file DLL n a, và đ y là m t c h i đ thư vi n thực hi n các công vi c dọn
d p c a n Trên các h điều hành 32 it c a Windows điều này không thực sự cần thiết
nhưng là m t th i quen lập trình t t


Tư ng tự khi hàm DllMain được gọi với m t giá tr tham s là
DLL_THREAD_ATTACH thì c ngh a là m t tiến trình s d ng thư vi n đã t o ra m t luồng
thread mới Khi luồng kết th c Windows l i gọi tới hàm DllMain với tham s là
DLL_THREAD_DETACH Cũng c th xảy ra trường hợp Windows thực hi n lời gọi tới
hàm DllMain với giá tr c a tham s fdwReason ng DLL_THREAD_DETACH mà không
thực hi n lời gọi với giá tr DLL_THREAD_ATTACH trước đ nếu như thư vi n liên kết
đ ng được g n với m t tiến trình sau khi luồng đã được t o ra


Luồng vẫn tồn t i khi hàm DllMain được gọi đến với tham s


DLL_THREAD_DETACH N thậm chí c th g i các thông đi p trong tiến trình Nhưng
các luồng khơng nên s d ng hàm PostMessage vì luồng c th kết th c trước khi thơng
đi p đến đích


Chư ng trình đ test thư vi n liên kết đ ng là m t chư ng trình đ n giản và là m t
Project khác thu c lo i Win32 Application Ch ng ta c th đ các file c a 2 Project vào
c ng m t thư m c ho c riêng r trong 2 thư m c


Trong quá trình d ch chư ng trình file simpledll dll và simpledll li s được sinh ra
trước, file simpledll li s được tự đ ng liên kết với chư ng trình th nghi m và file
simpledll dll s được n p vào nhớ khi chư ng trình ch y Cần ch ý là chư ng trình
usedll exe không ch a mã c a hàm s d ng trong thư vi n, mã c a hàm chỉ được n p vào
nhớ khi chư ng trình ch y


Vi c include file simpledll h cũng gi ng như ch ng ta include file windows h, liên kết
với file simpledll li cũng tư ng tự như liên kết với file user32 li và liên kết với file
simpledll dll cũng gi ng như chư ng trình liên kết với file user32 dll


</div>
<span class='text_page_counter'>(71)</span><div class='page_container' data-page=71>

64


m t file dll đồng thời, nhưng Windows s đ ng vai tr lá ch n đ ngăn ch n các can thi p lẫn
nhau gi a các ng d ng này


Nhiều tiến trình c th chia s c ng m t m t đo n mã trong m t thư vi n liên kết đ ng
Tuy nhiên d li u được s đ ng ởi m t thư vi n DLL s là khác nhau với các tiến trình khác
nhau M i tiến trình c m t không gian đ a chỉ d li u c a riêng n đ ch a các d li u c th
s d ng đến ởi file DLL Chia s nhớ gi a các tiến trình đ i h i m t s kỹ thuật khác mà
ch ng ta s àn tới trong phần tiếp theo


<b>7.4 Chia s ộ nh gi a các th viện iên kết ộng </b>



Windows cô lập các ng d ng s d ng c ng m t thư vi n liên kết đ ng đồng thời Tuy
nhiên đôi khi đ y không phải là m t lựa chọn thích hợp Ch ng ta c th mu n viết m t thư
vi n DLL ch a m t v ng nhớ nào đ c th được chia s ởi nhiều ng d ng, ho c gi a các
instance c a c ng m t ng d ng Điều này liên quan tới vi s d ng nhớ chia s , hay chính
xác là m t file ánh x nhớ memory-mapped file).


Ch ng ta s khảo sát m t chư ng trình c tên là strprog String Program và thư vi n
được s d ng là strli string li rary Strli ch a 3 hàm mà strprog c th gọi tới Và m t
trong s các hàm c a strli s s d ng m t hàm call- ack được đ nh ngh a trong strprog.


Strli là m t thư vi n liên kết đ ng ch a và làm vi c với m t x u t i đa 256 ký tự X u
được chuy n thành d ng ký tự hoa và ki m soát trong v ng nhớ chia s c a strli Strprog
c th s d ng 3 hàm c a thư vi n Strli đ c ng, x a và nhận được t t cả các x u hi n t i từ
strli Chư ng trình strprog c hai m c menu đ lựa chọn là Enter và Delete cho ph p người
d ng nhập các x u đ thực hi n vi c c ng và x a các x u Strprog s in ra giá tr t t cả các
x u hi n đang n m ch a trong thư vi n


Các hàm được đ nh ngh a trong thư vi n Strli gồm c :
EXPORT BOOL CALLBACK AddString (pStringIn)
EXPORT BOOL CALLBACK DeleteString (pStringIn)


EXPORT int CALLBACK GetStrings (pfnGetStrCallBack, pParam)


Hàm th nh t s chuy n các x u thành d ng ký tự hoa và thêm vào danh sách các x u
c a thư vi n Giá tr trả về c a hàm là TRUE khác 0 nếu như thành công và FALSE 0 nếu
như xảy ra l i: ho c x u c đ dài ng 0 ho c không c p phát được nhớ ho c đã s d ng
hết 256 x u c a nhớ


Hàm th hai s thực hi n x a m t x u kh i danh sách các x u c a thư vi n nếu khớp


và nếu c nhiều x u khớp thì chỉ x u đầu tiên x a Kết quả trả về c a hàm là TRUE nếu
x a thành công và FALSE nếu x u cần x a c đ dài ng 0 ho c khơng tìm th y


Hàm th a là hàm s d ng đ li t kê các x u đang c trong thư vi n, hàm này s d ng
m t tham s là m t hàm call- ack ch a trong chư ng trình s d ng hàm Hàm này phải được
đ nh ngh a trong chư ng trình s d ng thư vi n như sau:


EXPORT BOOL CALLBACK GetStrCallBack (PSTR pString, PVOID pParam)


</div>
<span class='text_page_counter'>(72)</span><div class='page_container' data-page=72>

65


T t nhiên ở đ y ch ng ta cũng s d ng hai phiên ản cho m i hàm, ANSI và Unicode
version.


<b>7.5 Các vấn ề khác về th viện iên kết ộng </b>


Tôi đã từng đề cập trong phần đầu c a chư ng này là các thư vi n liên kết đ ng không
nhận các thông đi p Tuy nhiên m t thư vi n liên kết đ ng c th gọi tới hàm GetMessage và
PeekMessage Các thông đi p mà thư vi n l y về từ hàng đợi thông đi p qua các hàm này
thực sự là các thông đi p c a các chư ng trình gọi tới các hàm c a thư vi n N i chung thư
vi n làm vi c thay m c cho chư ng trình gọi n – m t qui luật chi ph i hầu hết các hàm c a
Windows mà m t thư vi n c th gọi tới


M t thư vi n liên kết đ ng c th n p các tài nguyên chẳng h n như các i u tượng
chư ng trình, các x u và các ảnh itmap từ file thư vi n ho c từ các file c a chư ng trình gọi
tới thư vi n đ Các hàm n p tài nguyên đ i h i m t handle tới instance Nếu như thư vi n s
d ng handle tới instance c a riêng n được truyền cho thư vi n qua vi c gọi tới hàm DllMain
đ khởi t o n thì thư vi n c th nhận được các tài nguyên từ file riêng c a n Đ n p các
tài nguyên từ chư ng trình gọi tới các hàm c a thư vi n, đ i h i handle tới instance c a
chư ng trình gọi hàm



Vi c khai áo các lớp c a s chư ng trình và t o ra c a s chư ng trình trong m t thư
vi n đ i h i m t s th thuật Cả c u tr c lớp c a s và hàm CreateWindow ho c
CreateWindowEx đều đ i h i m t handle tới m t instance c a chư ng trình M c d ch ng ta
c th s d ng hande c a thư vi n trong vi c t o ra các lớp c a s và c a s chư ng trình, các
thơng đi p c a s vẫn đi qua hàng đợi thông đi p c a chư ng trình gọi tới thư vi n khi thư
vi n t o ra c a s chư ng trình Nếu như n cần phải t o ra các lớp c a s và các c a s
chư ng trình trong m t thư vi n thì t t nh t là nên s d ng handle tới instance c a chư ng
trình gọi tới hàm thư vi n


Vì các thơng đi p cho các h p tho i modal được nhận ên ngoài v ng l p thông đi p
c a chư ng trình nên ch ng ta c th t o ra m t h p tho i modal trong m t thư vi n ng
cách gọi tới hàm DialogBox Handle tới instance c th là c a thư vi n ho c tham s
hwndParent c a hàm DialogBox c th đ t ng NULL


<b>Các th viện khơng c import </b>


Thay vì đ Windows thực hi n vi c liên kết đ ng khi chư ng trình lần đầu tiên được
n p vào nhớ ch ng ta c th liên kết m t chư ng trình với m t thư vi n khi chư ng trình
đang ch y


Chẳng h n ch ng ta mu n gọi tới hàm Rectangle như sau:
Rectangle (hdc, xLeft, yTop, xRight, yBottom) ;


Điều này s làm cho chư ng trình được liên kết tới thư vi n gdi32 li khi iên d ch đ
l y đ a chỉ c a hàm Rectangle Ch ng ta c th gọi tới hàm Rectangle theo m t cách khác:


typedef BOOL (WINAPI * PFNRECT) (HDC, int, int, int, int) ;
khai áo hai iến:



HANDLE hLibrary ;
PFNRECT pfnRectangle ;


</div>
<span class='text_page_counter'>(73)</span><div class='page_container' data-page=73>

66


hLibrary = LoadLibrary (TEXT ("GDI32.DLL"))


pfnRectangle = (PFNPRECT) GetProcAddress (hLibrary, TEXT ("Rectangle"))
Và y giờ c th gọi tới hàm Rectangle:


pfnRectangle (hdc, xLeft, yTop, xRight, yBottom) ;
FreeLibrary (hLibrary) ;


M c d kỹ thuật s d ng thư vi n liên kết đ ng theo ki u này không làm tăng hi u quả
s d ng c a hàm Rectangle nhưng n l i là m t cách hi u quả trong trường hợp mà ch ng ta
không iết tên c a thư vi n cho tới khi chư ng trình ch y chẳng h n đ i với hàm
AlphaBlend chẳng h n


Đo n mã trên s d ng hai hàm LoadLi rary và FreeLi rary Windows ki m soát các
iến đếm tham chiếu tới t t cả các module thư vi n Hàm LoadLi rary s làm cho iến đếm
tham chiếu tới các thư vi n được n p tăng lên 1 Biến đếm tham chiếu cũng được tăng lên khi
Windows n p m t chư ng trình c s d ng thư vi n FreeLi arary s làm cho iến đếm này
giảm đi 1, trường hợp m t instance c a m t chư ng trình s d ng thư vi n lo i kh i nhớ
biến đếm tham chiếu cũng giảm đi 1 đ n v Khi iến đếm tham chiếu này ng 0 Windows s
lo i thư vi n kh i nhớ vì l c đ thư vi n không c n cần thiết n a


<b>Các th viện ch chứa tài nguyên </b>


B t c hàm này trong m t thư vi n liên kết đ ng mà m t chư ng trình trên Windows và
các thư vi n khác c th gọi tới đều phải được export Tuy nhiên m t thư vi n liên kết đ ng


c th không nh t thiết phải ch a t c m t hàm export nào Vậy các thư vi n đ ch a gì
C u trả lời là các tài nguyên


Chẳng h n ch ng ta làm vi c trên m t ng d ng Windows cần m t s các ảnh itmap
Thông thường ch ng ta s li t kê các ảnh này trong file k ch ản tài nguyên và n p ch ng vào
nhớ với hàm LoadBitmap Nhưng c l ch ng ta mu n c m t s tập ảnh, m i tập cho m t
đ ph n giải c a màn hình hình thường được s d ng với Windows Giải pháp khả d nh t là
ch a các tập ảnh khác nhau này vào các file khác nhau vì m t người d ng chỉ cần tới m t tập
các ảnh này trên đ a c ng Và các file này được gọi là các file thư vi n chỉ ch a tài nguyên


Hình 21-5 cho ch ng ta th y cách th c t o ra m t thư vi n chỉ ch a tài nguyên được gọi
là itli dll ch a 9 ảnh itmap File itli rc ch a t t cả các ảnh này và gán cho m i ảnh m t
s Đ t o ra file itli dll ch ng ta cần c 9 ảnh c tên lần lượt là itmap1 mp,
itmap2 mp, , itmap9 mp Ch ng ta c th s d ng các ảnh đi k m với đ a CD c a
quy n sách đ d ng


<b> ài tập </b>


</div>
<span class='text_page_counter'>(74)</span><div class='page_container' data-page=74>

67


<b>Tài iệu tham khảo </b>


<i>[1] Lê H u Đ t NXB Giáo d c </i>


<i>[2] Charles Petzold. Programming Windows, fifth edition. Microsoft Press. 1998. </i>


</div>
<span class='text_page_counter'>(75)</span><div class='page_container' data-page=75>

68


<b>Đề thi tham khảo </b>
<b>Đề số 1 </b>



<b> ài số 1 </b>


Cho Dialog sau:


Biết r ng các ID c a các control c a Dialog trên như sau: các ID c a các Edit Text tư ng ng
với các Static Text Canh a, Canh , Canh c lần lượt là: ID_CANHA, ID_CANHB,
ID_CANHC, ID c a Static 1 là ID_KQKT, ID c a Static 2 là ID_DTCV, ID c a các Button
Kiem tra và Thoat là ID_KIEMTRA, ID_THOAT Hãy viết hàm x lý cho Dialog trên sau
cho khi nh n vào n t Kiem tra thì chư ng trình s ki m tra xem a s nguyên được nhập và 3
Edit text tư ng ng c là 3 c nh c a 1 tam giác hay không, kết quả ki m tra được thông áo
qua Static 1 Trong trường hợp là 3 c nh c a 1 tam giác hãy tính và hi n th chu vi, di n tích
c a tam giác qua Static 2 và khi người d ng nh n vào n t Thoat s kết th c Dialog


<b> ài số 2 </b>


a) Hãy trình ày đưa ra d ng đ n giản nh t c a m t hàm x lý thông đi p c a s
chư nh trình hàm Window Proc


b) Giả s chư ng trình chỉ c m t m c menu Help, trong đ c 2 m c menu con là
Contents và A out, hãy viết hàm x lý thông đi p c a s chư ng trình sao cho khi
người d ng chọn các m c trong menu Help chư ng trình s hi n th các thông áo
hàm Message Box tư ng ng và khi người d ng nh n chu t trái vào 1 v trí trên màn
hình, hãy in ra m t thông áo về tọa đ chu t t i v trí đ hàm TextOut


<b>Đề số 2 </b>
<b> ài số 1 </b>


</div>
<span class='text_page_counter'>(76)</span><div class='page_container' data-page=76>

69



Các điều khi n XA, YA, XB, YB, XC, YC là tọa đ 3 đỉnh trên m t phẳng tọa đ
nguyên Khi nh n n t Tinh chu vi hãy tính chu vi c a tam giác t o thành ởi 3 đỉnh A, B,
C và hi n th lên IDC_KQ Nh n Thoat đ th at kh i h p tho i và nh n Tinh dien tich s
tính di n tích và hi n th như trong phần tính chu vi


<b> ài số 2 </b>


a) Hãy trình ày đưa ra d ng đ n giản nh t c a m t hàm x lý thông đi p c a s cho
m t h p tho i


b) Hãy viết hàm WndProc cho m t chư ng trình c h th ng menu gồm 1 m c File,
trong đ c các m c con với các ch c năng sau: Menu1, Menu2, khi người d ng nh n
vào các m c này chỉ cần đưa ra thông áo đ n giản, m c Exit đ thoát kh i chư ng
trình


<b>Đề số 3 </b>
<b> ài số 1 </b>


Viết hàm x lý h p tho i sau:


</div>
<span class='text_page_counter'>(77)</span><div class='page_container' data-page=77>

70


<b> ài số 2 </b>


a) Hãy trình ày đưa ra d ng đ n giản nh t c a m t hàm x lý thông đi p c a s cho
m t h p tho i


</div>

<!--links-->

×