96
  BGIAO THÔNG VN TI TRƢỜNG ĐẠI HC HÀNG HI  BMÔN: KHOA HO    C MA   Y TI   NH  KHOA: CÔNG NGHTHÔNG TIN BÀI GING LP TRÌNH WINDOWS TÊN HC PHN : Lp trình Windows MÃ HC PHN : 17214 TRÌNH ĐỘ ĐÀO TO : ĐẠI HC CHÍNH QUY DÙNG CHO SV NGÀNH : CÔNG NGHTHÔNG TIN HI PHÕNG - 2010 

Bai Giang Lap Trinh Windows

Embed Size (px)

Citation preview

Page 1: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 1/96

 

BỘ GIAO THÔNG VẬN TẢITRƢỜNG ĐẠI HỌC HÀNG HẢI 

BỘ MÔN: KHOA HO   C MA  Y TI NH 

KHOA: CÔNG NGHỆ THÔNG TIN 

BÀI GIẢNG 

LẬP TRÌNH WINDOWS 

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

MÃ HỌC PHẦN : 17214 

TRÌNH ĐỘ ĐÀO TẠO : ĐẠI HỌC CHÍNH QUY DÙNG CHO SV NGÀNH : CÔNG NGHỆ THÔNG TIN 

HẢI PHÕNG - 2010 

Page 2: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 2/96

Bài giảng môn học: Lâ   p tr  nh Windows 

i

Tên học phần: Lập trình Windows  Loại học phần: 2

Bộ môn phụ trách giảng dạy: Khoa học Máy tính 

Khoa phụ trách: CNTT

Mã học phần: 17214  Tổng số TC: 3

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

Điều kiện tiên quyết: 

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 tru  c dƣ   liê  u 

Mục tiêu của học phần: 

-  Cung cấp các kiến thức cơ bản về lâ    p tr nh trƣ  c quan trên hê  điêu ha nh Windows 

-  Cung cấp ca c kiến thƣ  c về truy câ    p va  can thiê    p va o ca c t hành phần ca h điềuhành Windows 

Nội dung chủ yếu 

Các kiến thức về thao tác với file và thƣ mc , cơ sơ   dƣ   liê  u registry , các luồng , tiếntrình, dch v, các thƣ vin liên kết đng và lập trình sockets trên Windows .

Nội dung chi tiết của học phần:

TÊN CHƢƠNG MỤC 

PHÂN PHỐI SỐ TIẾT 

TS LT TH/Xemina BT KT

Chƣơng I. Các khái niệm cơ bản 3 0 0 01.1. Giới thiu về môi trƣơ   ng lâ    p tr nh trênWindows1.1.1. Cơ   sơ   về hê  điều ha nh Windows 1.1.2. Các phiên bản ca hê  điều ha nhWindows1.1.3. Vai tro  cu  a Windows trên thi  trƣơ   ng phầnmềm 1.2. Thƣ viê  n Win32 và Win641.2.1. Win32 API

1.2.2. Win64 API1.3. Giơ   i thiê  u về bô   công cu   Visual Studio2005

1

1

1

Chƣơng II. Hê   thô ng file va   thƣ mục 4 4 0

2.1. Truy câ    p va  sƣ  du  ng hê  thống file trên môitrƣơ   ng Windows 2.1.1. Hê  thống file va  thƣ mu  c cu  a Windows 2.1.2. Các thao tác với file và thƣ mc trênWindows2.1.3. Các vấn đề liên quan tới Unicode 2.2. Các ví d về thao ta c vơ   i file 2.2.1. To file và xư lý các li liên quan  

2

1

2

1

Page 3: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 3/96

Bài giảng môn học: Lâ   p tr  nh Windows 

ii

TÊN CHƢƠNG MỤC 

PHÂN PHỐI SỐ TIẾT 

TS LT TH/Xemina BT KT

2.2.2. Copy file2.2.3. Hiê n thi  danh sa ch ca c file trong thƣ mu  chiê  n thơ   i 

2.3. Quản lý file và thƣ mc nâng cao  2.3.1. Con tro  file 2.3.2. Truy câ    p tơ   i ca c thuô  c t nh ca file vàthƣ mu  c 

1 1

Chƣơng III. Hê   thô  ng cơ sơ   dƣ    liê   u Registry 4 6 0 1

3.1. Khái nim và vai tr ca CSDL Registry  3.1.1. Các kha, các hive 3.1.2. Các kiu d liu 3.2. Quản lý CSDL Registry  3.2.1. Thay đô  i kho

 a 

3.2.2. Thêm mơ   i kho  a 3.2.3. Liê   t kê ca c kho a 3.3. Can thiê    p Windows qua Registry 3.3.1. Thay đô  i giao diê  n 3.3.2. Thay đô  i ca c thiết lâ    p đối vơ   i ca c ô  đ  a 3.3.3. Thay đô  i ca c thiết lâ    p vơ   i ngƣơ   i du  ng 

1

1

2

1

2

3

1Chƣơng IV. Quản l các tiến trình và lung 4 6 0 1

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. To tiến trình 4.2.2. Kêt thu  c va  thoa t kho  i mô  t tiến tr nh 4.2.3. Các thao tác với biến môi trƣờng caWindows4.2.4. Ví d : Ghi nhâ   t ky  thơ   i gian thƣ  c hiê  nca các tiến trình 4.3. Quản lý luồng (thread) trên Windows4.3.1. Các khái nim cơ bản 4.3.2. Mô h nh Boss  / Worker va  ca c mô h nhkhác 

4.3.3. Bô   nhơ   da nh cho luông 4.3.4. Đ ƣu tiên và các trng thái ca luồng  4.4. Mô  t sô v  du   về tiến tr nh va  luồng 4.4.1. Tìm kiếm song song với các tiến trình 4.4.2. Thuâ   t toa n săp xếp trô  n bằng đa luồng 

2

1

1

2

2

2

1

Chƣơng V. Các dch vụ của Windows 4 6 0 1

5.1. Tô ng quan về di  ch vu   trên Windows 5.2. Các thành phần ca mt dch v 5.2.1. Hàm main()5.2.2. Hàm ServiceMain()5.2.3. Kiê m soa t di  ch vu   qua các Handler  5.3. Ví du: dch v đơn giản trên Windows 

1

1

2

2

Page 4: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 4/96

Bài giảng môn học: Lâ   p tr  nh Windows 

iii

TÊN CHƢƠNG MỤC 

PHÂN PHỐI SỐ TIẾT 

TS LT TH/Xemina BT KT

5.4. Quản lý các dch v ca Windows  5.4.1. Các phƣơng pháp kim soát các dch vca Windows 

5.4.2. Ví d : Điêu khiê n ca c di  ch vu   cu  aWindows

2 2

1

Chƣơng VI. Lâ   p tr  nh ma   ng vơ   i Sockets 4 4 0 0

6.1. Khái nim 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 dng mng đơn gia n 6.4.1. Phía server  6.4.2. Phía client 6.5. Windows Sockets 2.0

0,50,50,52

0,5

10,50,52

Chƣơng VII. Thƣ viê   n liên kê t đô   ng 4 4 0 0

7.1. Khái nim và ứng dng ca thƣ vin liênkết đô  ng 7.2. Hê  thống thƣ viê  n DLL cu  a Windows  7.3. Các bƣớc to mt thƣ vin DLL  7.3.1. To thƣ viê  n DLL 7.3.2. Viết ƣ  ng du  ng go   i tơ   i thƣ viê  n DLL 

112

0,512,5

Nhiệm vụ của sinh viên : 

Tham dự các buổi thuyết trình ca giáo viên, tự học, tự làm bài tập do giáo viên giao,

tham dự các bài kim tra đnh kỳ và cuối kỳ. 

Tài liệu học tập :

-  Lê Hƣ  u Đa   t. Lâ    p tr nh Windows. NXB Gia o du  c.

-  Charles Petzold. Programming Windows, fifth edition. Microsoft Press. 1998.

-  Johnson M. Hart. Windows System Programming Third Edition. Addison WesleyProfessional. 2004.

Hình thức và tiêu chuẩn đánh giá sinh viên:

-  Hình thức thi cuối kỳ : Thi vấn đáp. -  Sinh viên phải đảm bảo các điều kin theo Quy chế ca Nhà trƣờng và ca B 

Thang điểm: Thang điểm chữ A, B, C, D, F 

Điểm đánh giá học phần: Z = 0,3X + 0,7Y. 

Page 5: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 5/96

Bài giảng môn học: Lâ   p tr  nh Windows 

i

MỤC LỤC 

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

CHƢƠNG 1: CC KHI NIM CƠ BẢN ............................................................................... 2

1. Giới thiu 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 bản ca h điều hành Windows ............................................................. 2

1.3 Vai tr ca Windows trên th trƣờng phần mềm .................................................... 3

2. Thƣ vin Win32 và Win64 .............................................................................................. 3

2.1 Win32 API .............................................................................................................. 3

2.2 Win64 API .............................................................................................................. 4

3. Các bƣớc phát trin ứng dng 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 gia n................................................................................. 5

3.3 Quản lý các thông đip ......................................................................................... 14

3.4 Vng lp xư lý thông đip .................................................................................... 17

Bài tập: .............................................................................................................................. 20

CHƢƠNG 2: HÊ   THÔ  NG FILE VA  THƢ MU  C .................................................................... 21

1. Truy câ    p va  sƣ  du  ng hê  thống file trên môi trƣơ   ng Windows ....................................... 21

2. Các ví d về thao tác với file ......................................................................................... 21

2.1 Serialization .......................................................................................................... 21

2.2 Cài đt mt lớp Serializable.................................................................................. 24

3. Quản lý file và thƣ mc nâng cao .................................................................................. 40

Bài tập: .............................................................................................................................. 40

CHƢƠNG 3: HÊ   THÔ  NG CSDL REGISTRY ........................................................................ 41

1. Khái nim và vai tr ca CSDL Registry ...................................................................... 41

1.1 Các kha, các hive ................................................................................................ 41

1.2 Các kiu d liu .................................................................................................... 42

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

2.1 Thay đô  i kho a ....................................................................................................... 43

2.2 Thêm mơ   i kho  a ..................................................................................................... 43

2.3 Liê   t kê các kha .................................................................................................... 44

3. Can thiê    p Windows qua Registry .................................................................................. 44

3.1 Thay đô  i giao diê  n ................................................................................................ 44

3.2 Thay đô  i ca c thiết lâ    p đối vơ   i ca c ô  đ  a ................................................................ 44

Page 6: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 6/96

Bài giảng môn học: Lâ   p tr  nh Windows 

ii

3.3 Thay đô  i ca c thiết lâ    p vơ   i ngƣơ   i du  ng .................................................................. 44

Bài tập: .............................................................................................................................. 44

CHƢƠNG 4: QUẢN L CC TIN TRÌNH VÀ LUNG .................................................... 45

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

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

2.1. To tiến trình........................................................................................................ 46

2.2. Kết thc và thoát khi mt tiến trình ................................................................... 47

2.3. Các thao tác với biến môi trƣờng ca Windows .................................................. 47

2.4. Ví d: Ghi nhâ   t ky  thơ   i gian thƣ  c hiê  n cu  a ca c tiên tr nh .................................... 47

3. Quản lý luồng (thread) trên Windows ........................................................................... 49

3.1. Các khái nim cơ bản........................................................................................... 49

3.2. Mô h nh Boss / Worker va  ca c mô h nh kha c ........................................................ 49

3.3. Bô   nhơ   da nh cho luồng ........................................................................................ 49

3.4. Đ ƣu tiên và các trng thái ca luồng ................................................................ 50

4. Mô   t số v  du   vê tiên tr nh va  luồng ............................................................................... 50

4.1. Tìm kiếm song song với các tiến trình................................................................. 50

4.2. Thuâ   t toa n săp xếp trô  n bằng đa luồng ................................................................ 52

Bài tập: .............................................................................................................................. 55

CHƢƠNG 5: CC DCH V CA WINDOWS .................................................................... 56

1. Tô ng quan về di  ch vu   trên Windows ............................................................................. 56

2. Các thành phần ca mt dch v ................................................................................... 56

2.1 Hàm main() ........................................................................................................... 56

2.2 Hàm ServiceMain() ............................................................................................... 56

2.3 Kiê m soát dch v qua các Handler ...................................................................... 56

3. Ví du: dch v đơn giản trên Windows .......................................................................... 57

4. Quản lý các dch v ca Windows ................................................................................ 60

4.1 Các phƣơng pháp kim soát các dch v ca Windows ........................................ 60

4.2 Ví d : Điêu khiê n ca c di  ch vu   cu  a Windows ....................................................... 60

Bài tập: .............................................................................................................................. 64

CHƢƠNG 6: L  P TRI  NH SOCKET....................................................................................... 65

1. Khái nim sockets trên Windows .................................................................................. 65

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

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

4. Ưng dng mang đơn giản .............................................................................................. 66

Page 7: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 7/96

Bài giảng môn học: Lâ   p tr  nh Windows 

iii

4.1 Phía server ............................................................................................................. 66

4.2 Phía client ............................................................................................................. 72

5. Windows Sockets 2.0 .................................................................................................... 74

Bài tập: .............................................................................................................................. 74

CHƢƠNG 7: THƢ VIÊ    N LIÊN KÊ  T ĐỘNG ......................................................................... 75

7.1. Khái nim và ứng dng ca thƣ vin liên kết đng .................................................... 75

7.2. H thống thƣ vin liên kết đng ca Windows .......................................................... 75

7.3. Các bƣớc to mt thƣ vin DLL ................................................................................. 76

7.4. Chia se  bô   nhơ   giƣ  a ca c thƣ viê  n liên kêt đô  ng.......................................................... 83

7.5. Các vấn đề khác về thƣ vin liên kết đng ................................................................. 84

Bài tập: .............................................................................................................................. 85

TÀI LIU THAM KHẢO ........................................................................................................ 86

ĐỀ THI THAM KHẢO ............................................................................................................ 87

Page 8: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 8/96

Bài giảng môn học: Lâ   p tr  nh Windows 

1

LỜI NÓI ĐẦU 

H điều hành Windows ca Microsoft là h điều hành đƣợ c cài đt nhiều nhất trên cácmáy PC hin nay. Sự phổ biến ca Windows và nền tảng phần cứng ca Intel dẫn tớ i sự cầnthiết phải có nhng hiu biết sâu về chúng, đc bit đối vớ i nhng lập trình viên. Mc đíchca học phần này là cung cấp cho học viên mt cái nhìn tổng quan, từ cơ bản tớ i chi tiết về các khía cnh ca lập trình trên h điều hành Windows, từ các chi tiết trong cấu trúc ca mtchƣơ ng trình tớ i các khái nim cấp cao về tiến trình, luồng, xư lý song song, thƣ vin DLL,lập trình Socket, can thip vào cơ sở d liu Registry ....

Tài liu này dựa trên nhng kinh nghim và nghiên cứu mà tác giả đã đc rt, thu thậptrong quá trình giảng dy môn học Lập trình C trên Windows, cng với sự tham khảo ca cáctài liu ca các đồng nghip , các tác giả trong và ngoài nƣớc , tƣ  điê n trƣ  c tuyến Wikipedia .Với bâ y chƣơng đƣợc chia thành các ch đề khác nhau từ ca c kha i niê  m cơ ba n cho tới cácthao tác vớ i h thống file, thƣ mc, h thống CSDL Registry, quản lý tiến trình và luồng, lậptrình quản lý dch v, lập trình socket, thƣ vin liên kết đng DLL… hy vọng sẽ cung cấp cho

các em sinh viên, các bn đc giả mt tài liu bổ ích . Mc d đã rất cố gắng song vẫn khôngtránh khi mt số thiếu st , hy vọng sẽ đƣợc các bn bè đồng nghip , các em sinh viên , các

 bn đc giả gp ý chân thành đ tôi c th hoàn thin hơn na tài liu này .

Xin gưi lời cảm ơn chân thành tới các bn bè đồng nghip và Ban ch nhim khoaCông ngh Thông tin đã to điều kin gip đỡ đ tài liu này c th hoàn thành.

 Hải phòng, tháng 06  năm 2010 

Tác giả 

Nguyê  n Hƣ   u Tuân 

Page 9: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 9/96

Bài giảng môn học: Lâ   p tr  nh Windows 

2

Chƣơng 1: Các khái niệm cơ bản 

Tài liu này đƣợc biên son đ cung cấp cho ngƣời ho  c nhng kiến thức cơ bản vế vicviết các chƣơng trình sư dng giao din lập trình API trên môi trƣờng Win32. Ngôn ng đƣợcsư dng là ngôn ng C, hầu hết các trình biên dch C++ hin nay đều c th dch đƣợc cácchƣơng trình mẫu trình bày trong tài liu này. Hầu hết tất cả các thông tin đƣợc trình bàytrong tài liu này đều c th ứng dng cho bất cứ ngôn ng nào c th truy cập các hàm API,chẳng hn nhƣ Java, Assembly, và Visual Basic. 

Tài liu này đƣợc biên son không phải đ dy các bn đc giả lập trình bằng ngôn ngC, hoc dy chng ta sư dng bất cứ mt trình biên dch c th nào (chẳng hn nhƣ BorlandC++, Visual C++, …) tuy nhiên trong phần ph lc tôi sẽ dành mt cht đ cung cấp cho các

 bn mt số ch ý về mt số trình biên dch mà tôi đã sư dng. 

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

1.1 Cơ sở về hệ điều hành Windows 

H điều hành Windows là mt h điều hành dành cho ngƣời dng cuối (End User Operating System) với các tính năng cơ bản sau: đa nhim, giao din đồ họa, plug and play vàquan trọng nhất là Windows Interface Based - tức là giao din các chƣơng trình chy trênWindows đều c dng các cưa sổ. 

1.2 Các phiên bản của hệ điều hành Windows 

Do cách dng tiếng Anh và vic hiu tiếng Anh dẫn tới vic nhiều ngƣời hiu về các phiên bản ca h điều hành Windows chƣa chính xác. Ví d c bn cho rằng Windows XPProfessional Edition và Windows XP Home Edition là hai phiên  bản khác nhau ca h điềuhành Windows. Thực ra nhƣ vậy vừa đng li vừa không đng, đng là Windows XPProfessional Edition và Windows XP Home Edition là hai Edition khác nhau ca cng 1Version Windows XP, c lẽ sai là vì hiu từ Edition và Version sai. Version c nghĩa là mt

 phiên bản, thƣờng đi kèm với các số hiu ca phiên bản (1.0, 1.2. … 5.0) và thƣờng là mtthay đổi lớn đối với bả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 trc nền tảng ca h điều hành (tức là phần kernel ca h điều hành), hai làcập nhật các bản vá (patch) cho các li ca phiên bản trƣớc đ đối với tất cả các phần ca hđiều hành, ba là các phần mới ca h điều hành (c th là các ứng dng đi kèm hoc 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 NETframework hay các ứng dng nhƣ Windows Media Player, IE …).  

Cn Edition là ấn bản khác nhau ca cng mt phiên bản, các Edition thƣờng gắn vớicác yếu tố về đa lý, ngôn ng khác nhau (ví d nhƣ Compact Edition nghĩa là bản rt gọn,Standard Edition là bản chuẩn, Ultimate Edition là bản c các tính năng cao cấp nhất …). Đốivới h điều hành Windows các Edition khác nhau thƣờng phân bit bởi các tính năng cachng, do nhắm tới vic phc v các đối tƣợng khác nhau nên Microsoft b đi mt số tínhnăng không cần thiết và tăng thêm các tính năng mà đối tƣợng ngƣời dng hay dng ví dnhƣ bản Home Edition nhắm tới ngƣời dng gia đình nên các tính năng đồ họa, video, âmthanh phải tốt, cn bản Professional nhắm tới các ngƣời dng chuyên nghip c trình đ caonên các tính năng h thống sẽ cao hơn. 

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

Page 10: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 10/96

Bài giảng môn học: Lâ   p tr  nh Windows 

3

Windows 2.11Windows 3.0Windows 3.1xWindows For Workgroups 3.1Windows NT 3.1

Windows For Workgroups 3.11Windows 3.2 (released in Simplified Chinese only)Windows NT 3.5Windows NT 3.51Windows 95Windows NT 4.0Windows 98Windows 98 SEWindows 2000Windows MeWindows XPWindows XP 64-bit Edition 2003Windows Server 2003Windows XP Professional x64 EditionWindows Fundamentals for Legacy PCsWindows VistaWindows Home ServerWindows Server 2008Windows 7

Tất nhiên là mi Version trên li c nhiều Edition khác nhau. Phần nhân (Kernel –  Core) ca h điều hành luôn là phần quan trọng nhất ca mt h điều hành. Đối vớ i Windowsnhân gồm 3 thành phần: các dch v chy ở mức nhân (kernel-mode service, đ phân bit vớicác dch v chy ở mức ứng dng) gồm các thƣ vin chính ca h điều hành, các thƣ vinthực hin quản lý tiến trình, lập lch, quản lý vào ra d liu trên đĩa cứng, b nhớ. Phần 2 làcác thƣ vin làm vic với các phần cứng ở mức chung, phần 3 là các Diver. 

1.3 Vai trò của Windows trên th trƣờng phần mềm 

Do sự thống tr ca hãng Microsoft ni riêng và sự phổ biến gần nhƣ đc tôn ca hđiều hành Windows ni chung ở Vit Nam nên Windows đng vai tr hết sức quan trọng

trong vic phát trin phần mềm ở Vit Nam. Về bản chất các chƣơng trình đều phải thực hintrên mt nền tảng (platform) nhất đnh bao 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 dng, các lập trình viên cần quan tâm nhiều nhất tới h điều hànhmà ứng dng sẽ chy. 

2. Thƣ viện Win32 và Win64 

2.1 Win32 API

Win32 API hay thƣờng đƣợc viết tắt là Win32 là phiên bản 32 bit tƣơng ứng với h điềuhành 32 bit ca Windows. Win32 bao gồm các hàm đƣợc cài đt ca h thống, chẳng hn nhƣcác hàm trong h thống Win16 bit, dƣới dng các file thƣ vin DLL ca h thống. Lõi (core)ca Win32 là các file thƣ vin kernel32.dll, user32.dll và gdi32.dll. Win32 đầu tiên đƣợc đƣara cùng với h điều hành Windows NT. Phiên bản đầu tiên ca Win32 đƣợc phát hành cngvới h điều hành Windows 95 (gọi là Win32c - compatible), và sau này chỉ cn là Win32. 

Page 11: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 11/96

Bài giảng môn học: Lâ   p tr  nh Windows 

4

2.2 Win64 API

Win64 là phiên bản 64 bit ca thƣ vin Win32, là mt biến th dành cho các nền tảng 64 bit ca h điều hành Windows (ví d hin ti là AMD64 và IA-64). Cả hai phiên bản 32 và 64 bit ca mt ứng dng đều c th đƣợc biên dch từ mt mã chƣơng trình chung, mc d cmt số khác bit trong hai phiên bản này. Sự khác nhau cơ bản ca hai phiên bản là các contr đa chỉ ca Win32 là 32 bit, cn với Win64 là 64 bit. 

3. Các bƣớc phát triển ứng dụng trên Windows 

3.1 Chƣơng trình Win32 đơn giản nhất. 

 Nếu bn là mt ngƣời mới bắt đầu lập trình trên môi trƣờng Win32 thì thao tác đầu tiênmà bn cần phải làm đƣợc đ là dch mt chƣơ ng trình cơ   bản trên môi trƣờng Windows. Hãygõ đon chƣơng trình trên vào và nếu mọi thứ suôn sẻ bn sẽ c mt chƣơng trình đơn giảnnhất (vô nghĩa) trong số các chƣơng trình mà bn đã làm.  

Hãy nhớ là dch chƣơ ng trình này theo kiu dch mt chƣơng trình viết bằng ngôn ngC, 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 hin bằngcách đổi phần tên mở rng từ cpp thành c. Chẳng hn bn c th đt tên cho file chƣơ ng trìnhsau là test.c và bắt đầu làm vic. 

#include <windows.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

LPSTR lpCmdLine, int nCmdShow)

{

MessageBox(NULL, "Goodbye, cruel world!", "Note", MB_OK);

return 0;

}

 Nếu nhƣ chƣơng trình không làm vic bƣớc đầu tiên mà bn cần làm là đọc tất cả cácli (error) mà chƣơng trình báo lên và nếu nhƣ   bn không hiu ý nghĩa ca chng hãy tratrong bất cứ mt quyn sách dy lập trình hoc các sách hƣớng dẫn đi kèm với trình biên dchmà bn đang sư dng. Hãy chắc chắn là bn c đầy đ các file mà trình biên dch yêu cầu.Thật không may là tôi không th gip nhiều trong trƣờng hợp này vì các li ph thuc vào

trình biên dch và ngƣời sư dng (trong vic gây li cũng nhƣ sưa li). Bn c th nhận đƣợc mt vài cảnh  báo từ trình biên dch về vic chƣơ ng trình không

sư dng các tham số đƣợc cung cấp cng với hàm WinMain(). Nhƣng không sao điều quantrọng là bn dch chƣơng trình thành công và c mt chƣơng trình Win32 thực sự. Chng tasẽ phân tích các đon 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 ca mt 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 đon mã chƣơng trình sẽ đƣợc thựcthi. Các tham số ca hàm main gồm c: 

HINSTANCE hInstance

Page 12: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 12/96

Bài giảng môn học: Lâ   p tr  nh Windows 

5

Tham số này quản lý module chƣơng trình (file .exe trong b nhớ). H điều hành sưdng tham số này đ quản lý chƣơng trình khi thực hin. 

HINSTANCE hPrevInstance

Luôn là NULL đối với các chƣơng trình Win32. 

LPSTR lpCmdLine

Các tham số dng lnh ca chƣơng trình đƣợc truyền dƣới dng mt xâu. Không baogồm tên chƣơng trình. 

int nCmdShow

Mt số nguyên c th truyền cho hàm ShowWindow(). Chng ta sẽ bàn về tham sốnày sau.

Tham số hInstance đƣợc dng cho các công vic đi loi nhƣ np (load) các tài nguyênvà bất cứ tác v nào khác đƣợc thực hin theo kiu từng module cơ bản. Mt module là mt

file EXE hoc file DLL đƣợc np vào chƣơng trình ca bn. Đối với hầu hết (không phải tấtcả) các chƣơng trình đƣợc trình bày trong tài liu này, chỉ c mt module mà chng ta cầnquan tâm đ là file chƣơng trình (EXE). 

Các qui ƣớc gọi hàm 

WINAPI chỉ đnh qui ƣớc gọi hàm và đƣợc đnh nghĩa là _stdcall. Nếu nhƣ bn khônghiu ý nghĩa ca chng thì cũng không cần bận tâm nhiều vì chng không ảnh hƣởng tới tàiliu này chỉ cần nhớ là đây là mt điều cần thiết (kiu ca hàm WinMain() là int, nhƣng kiugọi hàm là WINAPI). 

Các kiu d liu Win32. Các bn sẽ thấy rằng rất nhiều từ kha thông thƣờng hoc các kiu d liu đề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ânvân. Vic chọn lựa sư dng cách nào thực sự ph thuc vào bn. Nếu bn thích sư dng char * hơn là LPSTR thì hãy sư dng cách đ nhƣng cần phải kim soát đƣợc vic sư dng camình (cần nắm rõ các kiu d liu trƣớc khi thay chng bằng mt kiu khác).  

Bn chỉ cần nắm vng mt số nguyên tắc và sẽ hiu ý nghĩa ca 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 b qua.Cn nếu bn không hiu con tr là gì thì c lẽ bn nên học li về C hoc b qua chng và tiếp

tc. Tiếp đến là LPCSTR: long pointer const là mt hằng xâu, tức là mt xâu không th thay

đối, ngoài ra gia hai kiu LPSTR và LPCSTR cn c th c thêm mt ch T nhƣng nếu bnkhông c ý đnh sư dng các font Unicode trong chƣơng trình thì n cũng chẳng c ý nghĩa gìđc bit. 

3.2 Chƣơng tr  nh cƣ   a sô  đơn gia n 

Ví d: chƣơng tr nh gồm 1 cƣ  a sô  đơn gia n trên Windows 

Đôi khi mo   i ngƣơ   i ho  i nhau trong khi ho   cha t vơ   i nhau bằng phần mềm IRC la  “La mthế na o đê  ta  o ra mô   t cƣ  a sô  ?”. Tôi e rằng điều na y hoa n toa n không pha i la  mô   t điêu đơngiản. Không kho  khi ba  n biêt m nh đang la m g  nhƣng co  kha   t nhƣ  ng điều ba  n cần biết đê  to ra mt cưa sổ , và nhng điều đ hoàn toàn c th giải thích bằng mt đon văn bản ngắnhoă  c khoa ng mô   t va i phu  t chat bằng IRC.

Page 13: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 13/96

Bài giảng môn học: Lâ   p tr  nh Windows 

6

Tôi luôn muôn la m trƣơ   c va  ho  c ky   ca ng sa u v  thê ơ   đây tôi se   tr nh ba y đoa  n ma   chƣơng tr nh ta  o ra mô   t cƣ  a sô  trƣơ   c va  gia 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 đip cn li 

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;

 //Step 1: Registering the Window Classwc.cbSize = sizeof(WNDCLASSEX);

Page 14: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 14/96

Bài giảng môn học: Lâ   p tr  nh Windows 

7

wc.style = 0;

wc.lpfnWndProc = WndProc; /* hàm xư lý thông đip 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

// To ra mt th nghim ca lớp cưa sổ cho ứng dng

hwnd = CreateWindowEx(

WS_EX_CLIENTEDGE,

g_szClassName,

"The title of my window",

WS_OVERLAPPEDWINDOW,

CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,

NULL, NULL, hInstance, NULL);

if(hwnd == NULL)

{

MessageBox(NULL, "Window Creation Failed!", "Error!",

MB_ICONEXCLAMATION | MB_OK);

Page 15: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 15/96

Bài giảng môn học: Lâ   p tr  nh Windows 

8

return 0;

}

// Hin th cưa sổ 

ShowWindow(hwnd, nCmdShow);

UpdateWindow(hwnd);

 // Step 3: The Message Loop

// Step 3: To vng lp xư lý thông đip  

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

{

TranslateMessage(&Msg);

DispatchMessage(&Msg);

}

return Msg.wParam;

}

Hình 1 –  Cƣ  a sổ ca chƣơng trình khi chy 

Đây co  le   la  mô  t chƣơng tr nh windows đơn gia n nhât ma  ba  n co  thê  viết va  chƣ  c năngca chƣơng trình đơn giản là to ra mt cưa sổ cũng rất đơn giản . Bn nên gõ chƣơng trình và

 biên di  ch đê  cha  y thƣ  va  ha  y đa m ba o la  không co  lô  i g  xa y ra.

Bƣơ   c 1: Đăng ky   (Registering) lơ   p cƣ  a sô   (Window).

Mô   t lơ   p cƣ  a sô    (Window Class) chƣ  a ca c thông tin về kiê u cƣ  a sô  ,  bao gồm thu  tu  cWindow cu  a no    (th tc này kim soát cƣ  a sô  khi no  đƣơ   c ta  o ra va  đa  p ƣ  ng la   i ca c sƣ   kiê  nngƣơ   i du  ng ta c đô  ng lên cƣ  a sô  ), các icon lớn và nh ca cưa sổ , và màu nền ca cưa sổ. Theocách này bn c th đăng ký mt lớp và sau đ to ra bao nhiêu cưa sô  tu  y th ch ma  khôngcân ch  ro   tất ca  ca c thuô  c t nh đo  thêm mô   t lần na o nƣ  a . Hầu hết ca c thuô  c t nh ma  ba  n thiêtlâ    p trong lơ   p cƣ  a sô    (window) c th thay đổi đƣợc theo mt cách rất cơ bản (thô  mô  c) nếunhƣ ba  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 nim các lớp trongC++.

const char g_szClassName[] = "myWindowClass";

Biến trên lƣu tên cu  a lơ   p cƣ  a sô  cu  a chu  ng ta , chng ta sẽ sư dng n đ đăng ký lớpcƣ  a sô  cu  a chu  ng ta vơ   i hê   thống.

Page 16: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 16/96

Bài giảng môn học: Lâ   p tr  nh Windows 

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;

}

Đo  la  đoa  n ma   chƣơng tr nh chu  ng ta sƣ  du  ng trong ha m WinMain() đ đăng ky  lơ   p cƣ  asô  cu  a chu  ng ta . Chng ta sẽ điền đầy đ các thành viên ca cấu trc WNDCLASSEX và gọitơ   i ha m RegisterClassEx().

Các thành viên ca cấu trc ảnh hƣởng đến lớp cưa sổ gồm c :

cbSize: kích thƣớc ca cấu trc style: Class Style (CS_*), đ không nhầm lẫn với Window Style (WS_*). Thông thƣơ   ng

thuô  c t nh na y đƣơ   c ga n băng 0.

lpfnWndProc: con tro  tro  tơ   i thu  tu  c qua n ly  cƣ  a sô  cho lơ   p cƣ  a sô  na y.

cbClsExtra: Lƣơ   ng dƣ   liê  u thêm đƣơ   c  câp pha t trong bô   nhơ   cho mô  i cƣ  a sô  thuô  c loa   inày. Thông thƣơ   ng cu  ng đƣơ   c ga n bằng 0.

hInstance: Quản lý mt th nghim (instance) ca ứng dng (tham số đầu tiên cu  a ha mWinMain()).

hIcon: Icon lơ   n (thƣơ   ng la  32x32) hiê n th khi chng ta nhấn tổ hợp phím Alt+TAB.

Page 17: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 17/96

Bài giảng môn học: Lâ   p tr  nh Windows 

10

hCursor: Con tro  se   xuât hiê  n khi con tro  chuô   t di chuyê n qua vu  ng cƣ  a sô  cu  a chƣơngtrình.

hbrBackground: Tham sô sƣ  du  ng đê  thiết lâ    p mâu nên cu  a cƣ  a sô  .

lpszMenuName: tên cu  a ta i nguyên menu đƣơ   c sƣ  du  ng cho ca c cƣ  a sô  cu  a lơ   p .

lpszClassName: Tên đê  đi  nh danh lơ   p cƣ  a sô   

hIconSm: Icon nho   (16x16) hiê n thi  trên thanh task bar va  go c trên bên tra i cu  a cƣ  a sô  .

Bn không nên lo lắng nếu chƣa hiu về các thuc  tính này, chng sẽ đƣợc giải thích ở các phần tiếp theo ca tài liu này . Mô  t điều kha c cần pha i nhơ   la  không nên cố nhơ   nhƣ  ngthuô  c t nh na y. Tôi rât  t khi (không muôn no  i la  không bao giơ   ) nhơ   ca c thuô  c t nh cu  ng nhƣcác tham số ca các hàm , điều đo  hoa n toa n la  mô   t cố gắng la  ng ph  thơ   i gian va  công sƣ  c .

 Nếu nhƣ ba  n biết ca c ha m ba  n cần sƣ  du  ng trong mô   t chƣơng tr nh na o đo  , hãy tra trong cáctài liu help . Nêu ba  n không co  ca  c file help ha  y down chu  ng về , các file kiu này trên mngkhông hề thiếu . Cuôi cu  ng th  ba  n se   biêt ca c tham số cu  a ca c ha m ma  ba  n thƣơ   ng xuyên sƣ   dng.

Tiếp đến chu  ng ta go  i tơ   i ha m RegisterClassEx () và kim tra xem hàm   này c thànhcông hay không, nếu nhƣ ha m tra  về sai chu  ng ta se   hiê n thi  mô   t thông ba o thất ba   i va  dƣ  ngchƣơng tr nh.

Bƣơ   c 2: To ra cưa sổ chƣơng trình 

Khi đa   đăng ky  lơ   p cƣ  a sô  , chng ta c th to ra các cưa sổ trong chƣơng tr nh . Các bn nên tra các tham số ca hàm CreateWindowEx () ( bn luôn nên làm vậy khi làm vic vớicác hàm API mới), nhƣng tôi se   gia i th ch mô   t chu  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à kiu cưa sổ mở rng (extended), trongtrƣơ   ng hơ     p này tham số này đƣợc sư dng đ to thành mt đƣờng viền chìm bên trong xungquanh cƣ  a sô  . C th đt bằng 0 nếu chu ng ta muôn kha c . Cũng nên thay đổi các giá tr khácđ xem chng làm vic nhƣ thế nào.

Tiếp theo chu  ng ta cần co  tên lơ   p (g_szClassName), tham sô na y ba o cho hê   thống biếtloi cưa sổ mà chng ta muốn to ra . Vì chng ta muốn to ra mt cưa sổ từ lớp mà chng tavƣ  a đăng ky  nên chu  ng ta sƣ  du  ng tên cu  a lơ   p cƣ  a sô  đo  . Sau đo  chu  ng ta ch  ro   tên cu  a cƣ  asô  hoă  c tiêu đề (xâu ky  tƣ   ) sẽ xuất hin trong vai tr là tham số Caption hoc Title Bar ca

cƣ  a sô  cu  a chu  ng ta.

Page 18: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 18/96

Bài giảng môn học: Lâ   p tr  nh Windows 

11

Tham số chu  ng ta sƣ  du  ng WS_OVERLAPPEDWINDOW trong vai tro  tham sốWindow Style. C khá ít các tham số kiu này do đ bn nên kim tra và thay đổi giá tr cachng đ xem kết quả họat đng nhƣ thế nào . Chng ta sẽ bà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 va

 Y cu

 a go

 c trên bên tra

 i cu

 a cƣ

 a sô  va

 ca

 c k

 ch thƣơ 

 c da

 i rô  ng cu

 a no

 . Tôi đa

  thiết lâ    p gia

  

tr ca X và Y là CW _USEDEFAULT đê  windows tƣ   cho  n vi  tr  đê  đă   t cƣ  a sô  chƣơng tr nhkhi cha  y . Hãy nhớ l à bên trái ca màn hình là mt giá tr 0 ca X và n tăng dần khi sang

 phải. Đ nh cu  a ma n h nh tƣơng ƣ  ng vơ   i gia  tri   0 ca Y tăng dần theo chiều đi xuống . Các đơnv là các đim ảnh , là đơn v nh nhất mà màn hình c  thê  hiê n thi  đƣơ   c ta   i đô   phân gia i hiê  nti.

Tiếp theo (NULL, NULL, g_hInst, NULL) chng ta c mt handle quản lý cưa sổ chaca cưa sổ đƣợc sinh ra , mô  t handle qua n ly  menu , mô   t handle cho thê  nghiê  m cu  a ƣ  ng du  ngvà mt con tro  tro  tơ   i dƣ   liê  u cƣ  a sô  . Trong windows ca c cƣ  a sô  trên ma n h nh đƣơ   c săp xếptheo mô  t cấu tru  c phân cấp theo kiê u ca c cƣ  a sô  cha va  con . Khi chu  ng ta nh n thấy mô   t nu  t

trên mô   t cƣ  a sô  , nt đ là con và n đƣợc chứ a trong cƣ  a sô  la  cha cu  a no  . Trong v  du   na yca chng ta handle ca cưa sổ cha là NULL vì chng ta không c cưa sổ cha nào cả , đây la  cƣ  a sô  ch nh hoă  c cƣ  a sô  ơ   cấp cao nhất cu  a chu  ng ta . Menu cu  ng la  NULL v  chu  ng t a chƣac menu chƣơng trình nào . Handle da nh cho thê  nghiê  m cu  a chƣơng tr nh đƣơ   c ga n la  gia  tri   đƣơ   c truyền cho tham số đầu tiên cu  a ha m WinMain (). D liu cưa sổ (thƣơ   ng la  chu  ng tachă ng bao giơ   sƣ  du  ng chu  ng ) c th đƣợc sƣ  du  ng đê  gƣ  i ca c dƣ   liê  u kha c tơ   i cƣ  a sô  đangđƣơ   c ta  o ra va  cu  ng la  NULL.

 Nêu ba  n đang băn khoăn về gia  tri    NULL b  hiê m na y th  ha  y yên tâm v  no  đơn gia nchỉ là 0 (zero). Thƣ  c sƣ   trong C no  đƣơ   c đi  nh ngh  a la    ((void*)0) vì n đƣợc sư dng với các

con tro  . Vì thế cho nên bn c th sẽ gp các cảnh báo khi biên dch chƣơng trình nếu sư dng NULL cho ca c gia  tri  kiê u nguyên , ty thuc vào trình biên dch và cấp đ cảnh báo đƣợc  thiết lâ    p vơ   i tr nh biên di  ch. Bn c th b qua các cảnh báo hoc đơn giản là sư dng giá tr 0đ thay thế.

 Nguyên nhân số 1 mà mọi ngƣời không biết ti sao chƣơng trình ca mình li c li làdo ho   không kiê m tra ca  c gia  tri  tra  về cu  a lơ   i go   i ha m ma  ho   thƣ  c hiê  n trong chƣơng tr nhca mình. CreateWindow() sẽ trả về sai trong mt số trƣờng hợp ngay cả khi bn là mt lậptrình viên c nhiều kinh nghim , chỉ đơn giản bởi vì c rất n hiêu lô  i ma  chu  ng ta rất dê   ta  o rachng. Cho tơ   i khi ba  n ho  c đƣơ   c ca nh nhanh cho ng xa c đi  nh ca c lô  i kiê u nhƣ vâ  y , hãy tự chomình mt cơ hi đ c th tìm ra các li trong chƣơng trình , hãy luôn kim tra các giá tr tr ảvề khi go  i tơ   i ca c ha m.

if(hwnd == NULL)

{

MessageBox(NULL, "Window Creation Failed!", "Error!",

MB_ICONEXCLAMATION | MB_OK);

return 0;

}

Sau khi chu  ng ta đa   ta  o ra cƣ  a sô  va  kiê m tra đê  đa m ba o la   chng ta c mt handle hợplê   , chng ta sẽ hin th cưa sổ lên màn hình ca windows (hê  điêu ha nh ) bằng ca ch sƣ  du  ng

Page 19: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 19/96

Bài giảng môn học: Lâ   p tr  nh Windows 

12

tham sô cuôi cu  ng cu  a ha m WinMain () và sau đ cập nhật n đ đảm bảo là tự n đƣợc vẽ limô  t ca ch hơ     p lê   trên ma n h nh.

ShowWindow(hwnd, nCmdShow);

UpdateWindow(hwnd);

Tham sô nCmdShow la  tu  y cho  n , bn c th đơn giản gán n là SW _SHOWNORMALmô  i khi chu  ng ta la m viê  c vơ   i no  .Tuy nhiên sƣ  du  ng tham số đƣơ   c truyền va o hàm WinMain()sẽ to cơ hi cho các ngƣời dng sư dng chƣơng trình ca chng ta c th chỉ đnh họ muốnhoă  c không muốn cu  a sô  cu  a chu  ng ta bắt đầu vơ   i k ch thƣơ   c cƣ  a sô  lơ   n nhât hoă  c nho  nhất… Ba  n se   thấy ca c tu  y chọn này trong các tham số ca các shortcut ca tới các cưa sổ .

Bƣơ   c 3: Vng lp xư lý thông đip  

Đây ch nh la  tra i tim cu  a toa n bô   chƣơng tr nh , hâu hết nhƣ  ng thƣ  ma  chƣơng tr nh cu  achng 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ƣ  ha ng đơ   i thông điê    p cu  a ƣ  ng du  ng cu  a ba  n .Bât ky  thơ   i điê m na o ngƣơ   i du  ng di chuyê n con chuô   t , gõ bàn phím , click chuô   t trên menuca cưa sổ chƣơng trình , hoă  c la m bât cƣ  mô   t thao ta c na o đa   i loa   i nhƣ vâ  y , các thông đip sẽđƣơ   c sinh ra va  thêm chu  ng va o ha ng đơ   i thông điê    p cu  a chƣơng trình. Bằng ca ch go  i tơ   i ha mGetMessage()  bn đang yêu cầu thông đip tiếp theo loi b khi hàng đợi và trả n về cho

 bn xư lý . Nếu nhƣ không co  thông điê    p na o ha m GetMesage () sẽ chuyn sang blocks . Nếu bn không quen với thuâ   t ngƣ   , điêu đo  co  ngh  a la  no  se   đơ   i cho tơ   i khi co  mô   t thông điê    p tiêptheo đê  xƣ  ly   (lấy về cho chƣơng tr nh).

TranslateMessage() thƣ  c hiê  n thêm mô   t số xƣ  ly  trên ca c sƣ   kiê  n ba n ph m chă ng ha  nnhƣ sinh ra ca c thông   điê    p WM _CHAR cu  ng vơ   i ca c thông điê    p WM _KEYDOWN. Cuốicng DispatchMessage() gƣ  i thông điê    p tơ   i cƣ  a sô  ma  thông điê    p cần đƣơ   c gƣ  i tơ   i (xƣ  ly  theo

kiê u hƣơ   ng sƣ   kiê  n ). Đo  co  thê  la  cƣ  a sô  ch nh cu  a chƣơng tr nh hoă  c co  th là mt cưa sổkhác, hoă  c la  mô   t điều khiê n , và trong mt số trƣờng hợp là mt cưa sổ đƣợc to ra ở hậutrƣơ   ng bơ   i hê   thống hoă  c mô   t chƣơng tr nh kha c . Đây không pha i la  điêu ma  ca c ba  n cần pha ilo lắng v  tất ca   nhƣ  ng g  chu  ng ta ba n tơ   i la  lấy thông điê    p va  gƣ  i no  đi , hê   thống se   xƣ  ly  đê  đa m ba o thông điê    p đo  đƣơ   c gƣ  i đến đu  ng nơi se   nhâ  n no  .

Bƣơ   c 4: Th tc cưa sổ.

 Nêu nhƣ vo ng lă    p thông điê    p la  tra i tim cu  a chƣơng trình thì th tc cưa sổ là b nãoca chƣơng trình . Đây la  nơi ma  tất ca  ca c thông điê    p đƣơ   c gƣ  i tơ   i cƣ  a sô  cu  a chu  ng ta đƣơ   cxƣ  ly  .

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

Page 20: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 20/96

Bài giảng môn học: Lâ   p tr  nh Windows 

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 tc cƣ  a sô  đƣơ   c go   i tơ   i đê  xƣ  ly  ca c thông điê    p , tham sô HWND la  đê  qua n ly  cƣ  asô  cu  a ba  n, cũng chính là đối tƣợng ca thông đip . Điều na y la  quan tro  ng bơ   i v  ba  n co  thê  c hai hoc nhiều hơn na các cưa sổ cng lơ   p va  chu  ng se   sƣ  du  ng cu  ng mô   t thu  tu  c cƣ  a sô   (WndProc()). Sƣ   kha c nhau ơ   đây la  tham sô hwnd se   thay đô  i tu  y thuô  c va o cƣ  a sô  la  cƣ  a sô   nào. Chă ng ha  n khi chu  ng ta lấy về mô   t thông điê    p WM _CLOSE chu  ng ta se   hu  y cƣ  a  sô  . Và

vì chng ta sư dng 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 b ảnh hƣởng, chỉ c cưa sổ nhận thông đip là sẽ b hy .

WM_CLOSE đƣơ   c gƣ  i đến khi ngƣơ   i du  ng nhân chu t vào nt đng cưa sổ hoc nhấntô  hơ     p ph m Alt +F4. Thao ta c na y se   la m cho cƣ  a sô  bi  hu  y theo mă  c đi  nh , nhƣng tôi muốnxƣ  ly  no  mô   t ca ch dƣ  t khoa t , vì điều này c th liên quan tới mt số thao tác khác chẳng hnnhƣ đo ng ca c file dƣ   liê  u đang mơ   , ngắt ca c kết nối cơ sơ   dƣ   liê  u , các kết nối mng vân vântrƣơ   c khi thoa t kho  i chƣơng tr nh.

Khi chu  ng ta go  i tơ   i ha m DestroyWindow () hê   thống se   gƣ  i thông điê    pWM_DESTROY tơ   i cƣ  a sô  se   bi   hy b, trong trƣơ   ng hơ     p na y la  cƣ  a sô  cu  a chu  ng ta , và sau

đo  hu  y tất ca  ca c cƣ  a sô  con trƣơ   c khi loa   i bo  cƣ  a sô  cu  a chu  ng ta kho  i hê   thống . Vì chỉ cmô  t cƣ  a sô  trong chƣơng tr nh cu  a chu  ng ta nên cu  ng không co  nhiê u viê  c pha i la m va  chu  ngta muôn thoa t kho  i chƣơng tr nh , vì thế hàm PostQuitMessage() đƣơ   c go  i tơ   i . Hàm này sẽ gưithông điê    p WM _QUIT tơ   i vo ng lă    p thông điê    p . Chng ta không bao nhận đƣợc thông đipnày vì n làm cho hàm GetMessage() trả về FALSE , và nhƣ bn sẽ thấy trong đon mã vnglă    p xƣ  ly  thông điê    p cu  a chu  ng ta , khi điêu đo  xa y ra chu  ng ta dƣ  ng viê  c xƣ  ly  ca c thông điê    pvà trả về giá tr cuối cng , tham số wParam cu  a thông điê    p WM _QUIT la  gia  tri  đƣơ   c truyềnqua ha m PostQuitMessage (). Giá tr trả về chỉ thực sự c ích nếu chƣơng trình ca chng tađƣơ   c thiêt kê đê  mô   t chƣơng tr nh kha c go   i va  chu  ng ta muốn tra  vê mô  t gia  tri  cu   thê  .

Bƣơ   c 5: không co  bƣơ   c 5Đến đây la  hết , chng ta không c bƣớc 5 và tôi hy vọng các bn đã hiu đƣợc ít nhiều

câu tru  c cơ ba n cu  a mô   t chƣơng tr nh trên Windows.

Page 21: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 21/96

Bài giảng môn học: Lâ   p tr  nh Windows 

14

3.3 Quản l các thông điệp 

Ví d: window_click.

Vâ  y la  chu  ng ta đa   co  mô   t cƣ  a sô  , nhƣng no  se   không la m bât cƣ  điêu g  ngoa   i trƣ   nhƣ  ng g  ma  ha m DefWindowProc () cho phe  p no  la m , chă ng ha  n nhƣ thay đô  i k ch thƣơ   c ,

 phng to, thu nho  , vân vân. Quả là không th v tí nào.Trong phân tiêp theo tô i se   hƣơ   ng dâ  n ca c ba  n sƣ  a đô  i nhƣ  ng g  chu  ng ta đa   viêt đê  ta  o

ra mô   t ca i g  đo  mơ   i me .

Trƣơ   c tiên cần đa m ba o la  ba  n đa   biên di  ch va  cha  y chƣơng tr nh simple _window tha nhcông, chng ta sẽ copy n sang ví d mới và  sƣ  a đô  i ma   nguồn (code) ca chƣơng trình.

Chng ta sẽ thêm cho chƣơng trình khả năng hin th tên ca chƣơng trình khi ngƣờidng kích chut vào cưa sổ ca chƣơng trình . Thƣ  c chất cu  a kha  năng mơ   i na y la  chu  ng ta se   tƣ   xƣ   lý thông đip nhấn chut ca ngƣời dng , tât nhiên la  trong ha 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 chu  ng ta muôn xƣ  ly  ca c thông điê    p nhân chuô   t chu  ng ta cần co  t hêm ca c handle :WM_LBUTTONDOWN (hoă  c WM_RBUTTONDOWN, WM_MBUTTONDOWN cho ca cthao ta c nhấn chuô   t pha i va  giƣ  a):

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

{

switch(msg){

case WM_LBUTTONDOWN: // <-

Page 22: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 22/96

Bài giảng môn học: Lâ   p tr  nh Windows 

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ƣ  ly  ca c thông điê    p la  quan tro  ng va  cần nhơ   la  đôi vơ   i ca c thông điê    p kha c(ngoài WM_DESTROY va  WM_QUIT) cần co  thêm câu lê  nh break sau khi xƣ  ly  xong thông  điê    p.

Trƣơ   c tiên tôi se   tr nh ba y đoa  n ma   lê  nh ma  chu  ng ta se   thêm va o (hiê n thi  tên cu  achƣơng tr nh cu  a chu  ng ta ) và sau đ tôi sẽ tích hợp đon mã đ vào chƣơng trình ca chngta. Trong ca c phần sau cu  a chƣơng tr nh t ôi se   ch  cho ca c ba  n đoa  n ma   va  đê  ca c ba  n tƣ   t ch

hơ     p đoa  n ma   đo  va o ca c chƣơng tr nh . Điêu na y vƣ  a tốt cho tôi : tôi se   không pha i go   đi go   la   icác đon mã lnh và vừa tốt cho các bn : các bn c cơ hi thực hàn h nhƣ  ng hiê u biết cu  amình đ nâng cao kỹ năng thực hành . Cn nếu nhƣ bn không chắc chắn hãy tra trong mãnguồn chƣơng tr nh đi ke m vơ   i ta i liê  u na y.

GetModuleFileName(hInstance, szFileName, MAX_PATH);

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

Hàm WndProc() ca chng ta bâ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];

HINSTANCE hInstance = GetModuleHandle(NULL);

Page 23: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 23/96

Bài giảng môn học: Lâ   p tr  nh Windows 

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 cp dấu { và } mơ   i. Các cp dấu này là bắt buc khi chng ta khai báo các biến trong câu lê  nh switch. Bƣớc tiếp theo tất nhiên là dch chƣơng trình , chy thư và xem kếtquả ca chƣơng trình.

Chng ta c th ch ý là ở đây tôi đã sư dng hai biến khi gọi hàmGetModuleFileName(), tham sô thƣ  nhât la  mô   t handle tham chiếu tơ   i mô   t chƣơng tr nh đangchy, nhƣng chu  ng ta co  thê  lấy handle đo  ơ   đâu ra ? Ở đây mt lân na chng ta li sư dngmô  t ha m API kha c GetModuleHandle(), thâ   t may mắn la  đôi vơ   i ha m na y nếu chu  ng ta truyềntham sô la  NULL va o th   kêt qua  tra  vê se   la  handle tro  tơ   i file đƣơ   c sƣ  du  ng đê  ta  o ra tiếntrình đã gọi hàm, đo  ch nh xa c la  ca i ma  chu  ng ta cần. Và do đ chng ta c câu lnh:

HINSTANCE hInstance = GetModuleHandle(NULL);

Tham sô thƣ  hai khi go   i ha m GetModuleFileName () là mt con tr xâu đ chứa đƣờngdâ  n (kêt qua  cu  a ha m ) tơ   i chƣơng tr nh co  handle la  tham sô thƣ  nhất , kiê u cu  a no  la  LPTRSTR (hoă  c LPSTR ) và do LPSTR hoàn toàn tƣơng tự nhƣ char  * nên chu  ng ta khao báomô  t xâu nhƣ sau:

char szFileName[MAX_PATH];

MAX_PATH la  mô   t macro thuô  c windows .h đi  nh ngh  a đô   da i tôi đa cu  a mô   t xâu đê  chƣ  a đô   da  i đƣơ   ng dâ  n tơ   i mô   t file trên windows.

Page 24: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 24/96

Bài giảng môn học: Lâ   p tr  nh Windows 

17

3.4 Vòng lp xư l thông điệp 

 Nhƣ  ng kiến thƣ  c vê vng lp xư lý thông đip và cấu trc ca vic gưi mt thông điplà cần thiết đ viết bất cứ ứng dng nào . Cho đến thơ   i điê m hiê  n ta   i chu  ng ta mơ   i xem xe t mô   tcht về quá trình xư lý thông đip , trong phần na y tôi sẽ trình bày với các bn kỹ càng hơn vềcả quá trình xư lý thông đip .

Thê na o la  mô  t thông điê    p?

Mô   t thông điê    p (message) là mt giá tr nguyên (sô). Nêu ba  n tra trong ca c file header (đây la  mô  t tho  i quen tốt khi la m vic với các hàm API) bn sẽ thấy các dng khai báo sau :

#define WM_INITDIALOG 0x0110

#define WM_COMMAND 0x0111

#define WM_LBUTTONDOWN 0x0201

vân vân. Các thông đip đƣợc sư dng đ tru yên thông hâu nhƣ mo   i thƣ  trên hê  điềuhành windows ít nhất là ti các cấp đ cơ bản . Nêu ba  n muôn mô   t cƣ  a sô  hoă  c mô   t điều khiê n(là mt dng cưa sổ đc bit ) thƣ  c hiê  n mô  t công viê  c na o đo  ,  bn sẽ phải gưi cho n  mô   tthông điê    p.  Nêu mô  t cƣ  a sô  kha c muốn ba  n la m điều g  đo  no  se   gƣ  i tơ   i cho ba  n mô   t thôngđiê    p. Nêu mô  t sƣ   kiê  n xa y ra chă ng ha  n nhƣ ngƣơ   i du  ng go   ba n ph m , di chuyê n chuô   t , nhấnchuô  t lên mô   t button , thì các thôn g điê    p se   đƣơ   c hê   thống (hê  điều ha nh windows ) gƣ  i đêncho ca c cƣ  a sô  chi  u ta c đô  ng cu  a sƣ   kiê  n đo  . Nêu ba  n la  mô   t trong ca c cƣ  a sô  nhƣ thế , bn sẽtiêp nhâ  n va  xƣ  ly  thông điê    p, c các hành vi thích hợp.

Mô  i mô  t thông điê    p co  thê  co  nhiều nhất la  hai tham số , wParam va  lParam . Nguyên

 bản wParam là 16 bit va  lParam la   32 bit, nhƣng trên ca c hê   thông Win32 chng đều là 32 bit.Không pha i tât ca c thông điê    p đều sƣ  du  ng hai tham số na y , và mô  i thông điê    p sƣ  du  ng chu  ngtheo ca c ca ch kha c nhau . Chă ng ha  n thông điê    p WM _CLOSE không sƣ  du  ng ca  hai tham sốtrên, và bn c th b qua chng . Thông điê    p WM_COMMAND sƣ  du  ng ca  hai tham số trên ,wParam chƣ  a hai gia  tri   , HIWORD(wParam) là thông đip báo hiu (nếu th ch hơ     p ) vàLOWORD(wParam) là đnh danh điều khin hoc menu gưi thông đip . lParam la  HWND(window handle) ca điều khin gưi thông đip hoc NULL nếu nhƣ các thông đip không

 phải đƣợc gƣ  i đi tƣ  mô  t điều khiê n na o đo  .

HIWORD() và LOWORD là các macro đƣợc đnh nghĩa bởi windows lấy ra 2 byte cao

(High Word) ca mt giá tr 4 byte = 32 bit (0xFFFF0000) và hai byte thấp (0x0000FFFF)tƣơng ƣ  ng. Trên ca c hê  thống Win 32 mô   t WORD la  mô  t gia  tri   16 bit co n DWORD (DoubleWORD) là mt giá tr 32 bit.

Đê  gƣ  i mô   t thông điê    p ba  n co  thê  sƣ  du  ng ha m PostMessage () hoă  c SendMessage ().PostMessage() đă   t (put) thông điê    p va o ha ng đơ   i thông điê    p va  tra  vê ngay lâ    p tƣ  c. Điêu đo  co   nghĩa là mi khi chng ta gọi tới hàm PostMessage () n sẽ gưi thông đip đi ngay nhƣng victhông điê    p đo  co  thƣ  c hiê  n ngay hay không hoă  c thâ  m ch  co  thƣ  c hiê  n hay không th  co nchƣa chắc chắn . Hàm SendMessage() gƣ  i thông điê    p trƣ  c tiêp tơ   i cho cƣ  a sô  nhâ  n thông điê    pvà sẽ không kết thc cho tới khi thông đip đ đƣợc xư lý xong . Nếu chu  ng ta muốn đo ng mô   tcƣ  a sô  chu  ng ta co  thê  gƣ  i tơ   i cƣ  a sô  đo  mô   t thông điê    p WM_CLOSE chă ng ha  n nhƣPostMessage(hwnd, WM_CLOSE, 0, 0); điều na y co  ta c đô  ng tƣơng tƣ   nhƣ viê  c chu  ng tanhân chuô  t lên biê u tƣơ   ng trên go  c trên bên pha i cu  a cƣ  a sô  . Ch ý rằng wParam và

Page 25: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 25/96

Bài giảng môn học: Lâ   p tr  nh Windows 

18

lParam đêu băng 0 trong trƣơ   ng hơ     p na y . Điều na y la  do nhƣ chu  ng ta đa   no  i trƣơ   c chu  ngkhông co  y  ngh  a g  đôi vơ   i thông điê    p WM_CLOSE.

Các hp thoi (Dialog).

Khi ba  n đa   bắt đầu sƣ  du  ng ca c hô    p thoa   i ,  bn sẽ cần gưi các thông đip tới các điều

khiê n đê  co    thê  truyền thông vơ   i chu  ng . Bn c th làm điều này bằng cách trƣớc hết lấyhandle qua n ly  điều khiê n bằng ha m GetDlgItem () và sau đ sư dng hàm SendMessage ()hoă  c co  thê  sƣ  du  ng ha m SendDlgItemMessage () (hàm này kết hợp công vic ca cả hai hàmtrên). Bn sẽ cung cấp cho hàm mt handle ca mt cưa sổ và mt ID con và hàm sẽ lấyhandle con cu  a hô    p thoa   i va  gƣ  i thông điê    p tơ   i cho no  . SendDlgItemMessage() và mt vàihàm API tƣơng tự khác chă ng ha  n nhƣ GetDlgItemText () sẽ làm vic trên tất cả các cưa sổchƣ  không ch  vơ   i ca c hô    p thoa   i.

Thê na o la  ha ng đơ   i thông điê    p?

Giả sư bn đang bận ti bi với vic xư lý thông đip WM _PAINT va  đô  t nhiên ngƣơ   i

dng thƣ  c hiê  n ha ng loa   t thao ta c trên ba n ph m cu  a ma y t nh . Điều g  se   xa y ra ? Bn sẽ bngăt viê  c đang ve   đê  xƣ  ly  ca c thao ta c ba n ph m cu  a ngƣơ   i du  ng hoă  c ca c thao ta c đo  se   bi    bo   qua? Tất ca  ca c ca ch gia i quyết nhƣ  vâ  y đều co  vân đề , giải pháp ở đây là sư dng mt hàngđơ   i đê  lƣu ca c thông điêp cần xƣ  ly  , khi ca c thông điê    p đƣơ   c gƣ  i đến chu  ng se   đƣơ   c thêm va ohàng đợi và khi các thông đip đƣợc xư lý chng sẽ đƣợc loi b kh i ha ng đơ   i . Và đ đảm

 bảo các thông đip không b b qua nếu nhƣ bn đang bận xư lý mt thông đip nào đ , cácthông điê    p kha c se   đƣơ   c chơ   trong ha ng đơ   i cho tơ   i khi tơ   i lƣơ   t chu  ng đƣơ   c xƣ  ly  .

Thê na o la  mô  t vo ng lă    p thông điê    p (vng lp xư lý thông đip – Message Loop)

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

{

TranslateMessage(&Msg);

DispatchMessage(&Msg);

}

1.  Vng lp thông đip gọi tới hàm GetMessage (), hàm này sẽ kim tra hàng đợithông điê    p cu  a ba  n . Nếu nhƣ ha ng đơ   i thông điê    p la  rô  ng chƣơng tr nh cu  a ba  n vê cơ ba nsẽ dừng và đợi cho tới khi c mt thông đip mới (trng thái Block ).

2. 

Khi mô   t sƣ   kiê  n xa y ra la m cho mô   t thông điê    p đƣơ   c thêm va o ha ng đơ   i(chă ng ha  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 gia  tri  nguyên dƣơng ch  ra rằng co  mô  t thông điê    p cần xƣ  ly  , và các thông tin vềthông điê    p đo  se   đƣơ   c điền va o câu tru  c MSG truyền  cho ha m. Hàm sẽ trả về 0 nêu nhƣthông điê    p la  WM_QUIT va  la  mô   t gia  tri  âm nếu nhƣ co  lô  i xa y ra.

3.  Chng ta nhận đƣợc thông đip (qua biên Msg ) và truyền cho hàmTranslateMessage(), hàm này thực hin xư lý thêm mt cht , dch các thông tin ca thôngđiê    p tha nh ca c thông điê    p ky  tƣ   . Bƣơ   c na y thƣ  c sƣ   không bắt buô  c nhƣng mô   t sô thôngđiê    p se   không la m viê  c đƣơ   c nếu không co  bƣơ   c na y.

4. 

Sau đo  chu  ng ta chuyê n thông điê    p cho ha m DispatchMessage (). Hàm này sẽnhâ  n thông điê    p kiê m tra cƣ  a sô  đ ch cu  a thông điê    p va  t m ha m xƣ  ly  thông điê    p

Page 26: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 26/96

Bài giảng môn học: Lâ   p tr  nh Windows 

19

(Window Procedure) ca cưa sổ đ . Sau đo  no  se   go   i tơ   i ha m xƣ  ly  thông điê    p cu  a cƣ  a sô  ,gƣ  i ca c tham số : handle cu  a cƣ  a sô  , thông điê    p va  ca c tham sô wParam, lParam.

5.  Trong ha m xƣ  ly  thông điê    p ba  n se   kiê m tra thông điê    p va  ca c tham số cu  a no   và làm bất cứ điều gì mà bn thích với chng . Nêu ba  n không muốn xƣ  ly  ca c thông điê    pmô  t ca

 ch chi tiết  c th, bn hầu nhƣ chỉ vic gọi tới hàm DefWindowProc (), hàm này sẽ

thƣ  c hiê  n ca c ha nh đô  ng mă  c đi  nh cho ba  n (điêu na y thƣơ   ng co  ngh  a la  chă ng la m g  ca  ).

6.  Sau khi ba  n đa   kêt thu  c viê  c xƣ  ly  thông điê    p, hàm xư lý thông điê    p cu  a ba  n tra   vê, hàm DispatchMessage() trả về và chng ta qua trở li đầu vng lp .

Đây la  mô   t kha i niê  m cƣ  c ky  quan tro  ng cu  a ca c chƣơng tr nh trên Windows . Th tcxƣ  ly  thông điê    p cu  a ba  n không đƣơ   c go   i mô   t c ách thần bí bởi h thống , mà chính bn đã gọitơ   i chu  ng mô   t ca ch gia n tiếp thông qua viê  c go   i tơ   i ha m DitpatchMessage ().  Nếu nhƣ ba  nmuốn, bn c th sư dng hàm GetWindowLong () trên handle cu  a cƣ  a sô  đ ch cu  a thông điê    p  đ tìm ra th tc xư lý cưa sổ ca n và gọi tới hàm đ mt 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 đa   thƣ  ca ch đo  vơ   i đoa  n ma   chƣơng tr nh trƣơ   c cu  a chu  ng ta va  no  hoa   t đô  ng tốt ,tuy nhiên co  rất nhiều vấn đề chă ng ha  n nhƣ ca c chuyê n đô  i Unicode  /ANSI, các lời gọi tới

các điều khin 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ẽ break vơ   i hầu hết ca c chƣơng tr nh trƣ  ca c chƣơng tr nh đơn gia n . Vì thế không nên thư dnghàm này, trƣ  khi ba  n ch  muôn thƣ  no  .

Ch ý là chng ta sư dng hàm Get WindowLong() đ lấy th tc xư lý cưa sổ ca cưasô  . Ti sao chng ta không đơn giản là gọi tới hàm WndProc () mô   t ca ch trƣ  c tiếp ? Vng lpcác thông đip ca chng ta chu trách nhim đáp ứng cho tất cả các cưa sổ tron g chƣơngtrình ca chng ta , điều na y bao gồm ca  ca c thƣ  chă ng ha  n nhƣ ca c nu  t (button) và các hpdanh sa ch vơ   i ca c ha m xƣ  ly  thông điê    p cu  a chu  ng , vì thế chng ta cần đảm bảo là chng tagọi đến đng hàm xư lý cưa sô  cu  a ca c tha nh phân đo   (đây thƣ  c sƣ   la  mô   t v  du   cu  a kha i niê  m

đa thê  trong lâ    p tr nh hƣơ   ng đôi tƣơ   ng ). Vì các cưa sổ c th sư dng chung mt hàm xư lýthông điê    p nên tham sô đâu tiên (handle cu  a cƣ  a sô  ) đƣơ   c du  ng đê  ch  cho ha m xƣ  ly  thôngđiê    p biết cƣ  a sô  na o la  da nh cho thông điê    p na o.

 Nhƣ ba  n co  thê  thấy ƣ  ng du  ng cu  a ba  n da nh phần lơ   n thơ   i gian cu  a no  cho vo ng lă    p xƣ   lý thông đip , nơi ma  ba  n co  thê  hân hoan gƣ  i ca c thông  điê    p tơ   i ca c cƣ  a sô  se   xƣ  ly  chu  ng .

 Nhƣng ba  n cần la m g  khi muốn thoa t kho  i chƣơng tr nh ? Vì chng ta sư dng mt vng lpwhile(), nêu nhƣ ha m GetMessage () trả về FALSE , vng lp sẽ thoát và chng ta sẽ tới cuốihàm WinMain() và thoát khi chƣơng trình . Đo  ch nh xa c la  nhƣ  ng g  ma  ha mPostQuitMessage() đa   la m. N đt mt thông đip WM _QUIT va o ha ng đơ   i thônmg điê    p va   thay v

 tra  về mô   t gia  tri  dƣơng, hàm GetMesage() điền đầy đu  ca c thông tin cho câu tru  c Msg

và trả về 0. Ti thời đim này thành viên wParam ca cấu trc Msg chứa giá tr mà bn đãtruyền cho ha m PostQuitMessage () và bn cũng c th b qua n , hoă  c tra  vê qua ha mWinMain(), giá tr đ sẽ đƣợc dng nhƣ là mã thoát chƣơng trình khi tiến trình kết thc.

Page 27: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 27/96

Bài giảng môn học: Lâ   p tr  nh Windows 

20

Ch ý: GetMessage() sẽ trả về -1 nếu nhƣ gă    p mô  t lô  i . Bn cần nhớ kỹ điều này nếukhông co  thê  chƣơng tr nh se   gă    p tru  c tră  c , mă  c du  ha m GetMessage() c kiê u BOOL song no   vâ  n co  thê  tra  vê mô   t gia  tri  không pha i la  TRUE hay FALSE v  BOOL co  ngh  a la  UINT(unsigned int). Các ví d sau c vẻ sẽ làm vic 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 ca  ca c trƣơ   ng hơ     p đo  đêu sai. Bn c th ch ý là tôi vẫn sư dng trƣờng hợp1 cho tất ca  ca c v  du   cho tơ   i thơ   i điê m na y , và nhƣ tôi đã đề cập n vẫn làm vic tốt khi màhàm GetMessage () không bao giơ   tra  về FALSE . Tuy nhiên không thê  đa m ba o la  ha mGetMessage() không gă    p lô  i trong tất ca  ca c trƣơ   ng hơ     p va  ba  n nên sƣ  du  ng ca ch viết nhƣsau:

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

Bài tập: 

Bài tập 1: Viết chƣơng trình mô phng chƣơng trình máy tính với các chức năng tính toánđơn giản trên Windows. 

Bài tập 2: Viết chƣơng trình với h thống menu cho phép thay đổi màu nền  

Page 28: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 28/96

Bài giảng môn học: Lâ   p tr  nh Windows 

21

Chƣơng 2: Hê   thô ng file va   thƣ mục 

1. Truy câ   p va   sƣ   du   ng hê   thô  ng file trên môi trƣơ    ng Windows 

Hầu hết ca c ƣ  ng du  ng nga y nay đều cho phe  p ngƣơ   i du  ng lƣ  a cho  n ghi la   i nhƣ  ng g  chƣơng tr nh đa   ta  o ra . Nhƣ  ng thƣ  cần ghi la   i co  thê  la  ca c ta i liê  u , dƣ   liê  u chƣơng tr nh hoă  c

mô  t thiêt lâ    p na o đo  đôi vơ   i chƣơng tr nh . Trong ba i thƣ  c ha nh na y chu  ng ta se   kha m pha  ca chô   trơ    cu  a Visual C ++ cho viê  c ca i đă   t ca c chƣ  c năng na y mô  t ca ch dê   da ng . C th chng tasẽ học:

 Cách Visual C++ sƣ  dung ca c luồng C++ đ ghi li d liu trong chƣơng trình 

 Cách thức sư dng file dng nh phân  

 Cách làm cho các đối tƣợng chƣơng trình c khả năng serialize  

 Cách thức lƣu các biến c kiu khác nhau vào cng mt file

2. Các v dụ về thao tác với file 

2.1 Serialization

C hai phần ca serialization . Khi dƣ   liê  u ƣ  ng du  ng đƣơ   c lƣu trên đ  a hê  thông dƣơ   idng mt file thì đ gọi là serialization . Khi tra  ng tha i cu  a ƣ  ng du  ng đƣơ   c phu  c hôi tƣ  file đo   đƣơ   c go  i la  deserialization . Sƣ   kêt hơ     p cu  a hai phần na y la m nên ca i go   i la  serialization cu  acác đối tƣơng ứng dng trong Visual C++.

2.1.1 Các lớp CArchive và CFile 

Serialization trong ca c ƣ  ng du  ng cu  a Visual C ++ đƣơ   c thƣ  c hiê  n qua lơ   p CArchive . Lơ   pCArchive đƣơ   c thiết kế đê  la m viê  c vơ   i ca c luông va o ra cho mô   t đối tƣơ   ng CFile nhƣ minh

họa trong hình vẽ sau:

Lơ   p na y sƣ  du  ng ca c luồng cu  a C ++ đ cho phép các luồng d liu đƣợc  np từ hoclƣu la   i tha nh ca c file mô   t ca ch hiê  u qua  . Lơ   p CArchive không thê  tồn ta   i nếu không co  mô   tđôi tƣơ   ng CFile gắn vơ   i no  .

Lơ   p CArchive co  thê  chƣ  a dƣ   liê  u trong rất nhiều kiê u file kha c nhau , tất ca  chu  ng đều

là hâ  u duê  cu  a lơ   p CFile . Theo mă  c đi  nh App Wizard se   bao go  i tất ca  ca c chƣ  c năng đê  ta  ovà mở các đối tƣợng CFile thông thƣờng đ sư dng với CArchive . Nếu chu  ng ta muốn hoă  c

Page 29: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 29/96

Bài giảng môn học: Lâ   p tr  nh Windows 

22

cân thiết pha i la m viê  c vơ   i mô   t trong ca c lo i file này chng ta cần phải viết thêm các đonmã chƣơng trình cần thiết đ c th làm vic với các loi file khác nhau .

2.1.2 Hàm Serialize 

Lơ   p CArchive đƣơ   c sƣ  du  ng trong ha m Serialize trên ca c đối tƣơ   ng document va  dƣ    

liê  u trong ca c ƣ  ng du  ng Visual C ++. Khi mô   t ƣ  ng du  ng đo  c hoă  c ghi lên mô   t file ha mSerialize cu  a đôi tƣơ   ng document se   đƣơ   c go   i đến , truyền đối tƣơ   ng CArchive đƣơ   c sƣ  du  ngđ ghi hoc đọc từ file. Trong ha m Serialize thƣ  tƣ   logic đƣơ   c tuân theo đê  xa c đi  nh xem đo  la  thao ta c đo  c hay ghi bằng ca ch go  i tơ   i ca c ha m IsStoring hoă  c IsLoading . Giá tr trả về từ haihàm trên sẽ xác đnh xem ứng dng cần ghi hay đọc từ luồng vào ra ca lớp CArchive . Mô  thàm Serialize đin hình sẽ c cấu trc nhƣ sau:

void CAppDoc::Serialize(CArchive& ar)

{

 // Is the archive being written to?

if (ar.IsStoring())

{

 // Yes, write my variable

ar << m_MyVar;

}

else

{

 // No, read my variable

ar >> m_MyVar;

}

}

Chng ta c th đt mt hàm Serialize trong bất cứ lớp nào mà chng ta to ra đ sau đgọ đến hàm Serialize từ hàm Serialize ca lớp document . Nếu chu  ng ta đă   t ca c đôi tƣơ   ng dochng ta to ra vào mt mảng các đối  tƣơ   ng chă ng ha  n nhƣ CObArray nhƣ trong ƣ  ng du  ng

trƣơ   c đây 3 ngày chng ta c th gọi tới hàm Serialize ca mảng từ hàm Serialize ca lớpdocument. Đối tƣợng mảng sẽ , khi tơ   i lƣơ   t no  , gọi tới hàm Serialize ca các đối tƣợng  đƣơ   cchƣ  a bên trong no  .

2.1.3 Các đối tƣng c thể Serialize 

Khi chu  ng ta ta  o ra lơ   p CLine trong ba i thƣ  c ha nh số 10 chng ta cần phải thêm 2 macrotrƣơ   c khi chu  ng ta co  thê  ghi la   i hoă  c na    p dƣ   liê  u tƣ  ca c file . Hai macro na y ,DECLARE_SERIAL va  IMPLEMENT_SERIAL se   bao go  i chƣ  c năng cần thiết trong ca c lơ   pca chng ta đ hàm Serialize c th hot đng đng đắn .

Macro thƣ  nhất DECLARE _SERIAL đƣơ   c đă   t ngay do ng lê  nh đầu tiên trong khai ba o

lơ   p (khái niê  m na y giống nhƣ kha i niê  m giao diê  n cu  a Java ), n nhận mt tham số là tên calơ   p, tác dng ca n là sẽ thêm vào lớp ca chng ta các khai báo toán tư và hàm cần thiết đchƣ  c năng serialization hoa   t đô  ng đu  ng đắn.

Page 30: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 30/96

Bài giảng môn học: Lâ   p tr  nh Windows 

23

Ví d nhƣ sau:

class CMyClass : public CObject

{

DECLARE_SERIAL (CMyClass)

public:

virtual void Serialize(CArchive &ar);

CMyClass();

virtual ~CMyClass();

};

Macro thƣ  hai IMPLEMENTATION _SERIAL đƣơ   c đă   t trong phần ca i đă   t cu  a lơ   p do

chng ta ta  o ra . Macro na y cần pha i đă   t bên ngoa i bất cƣ  ca c ha m tha nh viên na o cu  a lơ   p v  n sẽ thêm mã ca các hàm cần thiết cho lớp tƣơng ứng với khai báo ca macroDECLARE_SERIAL.

Macro na y nhâ  n 3 tham số . Tham sô thƣ  nhất   là tên lớp , giống nhƣ macro thƣ  nhất .Tham sô thƣ  hai la  tên cu  a lơ   p cơ sơ     (lơ   p cha). Tham số thƣ  ba la  mô   t sô version co  thê  đƣơ   csƣ  du  ng đê  xa c đi  nh mô   t file co  la  đu ng version đê  thƣ  c hiê  n thao ta c đo  c vơ   i ƣ  ng du  ng cachng ta hay không . Số version na y pha i la  mô  t số dƣơng nên đƣơ   c tăng lên mô  i lân phƣơngthƣ  c serializeation cu  a lơ   p đƣơ   c thay đô  i thay bất cƣ  ca ch thƣ  c na o la m thay đô  i dƣ   liê  u đƣơ   cghi hoă  c đo  c tƣ  file. Ví d về khai báo ca macro thứ hai này nhƣ sau :

 // MyClass.cpp: implementation of the CMyClass class.

#include "stdafx.h"

#include "MyClass.h"

#ifdef _DEBUG

#undef THIS_FILE

static char THIS_FILE[]=__FILE__;

#define new DEBUG_NEW

#endif 

IMPLEMENT_SERIAL (CMyClass, CObject, 1)

 ////////////////////////////////////////////////////////////////////// 

 // Construction/Destruction

 ////////////////////////////////////////////////////////////////////// 

Page 31: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 31/96

Bài giảng môn học: Lâ   p tr  nh Windows 

24

CMyClass::CMyClass()

{

}

CMyClass::~CMyClass()

{

}

2.1.4 Cài đă    t ha  m Serialize 

Cng với hai macro chng ta cần cài đt hàm Serialize trong lớp ca chng ta . Hàm nàynên đƣơ   c khai ba o la  ha m kiê u void vơ   i mô   t tham số (CArchive &ar), kiê u public va  la  ha mvirtual. Khi ca i đă   t ha m na y ch ng ta thƣờng sư dng cách tiếp cận giống nhƣ cách tƣơng tựđƣơ   c du

 ng trong lơ 

  p document ơ 

 trên , c nghĩa là cần phải kim tra đ là thao tác ghi hay đọc

trƣơ   c khi thƣ  c hiê  n thao ta c.

2.2 Cài đt một lớp Serializable 

Khi chu  ng ta bắt đầu thiết kế mô   t ƣ  ng du  ng mơ   i , mô  t trong nhƣ  ng điều đầu tiên ma  chng ta cần thiết kế là cách thức chứa d liu trong lớp document , dƣ   liê  u ma  chƣơng tr nhsẽ to ra và thao tác với . Nếu chu  ng ta ta  o ra mô  t ƣ  ng du  ng da  ng data -oriented chƣ  a mô  t tâ    pdƣ   liê  u tƣ  ngƣơ   i du  ng chă ng ha  n nhƣ mô   t ƣ  ng du  ng cơ   sơ   dƣ   liê  u chă ng ha  n la m thế na o đê  chƣ  a ca c dƣ   liê  u đo  trong bô   nhơ   cu  a chƣơng tr nh . Cách tổ chức d liu nhƣ thế nào nế uchng ta làm vic với mt ứng dng son thảo văn bản hoc ứng dng xư lý bảng tính ?

Khi chu  ng ta đa   xa c đi  nh đƣơ   c ca ch thiết kế ca c cấu tru  c dƣ   liê  u ma  chƣơng tr nh se   dng chng ta c th quyết đnh đƣợc cách tố t nhât đê  thƣ  c hiê  n chƣ  c năng serialize chochƣơng tr nh va  ca c lơ   p trong chƣơng tr nh .  Nêu chu  ng ta quyết đi  nh lƣu trƣ  c tiếp tất ca  dƣ    liê  u cu  a chƣơng tr nh trong lơ   p document th  tất ca  nhƣ  ng g  chu  ng ta cần la  ghi dƣ   liê   u va  đo  c dƣ   liê  u vơ   i đối tƣơ   ng CArchive trong ha m Serialize cu  a lơ   p document . Nếu chu  ng ta ta  ora lơ   p riêng đê  lƣu ca c dƣ   liê  u cu  a chƣơng tr nh (nhƣ chu  ng ta đa   la m ơ   ba i thƣ  c ha nh số 10)chng ta cần phải thêm chức năng se rializable cho ca c lơ   p na y đê  chu  ng co  thê  tƣ   ghi va  đo  ctƣ  file.

Trong ƣ  ng du  ng ma  chu  ng ta se   xây dƣ  ng ơ   ba i thƣ  c ha nh na y chu  ng ta se   viêt mô  t

chƣơng tr nh cơ sơ   dƣ   liê  u da  ng đơn gia n , flat-file đê  minh ho  a ca ch thƣ  c kết hơ     p ca c kiê u dƣ    liê  u kha c nhau trong mô   t luông dƣ   liê  u trong ƣ  ng du  ng serialization . Ưng dng ca chng tasẽ hin th mt số các trƣờng d liu c kiu khác nhau , ghi va  đo  c dƣ   liê  u tƣ  mô  t luồng dƣ    liê  u duy nhất vơ   i đôi tƣơ   ng CArchive.

2.2.1 Thiê t kê  giao diê   n chƣơng tr  nh 

Chng ta c th to ra các lớp ca riêng mình , các lớp này c th serialized , c th sưdng với các ứng dng SDI hoc MDI . Ni ngắn gọn bất cứ ứng dng nào làm vic với bất cứkiê u dƣ   liê  u na o, d đ là mt cơ sở d liu hoc mt tài liu đều c th serialized.

Chng ta tiến hành các bƣớc sau :

1.  To mt project dng SDI c tên là Serialize 

2.  Trong phần Document Template String gõ phần File Extension là fdb 

Page 32: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 32/96

Bài giảng môn học: Lâ   p tr  nh Windows 

25

3.  Phần Advanced features bo  dấu check ActiveX control 

4.  Phần Generated Classes cho  n lơ   p cơ sơ   cu  a lơ   p CSerialzeView la  CFormView

5.   Nhấn Finish , chng ta sẽ nhận đƣợc thông báo là chƣơng trình sẽ

không co  chƣ  c năng in ấn, nhấn Yes đê  tiêp tu  c Sau khi ta  o mô   t ƣ  ng du  ng SDI hoă  c MDI trong đo  lơ   p view kế thƣ  a tƣ  lơ   p CFormView

chng ta cần thiết kế form view ca chƣơng trình trình , quá trình này cũng giống nhƣ thiết kếcác hp thoi trong ca c ƣ  ng du  ng da  ng Dialog based nhƣng chu  ng ta không cần co  ca c nu  t đê  thoát khi chƣơng trình hoc hy b quá trình thực hin nhƣ trên các hp thoi thông thƣờng .Vơ   i mô   t ƣ  ng du  ng SDI hoă  c MDI chƣ  c năng ghi va  thoa t cƣ  a sô  đƣơ   c đă   t trên ca c hê  thốngmenu chƣơng tr nh hoă  c trên ca c thanh công cu  .

Ch ý :  Nếu chu  ng ta la m viê  c vơ   i ca c ƣ  ng du  ng da  ng Dialog based App Wizard se   không cung cấp ca c đoa  n ma   serialization cho ƣ  ng du  ng chu ng ta cân p hải tự thực hin điều

này nếu muốn.Thiêt kê form cu  a chƣơng tr nh gồm ca c điều khiê n nhƣ ba ng sau:

Object   Property  Setting 

Static Text ID IDC_STATIC

Caption &Name:

Edit Box ID IDC_ENAME

Static Text ID IDC_STATIC

Caption &AgeEdit Box ID IDC_EAGE

Static Text ID IDC_STATIC

Caption Marital Status:

Radio Button ID IDC_RSINGLE

Caption &Single

Group Checked

Radio Button ID IDC_RMARRIED

Caption &Married

Radio Button ID IDC_RDIVORCED

Caption &Divorced

Radio Button ID IDC_RWIDOW

Caption &Widowed

Check Box ID IDC_CBEMPLOYED

Caption &Employed

Button ID IDC_BFIRSTCaption &First

Page 33: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 33/96

Bài giảng môn học: Lâ   p tr  nh Windows 

26

Button ID IDC_BPREV

Caption &Previous

Button ID IDC_BNEXT

Caption Nex&t

Button ID IDC_BLAST

Caption &Last

Static Text ID IDC_SPOSITION

Caption Record 0 of 0

Giao diê  n chƣơng tr nh sau khi thiết kế trong nhƣ sau:

Khi chu  ng ta pha t triê n ca c ƣ  ng du  ng hoă  c cƣ  a sô  kiê u dialog - based chu  ng ta sẽ gắn các biên cho ca c điều khiê n trên cƣ  a sô  cu  a lơ   p hô    p thoa   i . Tuy nhiên đối vơ   i mô   t ƣ  ng du  ng da  ngSDI hoă  c MDI chu  ng ta se   gắn cho lơ   p na o ? Vì hàm UpdateData là mt hàm ca lớp CWndvà lớp view là mt hậu du ca lơ   p CWnd , mă  c du  lơ   p document th  không pha i , nên lơ   pview se   la  nơi logic nhất đê  đă   t ca c biến gắn vơ   i ca c điều khiê n trên cƣ  a sô  chƣơng tr nh .

Đê  ga n ca c biến cho ca c điều khiê n cu  a chƣơng tr nh chu  ng ta mơ   Class Wizard v à gắncác biến cho các điều khin và chỉ đnh lớp chứa chng là lớp view c th ở ứng dng này làCSerializeView. Các biến đƣợc gán cho các điu khin nhƣ sau :

Object    Name  Category  Type 

IDC_CBEMPLOYED m_bEmployed Value BOOL

IDC_EAGE m_iAge Value int

IDC_ENAME m_sName Value CString

IDC_RSINGLE m_iMaritalStatus Value int

Page 34: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 34/96

Bài giảng môn học: Lâ   p tr  nh Windows 

27

IDC_SPOSITION m_sPosition Value CString

 Nêu nhƣ chu  ng ta kiê m tra ma   chƣơng tr nh cu  a lơ   p view chu  ng ta se   thấy rằng khôngc hàm OnDraw. Nêu chu  ng ta sƣ  du  ng lơ   p tô  tiên CFormView cho ƣ  ng du  ng SDI hoă  c MDIchn g ta không cần lo lắng về hàm OnDraw . Thay va o đo  chu  ng ta se   đôi xƣ  vơ   i lơ   p view rất

giống vơ   i lơ   p hô    p thoa   i nhƣ trong mô   t cƣ  a s ổ hp thoi hoc mt ứng dng dng dialog -based. Sƣ   kha c nhau chu  yếu ơ   đây la  dƣ   liê  u chƣơng tr nh ma  chu  ng ta cần sƣ  du  ng đê  ga ncho ca c điều khiê n cu  a cƣ  a sô  chƣơng tr nh không pha i la  cu  a lơ   p view ma  la  cu  a lơ   pdocument. Do đo  chu  ng ta cần xâu dƣ  ng ca c tƣơng ta c giƣ  a ca c lơ   p na y đê  truyền ca c dƣ   liê  ugiƣ  a chu  ng.

2.2.2 Tạo lớp Serializable 

Khi chu  ng ta ta  o ra mô   t ƣ  ng du  ng da  ng form - based chu  ng ta se   gia  sƣ  rằng chƣơng tr nhsẽ chứa nhiều ba n ghi trong form va  ngƣơ   i du  ng co  thê  duyê   t qua ca c ba n ghi na y đê  thƣ  chiê  n ca c thay đô  i va  ghi la   i . Ngƣơ   i du  ng cu  ng co  thê  thêm va o ca c ba n ghi mơ   i va  loa   i bo  ba n

ghi na o đo  . Thách thức đối với chng ta trong  viê  c xây dƣ  ng ƣ  ng du  ng la  la m thê na o đê  biê udiê  n ca c ba n ghi đo  đê  co  thê  hô   trơ    tất ca  ca c chƣ  c năng cu  a chƣơng tr nh .

Mô   t ca ch tiêp câ  n la  ta  o ra mô  t lơ   p bao go  i tât ca  ca c ba n ghi va  sau đo  chƣ  a tất ca  ca c bản ghi trong mt mảng giống nhƣ cách mà chng ta đã thực hin với các ứng dng trong ba bài thực hành trƣớc đây . Lơ   p na y se   cần kế thƣ  a tƣ  lơ   p CObject va  cần chƣ  a ca c biến cho tấtcả các biến tƣơng ứng với các điều k hiê n đƣơ   c thêm va o lơ   p view cu  ng vơ   i phƣơng thƣ  c đo  cvà ghi tất cả các biến này. Cng với vic thêm vào các phƣơng thức đọc và ghi các biến chngta cân pha i la m cho lơ   p na y la  mô  t lơ   p serialiable bằng ca c thêm va o ha m Serialize cho lơ   pcng với hai macro đã mô tả ở trên.

Tạo một lớp cơ bản  Nhƣ ca c ba  n co  thê  nhơ   tƣ  ba i thƣ  c ha nh số 10 khi chu  ng ta muốn ta  o ra mô  t lơ   p mơ   i

chng ta cần chọn tab Class View và nhấn chut phải chọn Add | Add Class. Sau đo  trong hô    pthoi tiếp theo chọn đ là mt Generic class , chng ta sẽ học nhiều hơn về các lớp này trong

 bài thực hành số 16. Tiếp theo chu  ng ta go   tên lơ   p la  CPerson , lơ   p cơ sơ   cu  a lơ   p la  lơ   pCObject. Sau khi ta  o xong lơ   p chu  ng ta tiếp tu  c thêm ca c biến tha nh viên cho lơ   p , các biếnthành viên này cần phải khớp với các biến đƣợc gán cho các điều khin trên cưa sổ chƣơngtrình trong lớp view nhƣ trong bảng sau:

Name Type

m_bEmployed BOOL

m_iAge int

m_sName CString

m_iMaritalStatus int

Cài đt phƣơng thức đọc và ghi cho lớp CPerson 

Sau khi đa   ta  o ra lơ   p CPerson chu  ng ta se   cung cấp mô   t phƣơng tiê  n đê  đo  c va  ghi ca c

 biên cho lơ   p. Cách d nhất đ cung cấp các chức năng này là thêm các hàm inline trong đnhnghĩa ca lớp , chng ta c th thêm mt tập cá c ha m inline đê  thiết lâ    p va  lấy gia  tri  cu  a ca c

Page 35: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 35/96

Bài giảng môn học: Lâ   p tr  nh Windows 

28

 biến (riêng biê   t). Ví d chng ta c th mở file header  (Person.h) và sưa li khai báo ca lớpCPerson nhƣ sau: 

class CPerson : public CObject

{

public:

 // Functions for setting the variables

void SetEmployed(BOOL bEmployed) { m_bEmployed = bEmployed;}

void SetMaritalStat(int iStat) { m_iMaritalStatus = iStat;}

void SetAge(int iAge) { m_iAge = iAge;}

void SetName(CString sName) { m_sName = sName;}

 // Functions for getting the current settings of the variables

BOOL GetEmployed() { return m_bEmployed;}

int GetMaritalStatus() { return m_iMaritalStatus;}

int GetAge() {return m_iAge;}

CString GetName() {return m_sName;}

CPerson();

virtual ~CPerson();

private:

BOOL m_bEmployed;

int m_iMaritalStatus;

int m_iAge;

CString m_sName;

};

Hàm cấu tư mc đnh đƣợc Visual C++ tƣ   đô  ng cung cấp va  chu  ng ta không cần sƣ  a đô  i(vơ   i Visual 6.0 thì vẫn cần thêm hàm này vào).

2.2.3 Cài đt hàm Serialize

Tiếp đến chu  ng ta se   thêm ha m Serialize cho lơ   p bắt đầu bằng viê  c thêm 2 macro va ođu  ng vi  tr  cu  a chu  ng trong ca c file khai ba o va  ca i đă   t cu  a lơ   p CPerson , sau đo  thêm ha mvirtual, public Serialize(CArchive &ar) cho lơ   p CPerson nhƣ sau: 

void CPerson::Serialize(CArchive &ar)

{

 // Call the ancestor function

CObject::Serialize(ar);

 // Are we writing?

Page 36: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 36/96

Bài giảng môn học: Lâ   p tr  nh Windows 

29

if (ar.IsStoring())

 // Write all of the variables, in order

ar << m_sName << m_iAge << m_iMaritalStatus << m_bEmployed;

else

 // Read all of the variables, in order

ar >> m_sName >> m_iAge >> m_iMaritalStatus >> m_bEmployed;

}

Về ba n chất ha m na y cu  ng kha  đơn gia n , ban đâu no  go   i tơ   i phƣơng thƣ  c Serialize cu  alơ   p cha đê  xa c đi  nh xem đo  la   thao ta c đo  c hay ghi dƣ   liê  u , sau đo  no  go   i tơ   i ha m IsStoring đê  xác đnh nếu là ghi d liu thì thực hin ghi các biến thành viên ca lớp cn ngƣợc li thì thựchiê  n thao ta c đo  c (ch ý thứ tự ca các biến là quan  trọng).

Ch ý: chng ta biết là mt ứng dng không phải khi nào cũng c th đọc hoc ghi dliê  u tha nh công nên trên thƣ  c tê khi chu  ng ta tiến ha nh thƣ  c hiê  n ha m trên se   co  mô  tException đƣơ   c throw đê  kiê m soa t lô  i nhƣng  ở đây chng ta tm thời b qua vấn đề này(xem phu   lu  c A cuôn Teach yourself Visual C++ 6.0 in 21 days đê  biết thêm chi tiết).

Cài đt các chức năng cho lớp document 

Khi chu  ng ta xây dƣ  ng mô   t ƣ  ng du  ng da  ng form - based trong đo  form năm trên cƣ  a sô  la   không gian ch nh đê  ngƣơ   i du  ng co  thê  tƣơng ta c vơ   i ƣ  ng du  ng co  mô  t gia  sƣ  không đƣơ   c đềcâ    p ro   ra ng la  ƣ  ng du  ng cu  a chu  ng ta se   cho phe  p ngƣơ   i du  ng la m viê  c vơ   i nhiêu ba n ghi .Điêu na y co  ngh  a  là chng ta cần h trợ các tính năng lƣu và duyt qua các bản ghi này . Viê  c

lƣu ca c ba n ghi co  thê 

thƣ  c hiê  n dê   da ng bằng ca ch sƣ  du  ng mô   t ma ng nhƣ chu  ng ta đa   tƣ  nglàm trong bài thực hành số 10. Cách làm này cho phép chu  ng ta co  thê  thêm va o mô   t sô lƣơ   ng bản ghi không hn chế (không biết co  đu  ng không nƣ  a). Viê  c duyê   t qua ca c ba n ghi đƣơ   c thƣ  chiê  n qua bốn thao ta c la  First (duyê   t ba n ghi đầu tiên), Last ( bản ghi cuối cng), Previous ( bảnghi trƣơ   c) và Next ( bản ghi tiếp theo). Chng ta cần mt chức năng thông báo đ xác đnh bảnghi na o đang đƣơ   c hiê n thi   .

Đê  lƣu trƣ   va  hô   trơ    ca c t nh năng na y lơ   p document cần hai biến : mô   t ma ng va  mô  t ch  sô ba n ghi hiê  n ta   i nhƣ ba ng sau:

Name Typ

e

m_iCurPosition

int

m_oaPeople

CObArray

Mô   t viê  c kha c chu ng ta cần la m la  include file header cu  a lơ   p CPerson va o file ca i đă   tca lớp document (v trí trƣớc các file header ca lớp document và view) nhƣ sau:  

#include "stdafx.h"

#include "Serialize.h"

#include "Person.h"

Page 37: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 37/96

Bài giảng môn học: Lâ   p tr  nh Windows 

30

#include "SerializeDoc.h"

#include "SerializeView.h"

Thêm mô   t ba n ghi mơ   i 

Trƣơ   c khi chu  ng ta co  thê  duyê   t qua ca c ba n ghi trong chƣơng tr nh chu  ng ta cần xây

dƣ  ng chƣ  c năng thêm mô   t ba n ghi mơ   i cho ma ng ca c đôi tƣơ   ng . Cách tiếp cận tƣơng tự nhƣ bài thực hành sẽ đƣợc sư dng , và vì các bản ghi mc đnh đều c các trƣờng d liu là rngnên chu  ng ta ch  cần sƣ  du  ng ha m câu  tƣ  mă  c đi  nh do Visual C ++ cung cấp la  đu  , đồng thơ   imô  i khi thêm va o mô   t ba n ghi mơ   i chu  ng ta se   ga n ba n ghi hiê  n ta   i la  ba n ghi mơ   i đo    (hàmnày là private).

CPerson* CSerializeDoc::AddNewRecord(void)

{

 // Create a new CPerson object

CPerson *pPerson = new CPerson();try

{

 // Add the new person to the object array

m_oaPeople.Add(pPerson);

 // Mark the document as dirty

SetModifiedFlag();

 // Set the new position markm_iCurPosition = (m_oaPeople.GetSize() - 1);

}

 // Did we run into a memory exception?

catch (CMemoryException* perr)

{

 // Display a message for the user, giving them the

 // bad newsAfxMessageBox("Out of memory", MB_ICONSTOP | MB_OK);

 // Did we create a line object?

if (pPerson)

{

 // Delete it

delete pPerson;

pPerson = NULL;

}

Page 38: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 38/96

Bài giảng môn học: Lâ   p tr  nh Windows 

31

 // Delete the exception object

perr->Delete();

}

return pPerson;

}

Tƣơng tƣ   nhƣ ba i thƣ  c ha nh số 10 chng ta cần các hàm lấy tổng số bản ghi , sô thƣ  tƣ    bà đối tƣợng tƣơng ứng với bản ghi hin ti nhƣ sau (các hàm này là public):

int CSerializeDoc::GetTotalRecords( void)

{

return m_oaPeople.GetCount();

}

int CSerializeDoc::GetCurRecordNbr( void)

{

return m_iCurPosition + 1;

}

CPerson* CSerializeDoc::GetCurRecord(void)

{

 // Are we editing a valid record number?

if (m_iCurPosition >= 0)

 // Yes, return the current record

return (CPerson*)m_oaPeople[m_iCurPosition];

else

 // No, return NULL

return NULL;

}

Các chức năng tiếp theo cần đƣợc cài đt là các hàm cho phép thực hin các thao tác lấycác bản ghi ca mảng mt cách tƣơng đối (đầu, cuối, trƣơ   c, sau):

CPerson* CSerializeDoc::GetFirstRecord(void)

{

 // Are there any records in the array?

if (m_oaPeople.GetSize() > 0){

Page 39: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 39/96

Bài giảng môn học: Lâ   p tr  nh Windows 

32

 // Yes, move to position 0

m_iCurPosition = 0;

 // Return the record in position 0

return (CPerson*)m_oaPeople[0];

}else

 // No records, return NULL

return NULL;

}

CPerson* CSerializeDoc::GetNextRecord(void)

{

 // After incrementing the position marker, are we

 // past the end of the array?

if (++m_iCurPosition < m_oaPeople.GetSize())

 // No, return the record at the new current position

return (CPerson*)m_oaPeople[m_iCurPosition];

else

 // Yes, add a new record

return AddNewRecord();

}

CPerson* CSerializeDoc::GetPrevRecord(void)

{

 // Are there any records in the array?

if (m_oaPeople.GetSize() > 0)

{

 // Once we decrement the current position,

 // are we below position 0?

if (--m_iCurPosition < 0)

 // If so, set the record to position 0

m_iCurPosition = 0;

 // Return the record at the new current position

return (CPerson*)m_oaPeople[m_iCurPosition];

}else

 // No records, return NULL

Page 40: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 40/96

Bài giảng môn học: Lâ   p tr  nh Windows 

33

return NULL;

}

CPerson* CSerializeDoc::GetLastRecord(void)

{

 // Are there any records in the array?

if (m_oaPeople.GetSize() > 0)

{

 // Move to the last position in the array

m_iCurPosition = (m_oaPeople.GetSize() - 1);

 // Return the record in this position

return (CPerson*)m_oaPeople[m_iCurPosition];

}else

 // No records, return NULL

return NULL;

}

Tiếp đến la  ha m Serialize cho ma ng ca c đối tƣơ   ng cu  a lơ   p document (CSerializeDoc):

void CSerializeDoc::Serialize(CArchive& ar)

{

 // Pass the serialization on to the object array

m_oaPeople.Serialize(ar);

}

Hàm làm công tác môi trƣờng , dọn dp tất cả mọi thứ trƣớc khi bắt đầu mt tài liu mới(hàm này đƣợc gọi tới khi chƣơng tr nh kết thu  c hoă  c trƣơ   c khi mô   t ta i liê  u mơ   i đƣơ   c mơ   ):

void CSerializeDoc::DeleteContents()

{

 // TODO: Add your specialized code here and/or call the base class

 // Get the number of lines in the object array

int liCount = m_oaPeople.GetSize();

int liPos;

 // Are there any objects in the array?

if (liCount)

{

Page 41: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 41/96

Bài giảng môn học: Lâ   p tr  nh Windows 

34

 // Loop through the array, deleting each object

for (liPos = 0; liPos < liCount; liPos++)

delete m_oaPeople[liPos];

 // Reset the array

m_oaPeople.RemoveAll();

}

CDocument::DeleteContents();

}

Chng ta c th thấy các bƣớc thực hin hoàn toàn giống với bài thực hành số 10, vàcũng cần nhắc li mt ch ý đ là : cần pha i chuyê n đối tƣơ   ng lấy tƣ  ma ng CObArray tha nhkiê u CPerson v  đo  la  mô   t biến kiê u CObject.

Tiếp theo cần pha i sƣ  a la   i ha m tƣơng ƣ  ng vơ   i sƣ   kiê  n OnNewDocument:BOOL CSerializeDoc::OnNewDocument()

{

if (!CDocument::OnNewDocument())

return FALSE;

 // TODO: add reinitialization code here

 // (SDI documents will reuse this document) // If unable to add a new record, return FALSE

if (!AddNewRecord())

return FALSE;

 // Get a pointer to the view

POSITION pos = GetFirstViewPosition();

CSerializeView* pView = (CSerializeView*)GetNextView(pos); // Tell the view that it's got a new data set

if (pView)

pView->NewDataSet();

return TRUE;

}

Khi mô   t ta  i liê  u mơ   i bắt đầu chƣơng tr nh se   đƣa ra mô   t form rô  ng să  n sa ng đê  nhâ    pthông tin mơ 

 i , và đ bản ghi này c th sn sàng nhận thông  tin chu

 ng ta thêm va

 o mô  t ba

 n

ghi trong ma ng ca c đối tƣơ   ng va  khi mô  t ba n ghi mơ   i đƣơ   c thêm va o ma ng chu  ng ta cần thayđô  i viê  c hiê n thi  đê  ch  ra răng ba n ghi mơ   i đo  tôn ta   i ngƣơ   c la   i ca c hiê n thi  se   tiếp tu  c vơ   i ba  n

Page 42: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 42/96

Bài giảng môn học: Lâ   p tr  nh Windows 

35

ghi cuối cu  ng tƣ  tâ    p ba n ghi trƣơ   c (và ngƣời dng c th băn khoăn ti sao ứng dng cachng ta không bắt đầu với mt tập bản ghi mới).

Khi mơ   mô   t tâ    p dƣ   liê  u să  n co  chu  ng ta không cần thêm va o bât cƣ  ba n ghi mơ   i na  onhƣng vâ  n cần pha i cho đối tƣơ   ng view biết rằng no  cần pha i la m tƣơi ba n ghi đƣơ   c hiê n thi   cho ngƣơ 

 i du

 ng . Do đo

 chu

 ng ta co

 thê  thêm đoa  n ma

  tƣơng tƣ   cho ha

 m OnOpenDocument

nhƣ sau ( b phần đầu c chức năng thêm vào mt bản ghi mới) nhƣ sau: 

BOOL CSerializeDoc::OnOpenDocument(LPCTSTR lpszPathName)

{

if (!CDocument::OnOpenDocument(lpszPathName))

return FALSE;

 // TODO: Add your specialized creation code here

 // Get a pointer to the view

POSITION pos = GetFirstViewPosition();

CSerializeView* pView = (CSerializeView*)GetNextView(pos);

 // Tell the view that it's got a new data set

if (pView)

pView->NewDataSet();

return TRUE;

}

Đo  la  tất ca  ca c công viê  c chuâ n bi  , tô  chƣ  c va  xƣ  ly  dƣ   li u ca lớp document, tiêp đênchng ta sẽ làm vic với lớp view đ tƣơng tác với ngƣời dng.

Điều đầu tiên cần chu  y  la  ca c include trong ca c file ma   nguồn cần theo đu  ng thƣ  tƣ   (giống ba i thƣ  c ha nh số 10): lơ   p CPerson trƣơ   c, sau đo  tơ   i lơ   p document va  cuôi cu  ng la  lơ   pview va  ca c ch  thi  include na y ch  thƣ  c hiê  n trong ca c file ca i đă   t lơ   p (khác với C /C++ thôngthƣơ   ng)

#include "stdafx.h"

#include "Serialize.h"

#include "Person.h"

#include "SerializeDoc.h"

#include "SerializeView.h"

Vì số lƣợng các thao tác đối với các bản ghi là khá nhiều nên cũng giống nhƣ bài thực

hành 10 (sƣ  du  ng 1 biến lƣu điê m hiê  n ta   i cu  a con tro  chuô   t ) trong ba i thƣ  c ha nh na y đê  chotiê  n chu  ng ta thêm mô   t biến tha nh viên kiê u CPerson * c tên là m_ pCurPerson cho lơ   p View.

Page 43: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 43/96

Bài giảng môn học: Lâ   p tr  nh Windows 

36

Hàm đầu tiên mà chng ta sẽ thực hin là hàm hin th d liu , nhƣng chƣ  c năng na yđƣơ   c sƣ  du  ng trong hầu hết ca c tƣơng ta c nên chu ng ta se   l àm mt hàm riêng đ sau đ gọiđến hàm này (giống ha m Draw cu  a lơ   p CLine trong ba i thƣ  c ha nh 10 về chƣ  c năng ) (hàmprivate):

void CSerializeView::PopulateView( void)

{

 // Get a pointer to the current document

CSerializeDoc* pDoc = GetDocument();

if (pDoc)

{

 // Display the current record position in the set

m_sPosition.Format("Record %d of %d", pDoc->GetCurRecordNbr(),

pDoc->GetTotalRecords());

}

 // Do we have a valid record object?

if (m_pCurPerson)

{

 // Yes, get all of the record values

m_bEmployed = m_pCurPerson->GetEmployed();

m_iAge = m_pCurPerson->GetAge();

m_sName = m_pCurPerson->GetName();

m_iMaritalStatus = m_pCurPerson->GetMaritalStatus();

}

 // Update the display

UpdateData(FALSE);

}

Tiếp đến la   các hàm duyt qua các bản ghi , đồng thơ   i cu  ng la  ca c ha m xƣ  ly  ca c sƣ   kiê  ntƣơng ƣ  ng vơ   i ca c nu  t lê  nh:

void CSerializeView::OnBnClickedBfirst()

{

 // TODO: Add your control notification handler code here

 // Get a pointer to the current document

CSerializeDoc * pDoc = GetDocument();

if (pDoc)

{

Page 44: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 44/96

Bài giảng môn học: Lâ   p tr  nh Windows 

37

 // Get the first record from the document

m_pCurPerson = pDoc->GetFirstRecord();

if (m_pCurPerson)

{

 // Display the current record

PopulateView();

}

}

}

void CSerializeView::OnBnClickedBlast()

{

 // TODO: Add your control notification handler code here

 // Get a pointer to the current document

CSerializeDoc * pDoc = GetDocument();

if (pDoc)

{

 // Get the last record from the document

m_pCurPerson = pDoc->GetLastRecord();

if (m_pCurPerson)

{

 // Display the current record

PopulateView();

}

}

}

void CSerializeView::OnBnClickedBprev()

{

 // TODO: Add your control notification handler code here

 // Get a pointer to the current document

CSerializeDoc * pDoc = GetDocument();

if (pDoc)

{

Page 45: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 45/96

Bài giảng môn học: Lâ   p tr  nh Windows 

38

 // Get the last record from the document

m_pCurPerson = pDoc->GetPrevRecord();

if (m_pCurPerson)

{

 // Display the current record

PopulateView();

}

}

}

void CSerializeView::OnBnClickedBnext()

{

 // TODO: Add your control notification handler code here

 // Get a pointer to the current document

CSerializeDoc * pDoc = GetDocument();

if (pDoc)

{

 // Get the last record from the document

m_pCurPerson = pDoc->GetNextRecord();

if (m_pCurPerson)

{

 // Display the current record

PopulateView();

}

}

}

Tiếp đến chu  ng ta cần mô   t ha m reset la   i lơ   p view mô  i khi mô  t ba n ghi mơ   i đƣơ   c bắt đầuhoă  c đƣơ   c mơ   đê  ngƣơ   i không tiếp tu  c nh n thấy tâ    p ba n ghi cu   . Chng ta c th gọi tới hàmxƣ  ly  sƣ   kiê  n cu  a nu  t First đê  buô  c lơ   p view đƣa ra ba n ghi đầu tiên trong tâ    p ba n ghi . Đê  la mđiêu na y chu  ng ta thêm mô   t ha m void (pubic) tên la  NewDataSet nhƣ sau:

void CSerializeView::NewDataSet(void)

{

OnBnClickedBfirst();

}

Page 46: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 46/96

Bài giảng môn học: Lâ   p tr  nh Windows 

39

Đến đây chu  ng ta co  thê  di  ch va  cha  y chƣơng tr nh nhƣng ca c ba  n se   thấy ch  ca c ca cnt duyt qua các bản ghi là c tác dng cn các điều khin khác ca form là không c tácdng gì. Điêu na  y la  do chu  ng ta chƣa co  ca c ha m xƣ  ly  ca c điều khiê n trên form . Cần thêmcác hàm xư lý các sự kin với các điều khin trên form chƣơng trình nhƣ sau :

Hàm xư lý dấu check Employed :

void CSerializeView::OnBnClickedCbemployed()

{

 // TODO: Add your control notification handler code here

UpdateData(TRUE);

 // If we have a valid person object, pass the data changes to it

if (m_pCurPerson)

m_pCurPerson->SetEmployed(m_bEmployed);

}

hàm xư lý các sự kin cho các nt Radio :

void CSerializeView::OnBnClickedMaritalstatus()

{

 // TODO: Add your control notification handler code here

UpdateData(TRUE);

 // If we have a valid person object, pass the data changes to it

if (m_pCurPerson)

m_pCurPerson->SetMaritalStat(m_iMaritalStatus);

}

Đối với các trƣờng tên và tuổi chng ta cần xư lý sự kin EN _CHANGE va  go   i tơ   i ca chàm SetName, SetAge tƣơng ƣ  ng cu  a lơ   p CPerson nhƣ sau :

void CSerializeView::OnEnChangeEname()

{

 // TODO: Add your control notification handler code here

UpdateData(TRUE);

 // If we have a valid person object, pass the data changes to it

if (m_pCurPerson)

m_pCurPerson->SetName(m_sName);

}

void CSerializeView::OnEnChangeEage()

{

Page 47: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 47/96

Bài giảng môn học: Lâ   p tr  nh Windows 

40

 // TODO: Add your control notification handler code here

UpdateData(TRUE);

 // If we have a valid person object, pass the data changes to it

if (m_pCurPerson)

m_pCurPerson->SetAge(m_iAge);

}

Hãy dch chy thư và nhập d liu vào đ thấy các chức năng ca chƣơng trình đã chyđu  ng (đây qua  la  mô  t ba i thƣ  c ha nh không dê   da ng).

3. Quản l file và thƣ mục nâng cao 

Bài tập: 

Bài tập 1: Viết chƣơng trình mô phng tìm kiếm file. 

Bài tập 2: Viết chƣơng trình lit kê tất cả các thông tin về các file và thƣ mc trong mt thƣmc. 

Page 48: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 48/96

Bài giảng môn học: Lâ   p tr  nh Windows 

41

Chƣơng 3: Hê   thô ng CSDL Registry 

1. Khái niệm và vai trò của CSDL Registry 

1.1 Các kha, các hive 

Registry là nơi lƣu tr tất cả các các loi cấu trc d liu. 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 dng dựa trênWin32, và các thiết lập ngƣời dng khác đều đƣợc lƣu trong Registry.  

Ví d, bất cứ mt 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à chy) khởi to ngay và làm thay đổi luôn cấu hình trong Registry.

Registry lƣu tr tất cả các thiết lập về cấu trc b nhớ, phần cứng, thiết b ngoi vi, vàcác thành phần liên quan đến mng. Bn sẽ tìm thấy ở đ nhiều hơn nhng thiết lập cần thiếttrong các tp khởi to ban đầu 

Từ Win98 về sau, Windows c sư dng Registry Checker đ tự quét Registry, nếukhông thấy gì, n tự lƣu backup mt lần trong ngày, nếu tìm thấy li sẽ sưa... c th sưa bằng

cách thay thế bản Registry đã backup gần nhất cn tốt. Registry Checker tối ƣu hoá và nénfile backup thành công mi lần khởi đng máy. N cn làm mt lot các vic linh tinh nhƣloi b nhng khoảng trống không dng trong Registry, tối ƣu hoá... 

Page 49: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 49/96

Bài giảng môn học: Lâ   p tr  nh Windows 

42

Các tp Registry ca Windows. 

Registry hin ti bao gồm 3 tp chính: 

1. Tp USER.DAT 

Dng đ lƣu tr nhng xác lập ngƣời sư dng đối với các phần mềm. 

2. Tp SYSTEM.DAT 

Dng đ lƣu tr nhng xác lập liên quan tới máy tính và phần cứng. 

3. Tp Policy.pol 

System policies đƣợc thiết kế đ chuẩn b cho vic ghi đè bất cứ thiết lập đã đƣợc chứatrong 2 thành phần registry khác nhau.

System policies c th chứa d liu bổ sung đc trƣng tới mng hay môi trƣờng tổ hợpnhƣ đã đƣợc cài đt bởi network administrator. Bản thân System policies cũng đã đƣợc chứatrong tp Policy.pol. Không nhƣ SYSTEM.DAT và USER.DAT, Policy.pol không phải làthành phần bắt buc ca phần cài đt Windows. 

Các kha chính trong mt CSDL Registry: 

+ HKEY_LOCAL_MACHINE chứa các thông tin về cấu hình vật lý ca h thống cng

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 ca tài khoản ngƣời dng  

+ HKEY_CURRENT_CONFIG: chứa các thông tin thiết lập ca h thống hin tichẳng hn 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 kiu file sang các ứng dngmở chng. 

HKEY_CURRENT_USER: chứa các thông tin về các tài khoản trên h thống, chẳnghn nhƣ các biến môi trƣờng, các máy in và các ty chọn ứng dng khác. 

1.2 Các kiểu dữ liệu 

Lời khuyên của Microsoft về những công cụ xư l registry 

Page 50: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 50/96

Bài giảng môn học: Lâ   p tr  nh Windows 

43

Phƣơng pháp  Thiết lập 

Control PanelPhần lớn thiết lập h thống SYSTEM. Ví d bn sư dng DisplayProperties đ sưa các thành phần ca mc appearance 

System Policy Editor Thiết lập ngƣời dng, vài thiết lập h thống. 

Các chƣơng trình tin ích thứ 3  Thiết lập chi tiết ứng dng Bn c th đã sư dng Registry Editor đ thay đổi Registry bằng tay. Tôi thƣờng dng

 Norton Registry Editor vì n cn c thêm chức năng khác, ví d nhƣ tìm và thay thế đối vớicác thành phần ca Registry. 

Từ các phần mềm Registry Editor trên, ta nhận thấy registry đƣợc bố trí thành cácnhánh lớn. Ti mi nhánh c các khoá SUBKEY. Ti các SUBKEY d liu đƣợc lƣu ở cácdng: 

1. String (Dng chui) 

2. Numeric (Dng số) 3. Binary (Dng nh phân) 

4. Expanded String (Dng chui mở rng) 

5. MultiString (Dng chui tổng hợp) 

(Nếu bn dng Registry Editor - REGEDIT. EXE thì sẽ gọi tên khác là DWORD) 

2. Quản l CSDL Registry 

Khi lập trình đối với Registry, bn phải thực hin hết sức thận trọng, sao lƣu các tp nàythƣờng xuyên đ tránh li đáng tiếc, phải mất công cài li thì cũng rất mất thời gian.Sư dng

các hàm API đối với Registry cũng xin hết sức thận trọng.  

2.1 Thay đô  i kho  a 

Đ thay đổi giá tr ca mt kha trong CSDL Registry chng ta sư dng hàm LONGRegSetValueEx(HKEY hKey, LPCTSTR lpValueName, DWORD reserved, DWORDdwType, CONST BYTE * lpData, CONST cbData).

2.2 Thêm mơ   i kho  a 

Đ làm vic với các kha trong CSDL Registry đầu tiên chng ta sẽ quan tâm tới cáchàm thêm kha mới: LONG RegOpenKeyEx(HKEY hKey, LPCTSTR lpSubKey, DWORD

ulOptions, REGSAM samDesired, PHKEY phkResult). Trong đ tham số thứ nhất là handletr tới kha đang mở, tham số phkResult tr tới mt biến c kiu HKEY cho kha c th mớ mới, lpSubKey là tên ca subkey mà chng ta muốn mở, thông thƣờng c th là mt đƣờngdẫn chăng hn nhƣ “Microsoft \WindowsNT\ CurrentVersion”. Giá tr NULL cho biến này cnghĩa là mt kha bằng giá tr hKey sẽ đƣợc sinh ra. Biến ulOptions là biến dự tr và c giátr bằng 0. Biến samDesired là mt n truy cập mô tả giá tr bảo mật cho kha mới, c th làkết hợp ca các giá tr hằng số KEY_ALL_ACCESS, KEY_WRITE,KEY_QUERY_VALUE, KEY_ENUMERATE_SUBKEYS. Giá tr trả về ca hàm thƣờng làERROR_SUCCESS. Cũng c th dng hàm LONG RegCreateKeyEx( HKEY hKey,LPCTSTR lpSubKey, DWORD Reserved, LPTSTR lpClass, DWORD dwOptions, REGSAMsamDesired, PSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult,LPDWORD lpdwDisposition) đ to kha mới. 

Page 51: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 51/96

Bài giảng môn học: Lâ   p tr  nh Windows 

44

2.3 Liê    t kê ca  c kho  a 

Hàm lit kê các kha trong CSDL Registry là hàm LONG RegEnumKeyEx(HKEYhKey, DWORD dwIndex, LPTSTR lpName, LPDWORD lpcbName, LPDWORDlpReserved, LPTSTR lpClass, LPDWORD lpcbClass, PFILETIME lpftLastWriteTime).

3. Can thiê   p Windows qua Registry 

Hầu nhƣ tất cả các thay đổi, thiết lập ca Windows đều c th đƣợc thực hin thông quavic thiết lập các giá tr trong CSDL Registry, vấn đề cốt lõi là chng ta cần nắm đƣợc khavà giá tr cần thay đổi tƣơng ứng. 

3.1 Thay đô  i giao diê   n 

Đ ngăn cấm không cho ngƣời dng thay đổi Wallpaper chng ta c th thay đổi giá trkha:“HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/policies/ActiveDeskto

 p” với giá tr DWORD là 1. 

Đ chỉ đnh file Wallpaper ca Windows ta c th sưa các kha“HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\ System” với các kha là Wallpaper, WallpaperStyle và giá tr kiu REG_SZ (String) là đƣờngdẫn tới file ảnh. 

3.2 Thay đô  i ca  c thiê  t lâ   p đô  i vơ   i ca  c ô  đ  a 

Đ thay đổi thiết lập với các ổ đĩa ta thực hin với các khaHKEY_LOCAL_MACHINE\SYSTEM\ MountedDevices c tên là MountedDevices nhƣ hìnhsau:

3.3 Thay đô  i ca  c thiê  t lâ   p vơ   i ngƣơ    i du  ng 

Các biến môi trƣờng ca mt ngƣời dng nằm trong phần

“HKEY_CURRENT_USER\Environment”, cn cho cả h thống nằm trong phần“HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SessionManager\Environment”.

Bài tập: 

Bài tập 1: Viết chƣơng trình thay đổi giao din Windows bằng cách sư dng can thip quaRegistry.

Bài tập 2: Viết chƣơng trình thay đổi các biến môi trƣờng ca Windows bằng cách sư dngcan thip qua Registry. 

Page 52: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 52/96

Bài giảng môn học: Lâ   p tr  nh Windows 

45

Chƣơng 4: Quản l các tiê n tr  nh va   luô  ng 

1. Các tiến trình và lung trên Windows 

Tất cả các tiến trình (process) ca Windows đều c mt hoc nhiều luồng (thread) vàluồng chính là đơn v thực thi cơ sở nhất ca Windows. Các luồng đƣợc lập lch dựa trên các

nhân tố: sự sn sàng ca các tài nguyên nhƣ CPU và b nhớ vật lý, đ ƣu tiên. Windows htrợ kiến trc đa xư lý đối xứng SMP (Symmetric MultiProcessing) bắt đầu từ phiên bản NT4,do đ các luồng c th chy trên cac CPU riêng rẽ trong cng mt h thống.  

Trên quan đim ca lập trình viên mi tiến trình sẽ bao gồm các tài nguyên:  

+ Mt hoc nhiều luồng 

+ Mt không gian b nhớ ảo riêng.

+ Mt hoc nhiều đon mã, bao gồm ca các đon mã trong các file DLL. 

+ Mt hoc nhiều phân đon d liu chứa các d liu toàn cc. 

+ Các giá tr biến môi trƣờng 

+ Vng nhớ Heap 

+ Các tài nguyên khác chẳng hn nhƣ các handle và các heap đã mở sn. 

Mi luồng trong mt tiến trình sẽ chia sẻ mã chƣơng trình, các biến toàn cc, các biếnmôi trƣờng, các tài nguyên. Mi luồng sẽ đƣợc lập lch mt cách riêng rẽ và c các thành

 phần sau: 

+ Mt ngăn xếp các lời gọi tới các th tc, các ngắt, các quản lý bit l, và b nhớ  

+ Mt mảng TLS (Threa Local Storage) các con tr đ c th cấp phát b nhớ lƣu trd liu cho luồng. 

+ Mt tham số trên stack,  từ lc bắt đầu to ra luồng, đƣợc sư dng riêng cho miluồng. 

+ Mt cấu trc ng cảnh, đƣợc quản lý bởi nhân. 

Page 53: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 53/96

Bài giảng môn học: Lâ   p tr  nh Windows 

46

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

2.1. Tạo tiến trình 

Hàm cơ bản đ quản lý các tiến trình ca Windows là hàm CreateProcess(), hàm này tora mt tiến trình với mt luồng đơn. Tham số mà hàm cần là tên file chƣơng trình sẽ thựchin. Chng ta c th thấy c nhiều đề cập tới khái nim tiến trình cha, tiến trình con nhƣngthực sự thì quan h này không đƣợc quản lý bởi Windows. Windows đơn thuần chỉ tham

chiếu tới các tiến trình ti ra mt 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,

DWORD dwCreationFlags,LPVOID lpEnvironment,

Page 54: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 54/96

Bài giảng môn học: Lâ   p tr  nh Windows 

47

LPCTSTR lpCurDir,

LPSTARTUPINFO lpStartupInfo,

LPPROCESS_INFORMATION lpProcInfo)

2.2. Kê t thu  c va   thoa  t kho  i mô    t tiê n tr  nh 

Sau khi tiến trình kết thc, tiến trình, hay chính xác hơn là mt luồng chy trong tiếntrình sẽ gọi tới hàm ExitProcess() đ kết thc tiến trình. Hàm này không trả về giá tr mà thayvào đ sẽ kết thc tất cả các luồng ca tiến trình. Hàm c th gọi tới đ lấy mã kết thc mttiến trình là GetExitCodeProcess(). 

2.3. Các thao tác với biến môi trƣờng của Windows 

Đ thao tác với các biến môi trƣờng ca Windows ta dng hai hàm sau: 

DWORD GetEnvironmentVariable (

LPCTSTR lpName,

LPTSTR lpValue,

DWORD cchValue)

BOOL SetEnvironmentVariable (

LPCTSTR lpName,

LPCTSTR lpValue)

2.4. V dụ: Ghi nhâ   t ky  thơ    i gian thƣ    c hiê   n cu  a ca  c tiê n tr  nh 

#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;

OSVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);

Page 55: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 55/96

Bài giảng môn học: Lâ   p tr  nh Windows 

48

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);

} else {

Page 56: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 56/96

Bài giảng môn học: Lâ   p tr  nh Windows 

49

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

...

}

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

CloseHandle (hProc);

return 0;

}

3. Quản l lung (thread) trên Windows

3.1. Các khái niệm cơ bản 

Trong phần trƣớc chng ta đã xem xét cách thức mt luồng thực hin kết thc mt tiếntrình. Các luồng trong mt tiến trình chia sẻ chung d liu và mã lnh, vì thế về bản chất các

luồng đ cũng c vng nhớ riêng ca chng. Windows đáp ứng điều này bằng mt số cáchsau:

+ Mi luồng c mt stack ca 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 mt biến, con tr, tới thời gian to ra luồng.  

+ Mi luồng c th cấp phát TLS ca riêng n. 

3.2. Mô h  nh Boss / Worker va   ca  c mô h  nh kha  c 

Lnh grepMT minh họa cho mô hình Boss/Worker. Luồng boss (luồng chính) sẽ gáncác tác v cho luồng worker đ thực hin. Mi luồng worker sẽ đƣợc cho mt file đ tìm kiếm

và worker sẽ trả về giá tr ca n cho boss thread. Xem thêm ví d sắp xếp trn đ hiu rõ môhình này.

3.3. Bô   nhơ   da  nh cho luô  ng 

Các luồng c th cần phải cấp phát và quản lý b nhớ ca riêng n và bảo v các vngnhớ đ khi các luồng khác. Điều này đƣợc thực hin qua các TLS, c th minh họa bằnghình vẽ sau: 

Page 57: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 57/96

Bài giảng môn học: Lâ   p tr  nh Windows 

50

3.4. Độ ƣu tiên và các trạng thái của lung 

Các luồng thuc về nhân ca Windows luôn c đ ƣu tiên cao nhất khi sn sàng đ thựchin. Mt luồng đƣợc coi là không sn sàng đ thực hin nếu n ở trng thái chờ, treo, hay b

 block bởi mt lý do nào đ. 

4. Mô    t sô  v  du    vê   tiê n tr  nh va   luô  ng 

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

#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,

ProcFile [iProc].TempFile); /* For search results. */ hTempFile = /* This handle is inheritable */ 

Page 58: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 58/96

Bài giảng môn học: Lâ   p tr  nh Windows 

51

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);

CreateProcess (NULL, CommandLine, NULL, NULL,

TRUE, 0, NULL, NULL, &StartUp, &ProcessInfo);

WaitForSingleObject (ProcessInfo.hProcess, INFINITE);

CloseHandle (ProcessInfo.hProcess);

Page 59: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 59/96

Bài giảng môn học: Lâ   p tr  nh Windows 

52

CloseHandle (ProcessInfo.hThread);

}

CloseHandle (hProc [iProc]);

DeleteFile (ProcFile [iProc].TempFile);

}

free (ProcFile);

free (hProc);

return 0;

4.2. Thuâ    t toa  n să  p xê p trô   n bă  ng đa luô  ng 

#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;

LPRECORD pRecords = NULL;

Page 60: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 60/96

Bài giảng môn học: Lâ   p tr  nh Windows 

53

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;

ThreadHandle [iTh] = (HANDLE) _beginthreadex (NULL, 0,

ThSort, &ThArg [iTh], CREATE_SUSPENDED, &ThId);

}

Page 61: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 61/96

Bài giảng môn học: Lâ   p tr  nh Windows 

54

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;

}

_endthreadex (0);

Page 62: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 62/96

Bài giảng môn học: Lâ   p tr  nh Windows 

55

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ài tập 1: Viết chƣơng trình hin th tất cả các thông tin về tiến trình và luồng ca mt tiếntrình đang chy. 

Page 63: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 63/96

Bài giảng môn học: Lâ   p tr  nh Windows 

56

Chƣơng 5: Các dch vụ của Windows 

1. Tô ng quan vê   di    ch vu    trên Windows 

Các dch v ca Windows, ban đầu đƣợc gọi là các dch v NT, cung cấp khả năngquản lý đi hi các chƣơng trình theo kiu server phải đƣợc chy trên dng lnh, hoc vào

thời đim h thống khởi đng, trƣớc khi bất cứ ngƣời dng nào đăng nhập, và cũng c ththực hin tm dừng, khôi phc, kết thc. Các dch v đƣợc đƣa ra nhằm đáp ứng yêu cầu này.  

Đ quản lý các dch v chng ta c th dng công c Service Control Manager đƣợ cung cấp sn bởi Windows, công c này sẽ thực hin ba bƣớc đ quản lý mt dch v: 

+ Gọi tới hàm main() ca dch v 

+ Chuyn đổi từ hàm main() sang hàm ServiceMain() 

+ Ghi các con tr quản lý đ c th đáp ứng li các lnh từ SCM  

2. Các thành phần của một dch vụ 

2.1 Hàm main()

Hàm này đƣợc gọi bởi SCM, c nhim v là khai báo dch v với SCM và bắt đầu thựchin công vic ca mt dch v. 

2.2 Hàm ServiceMain()

Hàm ServiceMain() là mt dng tƣơng tự nhƣ hàm main() với các tham số tƣơng tự, nthực hin các tác v chính ca mt dch v. 

2.3 Kiê m soa  t di    ch vu    qua ca  c Handler 

Đ kim soát dch v, chng ta sư dng các hàm sau: 

DWORD WINAPI HandlerEx (

DWORD dwControl,

DWORD dwEventType,

Page 64: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 64/96

Bài giảng môn học: Lâ   p tr  nh Windows 

57

LPVOID lpEventData,

LPVOID lpContext)

3. V du: dch vụ đơn giản trên Windows 

#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;

}

 /* ServiceMain entry point, called when the service is created. */ 

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

Page 65: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 65/96

Bài giảng môn học: Lâ   p tr  nh Windows 

58

{

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;

}

Page 66: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 66/96

Bài giảng môn học: Lâ   p tr  nh Windows 

59

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:

if (Control > 127 && Control < 256) /* User defined. */ 

Page 67: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 67/96

Bài giảng môn học: Lâ   p tr  nh Windows 

60

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;

}

4. Quản l các dch vụ của Windows 

4.1 Các phƣơng pháp kiểm soát các dch vụ của Windows 

Đ quản lý các dch v ca Windows ta c hai cách: mt là dng công c SCM, hai làgõ trực tiếp các lnh trên dng lnh. 

4.2 V dụ : Điê  u khiê n ca  c di    ch vu    cu  a Windows 

#include "EvryThng.h"

static SC_HANDLE hScm;

static BOOL Debug;

int _tmain (int argc, LPTSTR argv [])

{

BOOL Exit = FALSE;

TCHAR Command [MAX_COMMAND_LINE + 10], *pc;

Page 68: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 68/96

Bài giảng môn học: Lâ   p tr  nh Windows 

61

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;

TCHAR CurrentDir [MAX_PATH + 1], Executable [MAX_PATH + 1];

Page 69: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 69/96

Bài giảng môn học: Lâ   p tr  nh Windows 

62

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);

CloseServiceHandle (hSc);

Page 70: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 70/96

Bài giảng môn học: Lâ   p tr  nh Windows 

63

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);

if (dwControl == SERVICE_CONTROL_INTERROGATE) {

QueryServiceStatus (hSc, &ServiceStatus);

Page 71: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 71/96

Bài giảng môn học: Lâ   p tr  nh Windows 

64

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ài tập 1: Viết dch v ghi li nhật ký các lần login và sư dng h thống trên Windows. 

Bài tập 2: Viết chƣơng trình quản lý các dch v ca Windows.

Page 72: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 72/96

Bài giảng môn học: Lâ   p tr  nh Windows 

65

Chƣơng 6: Lâ   p trình Socket 

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

Socket: là mt thực th logic đi din cho kết nối gia các máy tính trên mt h thốngmng. Tất ca  ca c truyền thông giƣ  a ca c ma y t nh trên mô  t hê  thống ma  ng đƣơ   c thƣ  c hiê  n

thông qua socket . C hai mô hình lập trình mng : mô h nh client / server va  mô h nh peer  2peer (mng ngang hàng).

Theo mô h nh client /server:

Server: mơ   mô   t di  ch vu   bằng ca ch ta  o ra mô   t đôi tƣơ   ng ServerSocket vơ   i tham sô la  đi  achỉ cô ng đê  kêt nôi , sau đo  nhâ  n kêt nôi tƣ  ph a client bằng ca ch sƣ  du  ng ha m accept (), lấycác luồng d liu vào / ra cu  a client đê  thƣ  c hiê  n truyền dƣ   liê  u , thƣ  c hiê  n ca c xƣ  ly  cần thiết ,trả kết quả cho client và đng kết nối tơ   i client, dch v kết thc.

2. Các hàm sockets pha server 

Các hàm socket phía server mà chng 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);

V dụ: 

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);AddrLen = sizeof (ConnectAddr);

Page 73: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 73/96

Bài giảng môn học: Lâ   p tr  nh Windows 

66

sockio = accept (SrvSock,

(struct sockaddr *) &ConnectAddr, &AddrLen);

... Receive requests and send responses ...

shutdown (sockio);

closesocket (sockio);

3. Các hàm sockets pha client 

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));

4. Ưng dụng mang đơn giản

4.1 Pha server 

#define _NOEXCLUSIONS

#include "EvryThng.h"

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

struct sockaddr_in SrvSAddr;

Page 74: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 74/96

Bài giảng môn học: Lâ   p tr  nh Windows 

67

 /* 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;

srv_arg [ith].dlhandle = hDll; srv_arg [ith].srv_thd = NULL;

Page 75: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 75/96

Bài giảng môn học: Lâ   p tr  nh Windows 

68

}

 /* 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. */ 

hAcceptTh = (HANDLE)_beginthreadex (NULL, 0, AcceptTh,

&srv_arg [ith], 0, &ThId);

Page 76: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 76/96

Bài giảng môn học: Lâ   p tr  nh Windows 

69

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);

pThArg->sock = accept (SrvSock, /* This is a blocking call. */ 

Page 77: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 77/96

Bài giảng môn học: Lâ   p tr  nh Windows 

70

(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,

FILE_SHARE_READ | FILE_SHARE_WRITE, &TempSA,

CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

Page 78: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 78/96

Bài giảng môn học: Lâ   p tr  nh Windows 

71

 /* 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);

closesocket (ConnectSock);

Page 79: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 79/96

Bài giảng môn học: Lâ   p tr  nh Windows 

72

pThArg->status = 1;

if (strcmp (Request.Record, "$ShutDownServer") == 0) {

pThArg->status = 3;

ShutFlag = TRUE;

}

return pThArg->status;

}

4.2 Pha client 

#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. */ 

CHAR DefaultIPAddr [] = "127.0.0.1"; /* Local system. */ 

Page 80: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 80/96

Bài giảng môn học: Lâ   p tr  nh Windows 

73

 /* 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);

WSACleanup ();

Page 81: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 81/96

Bài giảng môn học: Lâ   p tr  nh Windows 

74

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

return 0;

}

5. Windows Sockets 2.0

Là phiên bản mới nhất ca Windows cho lập trình mng theo mô hình socket.  

Bài tập: 

Bài tập 1: Viết chƣơng trình client/server cho phép client nhập vào mt xâu, gưi sang server,server sẽ trả về số từ c trong xâu. 

Page 82: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 82/96

Bài giảng môn học: Lâ   p tr  nh Windows 

75

Chƣơng 7: Thƣ viê   n liên kê t đô   ng 

Các thƣ vin liên kết đng Dynamic -link Libararies la  mô   t trong ca c phần tƣ  quan tro  ngnhât cu  a hê  điều ha nh Windows . Hầu hết ca c thao ta c truy câ    p đ  a cƣ  ng trên Windows đềuđƣơ   c thƣ  c hiê  n bơ   i ca c chƣơng tr nh hoă  c ca c file liên kết đô  ng . Cho đên thơ   i điê m na y chu  ngta đa

  viết rất nhiều c ác chƣơng trình và bây giờ là lc chng ta xem xét vic viết các thƣ vin

liên kết đô  ng. Rất nhiều nguyên tắc trong viê  c viết ca c chƣơng tr nh cu  ng đƣơ   c a  p du  ng trongviê  c viết ca c thƣ viê  n song co  mô  t số thay đô  i quan tro  ng.

7.1. Khái niệm và ứng dụng của thƣ viện liên kết động 

 Nhƣ ca c ba  n thấy mô  t chƣơng tr nh trên Windows la  mô   t file cha  y thƣơ   ng ta  o ra mô  thoă  c mô   t sô cƣ  a sô  chƣơng tr nh va  sƣ  du  ng mô   t vo ng lă    p thông điê    p đê  nhâ  n ca c thông tininput tƣ  ngƣơ   i du  ng . Các thƣ vin liên kết đng thƣờng không phải là các file chy trực tiếpvà chng thƣờng không nhận các thông đip . Chng thƣờng là các file riêng bit chứa cáchàm c th đƣợc gọi bởi các chƣơng trình  và các thƣ vin khác đ thực hin mt công vic c

thê 

na o đo  . Mô   t thƣ viê  n liên kết đô  ng thƣơ   ng đƣơ   c na    p va o mô   t nhơ   đê 

thƣ  c hiê  n khi mô  tmodule chƣơng trình khác gọi tới mt hàm trong thƣ vin .

Thuâ   t ngƣ   liên kết đô   ng “dynamic link” đề câ    p tơ   i qua  tr nh ma  Windows sƣ  du  ng đê  liên kêt mô   t lơ   i go   i ha m trong mô  t module chƣơng tr nh vơ   i ca c ha m thƣ  c sƣ   năm trong mô   tthƣ viê  n liên kết đô  ng. Các liên kết tĩnh đƣợc thực hin khi trình biên d ch tiến hành bƣớc liênkết (link) các file object (.obj), các thƣ vin run-time (*.lib) và sư dng mt chƣơng trình biêndch tài nguyên đ to thành mt file chy .exe. Quá trình liên kết đng không din ra vào lc

 biên di  ch và liên kết chƣơng trình mà din ra vào lc chƣơng trình chy .

7.2. Hệ thống thƣ viện liên kết động của Windows 

Các thƣ vin Kernel 32.dll, user32.dll va  gdi 32.dll, rât nhiêu ca c file điều khiê n kha cchă ng ha  n nhƣ keyboard .drv, system.drv và mouse .drv cu  ng nhƣ ca c tr nh điều khiê n cardmàn hình và máy in đều là các thƣ vin liên kết đng . Các thƣ vin này đều alf các thƣ vinmà hầu hết các chƣơng trình trên Windows đều sư dng .

Mô   t va i thƣ viê  n liên kết đng (chă ng ha  n nhƣ ca c font chƣ   ) đƣơ   c go   i la  ca c thƣ viê  n ta inguyên (resource only ). Các thƣ vin này chỉ chứa d liu (thƣơ   ng la  dƣơ   i da  ng ca c ta inguyên) và không chứa mã chƣơng trình . Do đo  mô   t trong ca c mu  c đ ch cu  a c ác thƣ vin liênkết đô  ng la  cung cấp ca c ha m va  ca c ta i nguyên co  thê  đƣơ   c sƣ  du  ng bơ   i ca c chƣơng tr nhkhác. Trong ca c hê  điêu ha nh nga y xƣa (kiê u nhƣ DOS) chỉ c h điều hành mới chứa các th

tc mà các chƣơng trìn h kha c co  thê  go   i đên đê  hoa n tha nh mô   t công viê  c g  đo  . TrênWindows qua  tr nh mô   t module chƣơng tr nh go  i tơ   i mô   t ha m trong mô   t module chƣơng tr nhkhác là rất thƣờng xuyên . Bằng ca ch viết ca c Dll chu ng ta co  thêm ca c mơ    rô  ng cho hê  điềuhành.

Mă  c du  mô   t module thƣ viê  n liên kết đô  ng co  thê  co  bất cƣ  phần tên mơ   rô  ng na o(chă ng ha  n nhƣ .exe hay .com) nhƣng phần tên mơ   rô  ng chuâ n cu  a ca c thƣ viê  n liên kết đô  ngtrên Windows la   .dll. Chỉ c các thƣ vin liên kết đng c phần tên mở rng là dll mới đƣợc tựđô  ng na    p va o bô   nhơ   bơ   i Windows ca c thƣ viê  n co  phần tên mơ   rô  ng kha c se   đƣơ   c na    p thôngqua viê  c go  i tơ   i ca c ha m LoadLibrary hoă  c LoadLibraryEx .

Chng ta thƣờng thấy các thƣ vin liên kết đng đƣợc sư dng trong các chƣơng trìnhlơ   n. Chă ng ha  n nhƣ chu  ng ta viết mô   t go  i phân mềm kế toa n lơ   n chƣ  a mô  t va i chƣơng tr nhkhác nhau. Các chƣơng trình này sư dng nhiều th tc chung  do đo  chu  ng ta co  thê  kết hơ     p

Page 83: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 83/96

Bài giảng môn học: Lâ   p tr  nh Windows 

76

các hàm này vào mt thƣ vin liên kết tĩnh (*.lib) sau đo  thêm va o mô  i module chƣơng tr nhtrong qua  tr nh biên di  ch ca c chƣơng tr nh na y . Tuy nhiên ca ch tiếp câ  n đo  se   la  la  ng ph  v  mô  i chƣơng tr nh se   chƣ  a ca c đoa  n ma   giống nhau va  hơn nƣ  a nếu chu  ng ta thay đô  i mô   t ha mnào đ trong thƣ vin chng ta sẽ phải liên kết li tất cả các chƣơng trình c sư dng thƣ vinđo  . Nhƣng nếu chu  ng ta cho tất ca  ca c ha m  đo  va o mô   t thƣ viê  n liên kết đô  ng chă ng ha  n nhƣ

account.dll chă ng ha  n th  se   gia i quyết đƣơ   c ca  hai vấn đề trên . Chỉ c module cần thiết chứatất ca  ca c ma   cu  a ca c ha m đƣơ   c sƣ  du  ng bơ   i tất ca  ca c chƣơng tr nh điêu na  y se   đo  i ho  i  tkhông gian đ  a cƣ  ng hơn va  đồng thơ   i đo  i ho  i  t bô   nhơ   hơn khi nhiều chƣơng tr nh cu  ng cha  yđồng thơ   i, hơn nƣ  a chu  ng ta co  thê  thay đô  i ca c ca i đă   t cu  a ca c ha m trong thƣ viê  n ma  khôngcân thiết pha i liên kết la   i thƣ viê  n vơ   i ca c chƣơng tr nh.

Các thƣ vin liên kết đng cũng c th là cá sản phẩm thƣơng mi , hiê  n nay co  rất nhiềuhãng chuyên cung cấp các hàm thƣ vin dành cho phát trin mt loi sản phẩm phần mềm nàođo    chă ng ha  n nhƣ DirectX la  mô   t tâ    p ca c thƣ viê  n liên kết đô  ng da nh cho viê  c viết ca cchƣơng tr nh đô ho  a cao cấp.

Thƣ viê   n: mô    t lơ    i nga  n y  . (One word, many meanings) 

Mô   t phân ca c nhầm lâ  n đôi vơ   i ca c thƣ viê  n liên kết đô  ng là vic sư dng ca thuật ngthƣ viê  n (library) trong mô   t số ca c khung ca nh kha c nhau . Bên ca  nh ca c thƣ viê  n liên kếtđô  ng chu  ng ta co n no  i đên ca c thƣ viê  n đối tƣơ   ng va  ca c thƣ viê  n import.

Mô   t thƣ viê  n đối tƣơ   ng la  mô   t  file co  phân mơ   rô  ng la    .lib chƣ  a ca c đoa  n ma   chƣơngtrình sẽ đƣợc thêm vào file .exe trong qua  tr nh liên kết t  nh . Chă ng ha  n trong VC++ thƣ viê  nđôi tƣơ   ng run-time thƣơ   ng liên kết vơ   i ca c chƣơng tr nh la  libc.lib.

Mô   t thƣ vin import là mt dng đc bit ca các file thƣ vin đối tƣợng . Giống nhƣ ca c

thƣ viê  n đối tƣơ   ng ca c thƣ viê  n import co  phân mơ   rô  ng la   .lib va  đƣơ   c sƣ  du  ng bơ   i tr nh biêndch đ giải quyết các lời gọi hàm trong các c hƣơng tr nh cu  a chu  ng ta viết ra . Tuy nhiên ca cthƣ viê  n import na y không chƣ  a ca c ma   chƣơng tr nh . Thay va o đo  chu ng cung cấp cho tr nhliên kết ca c thông tin cần thiết đe  thiêt lâ    p ca c ba ng chuyê n (relocation table) trong file .exe đê  thƣ  c hiê  n ca c liên kết đô  ng . Các file kernel 32.lib, user32.lib, gdi32.lib đi ke m vơ   i ca c tr nh

 biên di  ch cu  a Microsoft đều la  ca c thƣ viê  n import . Nếu chu  ng ta go  i tơ   i mô   t ha m chă ng ha  nnhƣu Rectangle th  file gdi 32.lib se    báo cho trình liên kết biết rằng đ là mt hàm trong thƣviê  n liên kêt đô  ng gdi 32.dll. Thông tin na y se   đƣơ   c chƣ  a trong file chƣơng tr nh (*.exe) đWindows co  thê  thƣ  c hiê  n ca c liên kết đô  ng khi chƣơng tr nh cu  a chu  ng ta đƣơ   c thƣ  c hiê  n.

Các thƣ vin đối tƣợng và các thƣ vin import đều đƣợc sư dng trong quá trình phát

triê n ca c chƣơng tr nh . Các thƣ vin liên kết đng đƣợc sư dng trong quá trình chƣơng trìnhchy. Mô   t thƣ viê  n liên kêt đô  ng phải sn c trên đĩa đ chƣơng trình c th sư dng n khichy. Khi Windows cần na    p mô   t module DLL trƣơ   c khi cha  y mô   t chƣơng tr nh đo  i ho  i sƣ   dng hàm trong n file thƣ vin phải nằm cng thƣ mc với file .exe, trong thƣ mu  c hiê  n thơ   i,trong thƣ mu  c system cu  a hê  điều ha nh hoă  c nằm trong thƣ mu  c co  trong biến môi trƣơ   ngPATH cu  a hê  điêu ha nh (hê  điều ha nh se   tiên ha nh t m kiêm thƣ viê  n theo thƣ  tƣ   đo  ).

7.3. Các bƣớc tạo một thƣ viện DLL 

Mă  c du  ý tƣởng ca các thƣ vin liên kết đng là c th sư dng với nhiều ứng dngnhƣng chu  ng ta se   viêt mô   t ƣ  ng du  ng demo sƣ  du  ng mô   t thƣ viê  n liên kết đô  ng đơn gia n .

Page 84: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 84/96

Bài giảng môn học: Lâ   p tr  nh Windows 

77

Chng ta sẽ to mt mt thƣ vin liên kết đng là edrlib .dll (Easy drawing routine ).Hàm thƣ vin này sẽ chỉ chứa mt hàm đơn giản đ thực hin công vic vẽ ra mt xâu trongứng dng demo ca chng ta .

Đê  ta  o ra mô  t thƣ viê  n liên kêt đô  ng chu  ng ta cần co  mô  t ca ch tiếp câ  n kha c s o vơ   i ca chmà chng ta vẫn dng đ viết các ứng dng . VC++ phân biê   t giƣ

  a ca

 c kha

 i niê  m “workspace”

và “project” . Mô   t project thƣơ   ng la  mô   t ƣ  ng du  ng hoă  c mô  t thƣ viê  n liên kêt đô  ng . Mô  tworkspace co  thê  gôm nhiều project . Cho đên thơ   i điê m na y chu  ng ta mơ   i ch  viêt ca cworkspace ch  co    1 project. Trong phần na y chu  ng ta se   ta  o mô   t workspace co  hai project ,mô  t cho viê  c ta  o dll va  mô   t cho viê  c go   i tơ   i file dll đo  .

Các bƣớc to ứng dng với Visual Studio .NET 2003 nhƣ sau:  

1.  To 1 Solution (Dll1 chă ng ha  n) rô  ng (Blank Solution)

2.  Thêm mô  t project chƣ  a file dll cho ƣ  ng du  ng (chọn New Project  Win32 Project) và gõ tên ca Project là SimpleDll.

3.  Trong hô    p thoa   i Application Setting chọn DLL (Application Type) vàchọn mc Empty.

4.  Thêm file ma   nguồn cho Project va  go   nô   i dung cu  a file dll va 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#endif 

Page 85: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 85/96

Bài giảng môn học: Lâ   p tr  nh Windows 

78

 /*-------------------------------------------------

simpledll.c -- Easy Drawing Routine Library module

(c) Charles Petzold, 1998

-------------------------------------------------*/ 

#include <windows.h>

#include "simpledll.h"

int WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOIDpvReserved)

{

return TRUE ;

}

EXPORT BOOL CALLBACK EdrCenterTextA (HDC hdc, PRECT prc, PCSTRpString)

{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, PCWSTRpString)

{

int iLength ;

SIZE size ;

Page 86: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 86/96

Bài giảng môn học: Lâ   p tr  nh Windows 

79

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.  To mt Project Win 32 Project, sau đo  cho  n kiê u Project la  Application, to file .c cho ƣ  ng du  ng va  go   nô   i dung ƣ  ng du  ng va 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))

{

MessageBox (NULL, TEXT ("This program requires Windows NT!"),

szAppName, MB_ICONERROR) ;

Page 87: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 87/96

Bài giảng môn học: Lâ   p tr  nh Windows 

80

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, WPARAMwParam, LPARAM lParam)

{

HDC hdc ;

PAINTSTRUCT ps ;

RECT rect ;

switch (message)

{

case WM_PAINT:

hdc = BeginPaint (hwnd, &ps) ;

GetClientRect (hwnd, &rect) ;

EdrCenterText (hdc, &rect,

TEXT ("This string was displayed by a DLL")) ;

Page 88: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 88/96

Bài giảng môn học: Lâ   p tr  nh Windows 

81

EndPaint (hwnd, &ps) ;

return 0 ;

case WM_DESTROY:

PostQuitMessage (0) ;

return 0 ;

}

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

}

6.  Đt chế đ dch là Project thứ hai ph thuô  c (dependencies) vào Project

thƣ  nhất va  thƣ mu  c Output cu  ng ta  m cu  a hai Project la   ../Release.

7.  Dch và chy chƣơng trình .

Ở đây chng ta c hai phiên bản ca mt hàm trong thƣ vin liên kết đng đƣợc sưdng, điêu na y cho phép dng các hàm c h trợ Unicode trong trƣờng hợp h thống c h trợ và ngƣợc li sư dng mt hàm không c Unicode , thƣơ   ng tên cu  a ha m se   co  thêm chƣ   W nếuc h trợ Unicode và A nếu không.

Đồng thời chng ta cũng t hây trong ma   cu  a thƣ viê  n co  mô  t ha m DllMain , hàm này cvai tro  tƣơng tƣ   nhƣ ha m WinMain trong mô   t chƣơng tr nh . Tác dng ca hàm DllMain là

khơ   i ta  o va  thu hôi bô   nhơ   va  nhƣ  ng thƣ  liên quan kha c , chng ta sẽ bàn tới vấn  đề này ở cuốichƣơng, hiê  n ta   i ch  cần return TRUE la  ô n.

Điều b  â n co n la   i co  le   la  ơ   đi  nh danh EXPORT . Các hàm trong mt thƣ vin liên kếtđô  ng đƣơ   c sƣ  du  ng bơ   i ca c ƣ  ng du  ng kha c pha i đƣơ   c xuât khâ u . Điều na y không liên quan tơ   icác vấn đề thƣơng mi thông thƣờng mà chỉ là mt chỉ th đảm bảo trình biên dch sẽ thêm tênhàm vào thƣ vin import simpledll .lib đê  tr nh liên kết co  thê  đƣa ca c thông tin phu  hơ     p va ochƣơng tr nh (file *.exe) đ c th np các thƣ vin dll khi chƣơng trình chy . Đi  nh danhEXPORT co n bao gồm ch  đi  nh lơ   p chƣ  a __declspec(dllexport) và mt chỉ th tiền xư lý if extern “C” đê  đê pho ng trƣơ   ng hơ     p file header đƣơ   c biên di  ch theo kiê u C++. Điều na y ngănchă  n tr nh biên di  ch kho  i ca c lô  i tru  ng tên cu  a ca c ha m C ++ và cho phép các thƣ vin liên kếtđô  ng co  thê  đƣơ   c sƣ  du  ng bơ   i ca  ca c chƣơng tr nh C va  C++.

Điê m va  o va   điê m thoa  t cu  a thƣ viê   n (Entry and Exit Point) 

Hàm DllMain đƣợc gọi đến khi thƣ vin liên kết đng lần đầu tiên đƣợc np vào b nhớ đ thực hin và khi n kết thc nhim v ( b loi khi b nhớ  ). Tham số đầu tiên cu  a ha mDllMain la  handle tơ   i instance cu  a th ƣ viê  n. Nếu nhƣ thƣ viê  n co  sƣ  du  ng ca c ta i nguyên đo  ihi mt handle instance (chă ng ha  n nhƣ ca c hô    p thoa   i ), chng ta nên lƣu li hInstance vàomô  t biến toa n cu  c . Tham số cuối cu  ng cu  a ha m DllMain đƣơ   c dƣ   trƣ   da nh cho hê   t hông sƣ   dng.

Tham số fdwReason co  thê  la  mô   t trong 4 giá tr chỉ ra ti sao Windows li gọi tới hàmDllMain. Trong ca c mu  c tiếp theo chu  ng ta nên nhơ   răng mô  t chƣơng tr nh đơn co  thê  đƣơ   c

Page 89: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 89/96

Bài giảng môn học: Lâ   p tr  nh Windows 

82

np nhiều lần và chy đồng thời t rên Windows. Mô  i lần chƣơng tr nh đƣơ   c na    p no  đƣơ   c xemnhƣ la  mô  t tiến tr nh (process) riêng re  .

Giá tr ca tham số fdwReason bằng DLL _PROCESS_ATTACH ch  ra rằng thƣ viê  nliên kết đô  ng đa   đƣơ   c a nh xa  va o vu  ng đi  a ch  cu  a mô   t tiên tr nh . Đây la  mô  t đầu mối cho

 phép thƣ vin thực hin bất cứ khởi to nào đi hi đƣợc phc v cho các yêu cầu tiếp theoca tiến trình. Các khởi to kiu này c th là cấp phát b nhớ chẳng hn . Trong thơ   i gian tiếntrình đang chy , DllMain đƣơ   c go   i vơ   i mô  t tham số DLL _PROCESS_ATTACH ch  mô   t lântrong ca  thơ   i gian tồn ta   i cu  a process đo  . Bất cƣ  mô  t tiến tr nh na o kha c sƣ  du  ng cu  ng fileDLL se   go   i đên ha m DllMain vơ   i mô   t gia  tr tham số DLL_PROCESS_ATTACH.

 Nêu nhƣ viê  c khơ   i ta  o la  tha nh công DllMain se   tra  vê mô   t gia  tri  kha c 0, giá tr trả về là0 sẽ làm cho Windows không chy chƣơng trình .

 Nếu gia  tri  cu  a fdwReason bằng DLL _PROCESS_DETACH th  co    nghĩa là chƣơngtrình không cần file DLL na , và đây là mt cơ hi đ thƣ vin thực hin các công vic dọn

dp ca n . Trên ca c hê  điêu ha nh 32  bit cu  a Windows điều na y không thƣ  c sƣ   cần thiếtnhƣng la  mô  t tho  i quen lâ    p trình tốt.

Tƣơng tƣ   khi ha m DllMain đƣơ   c go   i vơ   i mô   t gia  tri  tham sô la   DLL_THREAD_ATTACH th  co  ngh  a la  mô  t tiến tr nh sƣ  du  ng thƣ viê  n đa   ta  o ra mô   t luông(thread) mơ   i. Khi luồng kết thu  c Windows la   i go   i tơ   i ha m DllMain vơ   i tham số la   DLL_THREAD_DETACH. Cũng c th xảy ra trƣờng hợp Windows thực hin lời gọi tớihàm DllMain với giá tr ca tham số fdwReason bằng DLL _THREAD_DETACH ma  khôngthƣ  c hiê  n lơ   i go   i vơ   i gia  tri  DLL _THREAD_ATTACH trƣơ   c đo  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 đa   đƣơ   c ta  o ra.

Luồng vâ  n tôn ta   i khi ha m DllMain đƣơ   c go   i đến vơ   i tham sốDLL_THREAD_DETACH.  N thậm chí c th gưi các thông đip trong tiến trì nh.  Nhƣngcác luồng không nên sư dng hàm PostMessage () vì luồng c th kết thc trƣớc khi thôngđiê    p đên đ ch.

Chƣơng tr nh đê  test thƣ viê  n liên kết đô  ng la  mô  t chƣơng tr nh đơn gia n va  la  mô  tProject kha c (thuô  c loa   i Win 32 Application). Chng ta c th đ các file ca 2 Project va ocng mt thƣ mc hoc riêng rẽ trong 2 thƣ mu  c.

Trong qua  tr nh di  ch chƣơng tr nh file simpledll .dll va  simpledll .lib se   đƣơ   c sinh ratrƣơ   c, file simpledll .lib se   đƣơ   c tƣ   đô  ng liên kết vơ   i chƣơng tr nh thƣ  nghiê  m va  file

simpledll.dll se   đƣơ   c na    p va o bô   nhơ   khi chƣơng tr nh cha  y . Cân chu  y  la  chƣơng tr nhusedll.exe không chƣ  a ma   cu  a ha m sƣ  du  ng trong thƣ viê  n , mã ca hàm chỉ đƣợc np vào b nhơ   khi chƣơng tr nh cha  y.

Viê  c include file simpledll .h cu  ng giống nhƣ chu ng ta include file windows .h, liên kếtvơ   i file simpledll .lib cu  ng tƣơng tƣ   nhƣ liên kết vơ   i file user  32.lib va  liên kết vơ   i filesimpledll.dll cu  ng giống nhƣ chƣơng tr nh liên kết vơ   i file user 32.dll.

Mă  c du  chu  ng ta xếp mô  t file DLL la  mô   t mơ   rô  ng cu  a Windows nhƣng no  cu  ng la  mô  tmơ   rô  ng cu  a chƣơng tr nh ƣ  ng du  ng cu  a chu  ng ta . Tất ca  nhƣ  ng g  file DLL thƣ  c hiê  n đêu la  thay mă   t cho ƣ  ng du  ng sƣ  du  ng no  . Chă ng ha  n tât ca  ca c thao ta c cấp pha t bô   nhơ   đƣơ   c kiê m

soát bởi chƣơng trình . Bất cƣ  cƣ  a sô  na o no  ta  o ra đều sơ   hƣ  u bơ   i chƣơng tr nh va  bất cƣ  filenào đƣợc mở cũng đƣợc kim soát bởi ch ƣơng tr nh. Nhiều chƣơng tr nh co  thê  sƣ  du  ng cu  ng

Page 90: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 90/96

Bài giảng môn học: Lâ   p tr  nh Windows 

83

mô  t file dll đồng thơ   i , nhƣng Windows se   đo ng vai tro  la  chăn đê  ngăn chă  n ca c can thiê    p lâ  nnhau giƣ  a ca c ƣ  ng du  ng na y.

 Nhiêu tiên tr nh co  thê  chia se  cu  ng mô   t mô  t đoa  n ma   trong mô   t thƣ viê  n liên kết đô  ng .Tuy nhiên dƣ  liê  u đƣơ   c sƣ  đu  ng bơ   i mô   t thƣ viê  n DLL se   la  kha c nhau vơ   i ca c tiến tr nh kha cnhau. Mô  i tiên tr

 nh co

 mô  t không gian đi  a ch

 dƣ  

liê  u cu a riêng no

 đê  chƣ

 a ca

 c dƣ

  li u c th

sƣ  du  ng đến bơ   i file DLL . Chia se  bô   nhơ   giƣ  a ca c tiến tr nh đo  i ho  i mô   t số ky   thuâ   t kha c ma  chng ta sẽ bàn tới trong phần tiếp theo.

7.4. Chia se  bô    nhơ   giƣ   a ca  c thƣ viê   n liên kê t đô   ng 

Windows cô lâ    p ca c ƣ  ng du  ng sƣ  du  ng cu  ng mô   t thƣ viê  n liên kết đô  ng đồng thơ   i . Tuynhiên đôi khi đây không pha i la  mô  t lƣ  a cho  n th ch hơ     p . Chng ta c th muốn viết mt thƣviê  n DLL chƣ  a mô   t vu  ng nhơ   na o đo  co  thê  đƣơ   c chia se  bơ   i nhiều ƣ  n g du  ng, hoă  c giƣ  a ca cinstance cu  a cu  ng mô   t ƣ  ng du  ng. Điêu na y liên quan tơ   i viê  sƣ  du  ng bô   nhơ   chia se  , hay ch nhxác là mt file ánh x b nhớ (memory-mapped file).

Chng ta sẽ khảo sát mt chƣơng trình c tên là strprog (String Program) và thƣ vinđƣơ   c sƣ  du  ng la  strlib (string library). Strlib chƣ  a 3 hàm mà strprog c th gọi tới . Và mttrong số ca c ha m cu  a strlib se   sƣ  du  ng mô   t ha m call- back đƣơ   c đi  nh ngh  a trong strprog.

Strlib la  mô  t thƣ viê  n liên kết đô  ng chƣ  a va  la m viê  c vơ   i mô   t xâu tối đa 256 ký tự. Xâuđƣơ   c chuyê n tha nh da  ng ky  tƣ   hoa va  kiê m soa t trong vu ng bô   nhơ   chia se  cu  a strlib . Strprogc th sư dng 3 hàm ca thƣ vin Strlib đ cng , xa và nhâ  n đƣơ   c tất ca  ca c xâu hiê  n ta   i tƣ   strlib. Chƣơng tr nh strprog co  hai mu  c menu đê  lƣ  a cho  n la  Enter va  Delete cho phe  p ngƣơ   idng nhập các xâu đ thực hin vic cng và xa các xâu . Strprog se   in ra gia  tri  tất ca  ca  cxâu hiê  n đang nằm chƣ  a trong thƣ viê  n.

Các hàm đƣợc đnh nghĩa trong thƣ vin Strlib 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ẽ chuyn các xâu thành dng ký tự hoa và thêm vào danh sách các xâuca thƣ vin. Giá tr trả về ca hàm là TRUE (khác 0) nếu nhƣ tha nh công va  FALSE (0) nếunhƣ xa y ra lô  i : hoă  c xâu co  đô   da i băng 0 hoă  c không cấp pha t đƣơ   c bô   nhơ   hoă  c đa   sƣ  du  nghết 256 xâu cu  a bô   nhơ   .

Hàm thứ hai sẽ thực hin xa b mt xâu khi danh sách các xâu ca thƣ vin nếu khớpvà nếu c nhiều xâu khớp thì chỉ xâu đầu tiên b xa . Kết qua  tra   vê cu  a ha m la  TRUE nếuxa b thành công và FALSE nếu xâu cần xa c đ dài bằng 0 hoă  c không t m thây.

Hàm thứ ba là hàm sư dng đ lit kê các xâu đang c trong thƣ vin , hàm này sư dngmô  t tham số la  mô  t ha m cal l- back chƣ  a trong chƣơng tr nh sƣ  du  ng ha m . Hàm này phải đƣợcđi  nh ngh  a trong chƣơng tr nh sƣ  du  ng thƣ viê  n nhƣ sau:

EXPORT BOOL CALLBACK GetStrCallBack (PSTR pString, PVOID pParam)

Tham số pfnGetStrCallBack cu  a ha m GetString ch  tơ   i m t hàm call-back. GetString co   

thê  go   i tơ   i ha m GetStrCallBack mô  i lần cho mô  i gia  tri  cu  a mô  t xâu cho tơ   i khi ha m na y tra  về FALSE. GetString se   tra  vê sô lƣơ   ng ca c xâu đƣơ   c truyền cho ha m call -back. Biên pParamsẽ là mt con tro  far tơ   i dƣ   liê  u đƣơ   c ngƣơ   i du  ng đi  nh ngh  a.

Page 91: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 91/96

Bài giảng môn học: Lâ   p tr  nh Windows 

84

Tất nhiên ơ   đây chu  ng ta cu  ng sƣ  du  ng hai phiên ba n cho mô  i ha m , ANSI va  Unicodeversion.

7.5. Các vấn đề khác về thƣ viện liên kết động 

Tôi đa   tƣ  ng đề câ    p trong phân đâu cu  a chƣơng na y la  ca c thƣ viê  n liên kết đô  ng không

nhâ  n ca c thông điê    p . Tuy nhiên mô  t thƣ viê  n liên kêt đô  ng co  thê  go  i tơ   i ha m GetMessage va  PeekMessage. Các thông đip mà thƣ vin lấy về từ hàng đợi thông đip qua các hàm nà ythƣ  c sƣ   la  ca c thông điê    p cu  a ca c chƣơng tr nh go   i tơ   i ca c ha m cu  a thƣ viê  n . Ni chung thƣviê  n la m viê  c thay mă  c cho chƣơng tr nh go  i no  –  mô   t qui luâ   t chi phôi hầu hết ca c ha m cu  aWindows ma  mô   t thƣ viê  n co  thê  go   i tơ   i.

Mô   t thƣ viê  n liên kết đô  ng co  thê  na    p ca c ta i nguyên (chă ng ha  n nhƣ ca c biê u tƣơ   ngchƣơng tr nh, các xâu và các ảnh bitmap ) tƣ  file thƣ viê  n hoă  c tƣ  ca c file cu  a chƣơng tr nh go   itơ   i thƣ viê  n đo  . Các hàm np tài nguyên đo  i ho  i mô   t handle tơ   i instance . Nếu nhƣ thƣ viê  n sƣ   dng handle tới instance ca riêng n (đƣơ   c truyền cho thƣ viê  n qua viê  c go  i tơ   i ha m DllMain

đ khởi to n ) thì thƣ vin c th nhận đƣợc các tài nguyên từ file riêng c a n. Đê 

na    p ca ctài nguyên từ chƣơng trình gọi tới các hàm ca thƣ vin , đo  i ho  i handle tơ   i instance cu  achƣơng tr nh go   i ha m.

Viê  c khai ba o ca c lơ   p cƣ  a sô  chƣơng tr nh va  ta  o ra cƣ  a sô  chƣơng tr nh trong mô  t thƣviê  n đ i hi mt số th thuật . Cả cấu trc lớp cưa sổ và hàm CreateWindow hocCreateWindowEx đều đo  i ho  i mô   t handle tơ   i mô   t instance cu  a chƣơng tr nh . Mă  c du  chu  ng tac th sư dng hande ca thƣ vin trong vic to ra các lớ p cƣ  a sô  va  cƣ  a sô  chƣơng tr nh , cácthông điê    p cƣ  a sô  vâ  n đi qua ha ng đơ   i thông điê    p cu  a chƣơng tr nh go   i tơ   i thƣ viê  n khi thƣviê  n ta  o ra cƣ  a sô  chƣơng tr nh .  Nếu nhƣ ba  n cần pha i ta  o ra ca c lơ   p cƣ  a sô  va  ca c cƣ  a sô   chƣơng tr nh trong mô   t thƣ viê  n th  tôt nhât la  nên sƣ  du  ng handle tơ   i instance cu  a chƣơng

trình gọi tới hàm thƣ vin.

Vì các thông đip cho các hp thoi modal đƣợc nhận bên ngoài vng lp thông đipca chƣơng trình nên chn g ta co  thê  ta  o ra mô   t hô    p thoa   i modal trong mô   t thƣ viê  n bằngcách gọi tới hàm DialogBox . Handle tơ   i instance co  thê  la  cu  a thƣ viê  n hoă  c tham sốhwndParent cu  a ha m DialogBox co  thê  đă   t bằng NULL .

Các thƣ viện không c import 

Thay v  đê  Windows thƣ  c hiê  n viê  c liên kết đô  ng khi chƣơng tr nh lân đầu tiên đƣơ   cnp vào b nhớ chng ta c th liên kết mt chƣơng trình với mt thƣ vin khi chƣơng trình

đang cha  y.Chă ng ha  n chu  ng ta muôn go   i tơ   i ha m Rectangle nhƣ sau: 

Rectangle (hdc, xLeft, yTop, xRight, yBottom) ;

Điều na y se   la m cho chƣơng tr nh đƣơ   c liên kết tơ   i thƣ viê  n gdi 32.lib khi biên di  ch đê  lấy đi  a ch  cu  a ha m Rectangle. Chng ta c th gọi tới hàm Rectangle theo mt cách khác:

typedef BOOL (WINAPI * PFNRECT) (HDC, int, int, int, int) ;

khai ba o hai biến:

HANDLE hLibrary ;

PFNRECT pfnRectangle ;

Tiếp đến go   i tơ   i ca c ha m LoadLibrary va  GetProcAddress :

Page 92: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 92/96

Bài giảng môn học: Lâ   p tr  nh Windows 

85

hLibrary = LoadLibrary (TEXT ("GDI32.DLL"))

pfnRectangle = (PFNPRECT) GetProcAddress (hLibrary, TEXT ("Rectangle"))

Và bây giờ c th gọi tới hàm Rectangle :

pfnRectangle (hdc, xLeft, yTop, xRight, yBottom) ;

FreeLibrary (hLibrary) ;

Mă  c du  ky   thuâ   t sƣ  du  ng thƣ viê  n liên kết đô  ng theo kiê u na y kh ông la m tăng hiê  u qua  sƣ  du  ng cu  a ha m Rectangle nhƣng no  la   i la  mô  t ca ch hiê  u qua  trong trƣơ   ng hơ     p ma  chu  ng takhông biết tên cu  a thƣ viê  n cho tơ   i khi chƣơng tr nh cha  y (chă ng ha  n đối vơ   i ha m AlphaBlendchă ng ha  n).

Đoa  n ma   trên sƣ  du  ng hai ha m LoadLibrary va  FreeLibrary . Windows kiê m soa t ca c biên đêm tham chiêu tơ   i tất ca  ca c module thƣ viê  n . Hàm LoadLibrary sẽ làm cho biến đếmtham chiếu tơ   i ca c thƣ viê  n đƣơ   c na    p tăng lên 1. Biến đếm tham chiếu cũng đƣợc tăng lên khi

Windows na    p mô   t chƣơng tr nh co  sƣ  du  ng thƣ viê  n . FreeLibarary se   la m cho biên đêm na ygiảm đi 1, trƣơ   ng hơ     p mô   t instance cu  a mô  t chƣơng tr nh sƣ  du  ng thƣ viê  n bi  loa   i kho  i bô   nhơ     biến đếm tham chiếu cũng giảm đi 1 đơn vi   . Khi biến đếm tham chiếu na y bằng 0 Windows se   loi b thƣ vin khi b nhớ vì lc đ thƣ vin không cn cần thiết na.

Các thƣ viện ch chứa tài nguyên 

Bất cƣ  ha m na y trong mô  t thƣ viê  n liên kết đô   ng ma  mô   t chƣơng tr nh trên Windows va  các thƣ vin 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 đô  ngc th không nhất thiết phải chứa bất cứ mt hàm export nào . Vâ  y ca c thƣ viê  n đo  chƣ  a g  ?Câu tra  lơ   i la  ca c ta i nguyên.

Chă ng ha  n chu  ng ta la m viê  c trên mô   t ƣ  ng du  ng Windows cần mô  t số ca c a nh bitmap .Thông thƣơ   ng chu  ng ta se   liê   t kê ca c a nh na y trong file ki  ch ba n ta i nguyên va  na    p chu ng va o

 bô   nhơ   vơ   i ha m LoadBitmap. Nhƣng co  le   chu  ng ta muốn co  mô  t sô tâ    p a nh , mô  i tâ    p cho mô   tđô   phân gia i cu  a ma n h nh h nh thƣơ   ng đƣơ   c sƣ  du  ng vơ   i Windows . Giải pháp khả dĩ nhất làchƣ  a ca c tâ    p a nh kha c nhau na y va o ca c file kha c nhau v   mô   t ngƣơ   i du  ng ch  cân tơ   i mô   t tâ    pcác ảnh này trên đĩa cứng. Và các file này đƣợc gọi là các file thƣ vin chỉ chứa tài nguyên .

Hình 21-5 cho chu  ng ta thấy ca ch thƣ  c ta  o ra mô  t thƣ viê  n ch  chƣ  a ta i nguyên đƣơ   c go   ilà bitlib.dll chƣ  a 9 ảnh bitmap. File bitlib.rc chƣ  a tất ca  ca c a nh na y va  ga n cho mô  i a nh mô   tsô. Đê  ta  o ra file bitlib .dll chu  ng ta cần co    9 ảnh c tên lần lƣợt là bitmap 1.bmp,

bitmap2.bmp, …, bitmap9.bmp. Chng ta c th sư d ng các ảnh đi kèm với đĩa CD caquyê n sa ch đê  du  ng.

Bài tập: 

Bài tập 1: Viết thƣ vin DLL chứa các hàm xư lý xâu. 

Page 93: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 93/96

Bài giảng môn học: Lâ   p tr  nh Windows 

86

Tài liệu tham khảo 

[1] Lê Hƣ  u Đa   t. Lâ    p tr nh Windows. NXB Gia o du  c.

[2] Charles Petzold. Programming Windows, fifth edition. Microsoft Press. 1998.

[3] Johnson M. Hart. Windows System Programming Third Edition. Addison Wesley

Professional. 2004.

Page 94: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 94/96

Bài giảng môn học: Lâ   p tr  nh Windows 

87

Đề thi tham khảo 

Đề số 1: Bài số 1Cho Dialog sau:

Biết rằng ca c ID ca các control ca Dialog trên nhƣ sau : các ID ca các Edit Text tƣơng ứngvơ   i ca c Static Text Canh a , Canh b , Canh c lần lƣơ   t la  : ID_CANHA, ID_CANHB,ID_CANHC, ID cu  a Static 1 là ID_KQKT, ID cu  a Static 2 là ID_DTCV, ID cu  a ca c ButtonKiem tra va  Thoat la  ID _KIEMTRA, ID_THOAT. Hãy viết hàm xư lý cho Dialog trên saucho khi nhấn va o nu  t Kiem tra th  chƣơng tr nh se   kiê m tra xem ba số nguyên đƣơ   c nhâ    p va    3Edit text tƣơng ƣ  ng co  la    3 cnh ca 1 tam gia c hay không , kêt qua  kiê m tra đƣơ   c thông ba o

qua Static 1. Trong trƣơ   ng hơ     p la   3 cnh ca 1 tam gia c ha  y t nh va  hiê n thi  chu vi , diê  n t chca tam giác qua Static 2 và khi ngƣời dng nhấn vào nt Thoat sẽ kết thc Dialog .

Bài số 2a)  Hãy trình bày (đƣa ra ) dng đơn giản nhất ca mt hàm xư lý thông đip cưa sổ

chƣơnh tr nh (hàm Window Proc).b)  Giả sư chƣơng trình chỉ c mt mc menu Help , trong đo  co    2 mc menu con là

Contents va  About , hãy viết hàm xư lý thôn g điê    p cƣ  a sô  chƣơng tr nh sao cho khingƣơ   i du  ng cho  n ca c mu  c trong menu Help chƣơng tr nh se   hiê n thi  ca c thông ba o(hàm Message Box) tƣơng ƣ  ng va  khi ngƣơ   i du  ng nhấn chuô  t tra i va o 1 v trí trên mànhình, hãy in ra mt thông ba o về to  a đô   chuô  t ta   i vi  tr  đo   (hàm TextOut).

Đề số 2: Bài số 1Viêt ha m xƣ  ly  hô    p thoa   i sau:

Page 95: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 95/96

Bài giảng môn học: Lâ   p tr  nh Windows 

88

Các điều khin XA , YA, XB, YB, XC, YC la  to  a đô     3 đ nh trên mă   t phă ng to  a đô    (nguyên). Khi nhấn nu  t “Tinh chu vi” ha  y tính chu vi ca tam giác to thành bởi 3 đ nh A, B,C va  hiê n thi  lên IDC _KQ. Nhấn “Thoat” đê  tho at kho  i hô    p thoa   i va  nhấn “Tinh dien tich” se   tính din tích và hin th nhƣ trong phần tính chu vi 

Bài số 2a)  Hãy trình bày (đƣa ra) dng đơn giản nhất ca mt hàm xư lý thông đip cưa sổ ch o

mô   t hô    p thoa   i.b)  Hãy viết hàm WndProc cho mt chƣơng trình c h thống menu gồm 1 mc File ,

trong đo  co  ca c mu  c con vơ   i ca c chƣ  c năng sau : Menu1, Menu2, khi ngƣời dng nhấnvào các mc này chỉ cần đƣa ra thông báo đơn giản , mc Exit đ thoát khi chƣơng

trình.Đề số 3: Bài số 1Viêt ha m xƣ  ly  hô    p thoa   i sau:

Các điều khin XA , YA, XB, YB, XC, YC la  to  a đô     3 đ nh trên mă   t phă ng   tọa đ(nguyên). Khi nhấn nu  t “Tinh chu vi” ha  y t nh chu vi cu  a tam gia c ta  o tha nh bơ   i 3 đ nh A, B,

C va  hiê n thi  lên IDC _KQ. Nhấn “Thoat” đê  tho at kho  i hô    p thoa   i va  nhấn “Tinh dien tich” se   tính din tích và hin th nhƣ trong phần t nh chu vi 

Page 96: Bai Giang Lap Trinh Windows

5/9/2018 Bai Giang Lap Trinh Windows - slidepdf.com

http://slidepdf.com/reader/full/bai-giang-lap-trinh-windows 96/96

Bài giảng môn học: Lâ   p tr  nh Windows 

89

Bài số 2a)  Hãy trình bày (đƣa ra) dng đơn giản nhất ca mt hàm xư lý thông đip cưa sổ ch o

mô   t hô    p thoa   i.b)  Hãy viết hàm WndProc cho mt chƣơng trình c h thống menu gồm 1 mc File ,

trong đo  co  ca c mu  c con vơ   i ca c chƣ  c năng sau : Menu1, Menu2, khi ngƣơ   i du  ng nhấn

vào các mc này chỉ cần đƣa ra thông báo đơn giản , mc Exit đ thoát khi chƣơngtrình.