NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________

L P TRÌNH C TRÊN WINDOWS

Trang 1

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________

Chương 1 T NG QUAN L P TRÌNH C TRÊN WINDOWS
1.1. M U
l p trình trên Microsoft Windows®, chúng ta c n n m ư c các c i m cơ b n nh t c a h i u hành này. Chương này s gi i thi u khái quát các c i m h i u hành Microsoft Windows, các v n liên quan n l p trình b ng ngôn ng C, ng th i ưa ra m t chương trình m u làm sư n cho các chương trình ư c vi t sau này. Trong ph n u, chúng ta tìm hi u sơ lư c l ch s phát tri n c a h Windows® và nh ng c i m n n t ng c a Windows. i u hành Microsoft

Ph n ti p theo s trình bày nh ng khái ni m và yêu c u căn b n c a vi c l p trình C trên Windows. Ngoài ra, ph n này cũng gi i thi u các cơ ch và các công c mà h i u hành cung c p cho ngư i l p trình hay ngư i phát tri n các ng d ng trên Windows. Cu i chương là ph n xây d ng m t chương trình ơn gi n nh t trên Windows. Chương trình này ư c xem như là khuôn m u c a m t chương trình ng d ng i n hình, và h u h t các o n chương trình ư c vi t minh h a trong sách u l y chương trình này làm khung sư n phát tri n cho phù h p v i t ng yêu c u. Thêm vào ó, m t s ki u d li u m i ư c nh nghĩa trên Windows và nh ng qui ư c v cách t tên bi n cũng ư c gi i thi u trong ph n này. Ph n chi ti t và chuyên sâu hơn c a vi c l p trình b ng ngôn ng C trên môi trư ng Windows s ư c trình bày trong các chương ti p theo.

1.2. H

I U HÀNH MICROSOFT WINDOWS

1.2.1. Gi i thi u
Gi a th p niên 80, công ty ph n m m máy tính Microsoft công b phiên b n u tiên c a dòng h i u hành Windows là Microsoft Windows® 1.0. ây là h i u hành dùng giao di n h a khác v i giao di n ký t (text hay console) c a MS-DOS. Tuy nhiên ph i n phiên b n th hai (Windows 2.0 - tháng 11 năm 1987) thì m i có bư c c i ti n áng k , ó là s m r ng giao ti p gi a bàn phím và thi t b chu t và giao di n h a (GUI-Graphic User Interface) như trình ơn (menu) và h p tho i (dialog). Trong phiên b n này Windows ch yêu c u b vi x lý Intel 8086 hay 8088 ch y real-mode truy xu t 1 megabyte b nh . Tháng 5 năm 1990, Microsoft công b phiên b n ti p theo là Windows 3.0. S thay i l n trong phiên b n này là Windows 3.0 h tr protected-mode 16 bit c a các b vi x lý 286, Trang 2

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ 386, và 486 c a Intel. S thay i này cho phép các ng d ng trên Windows truy xu t 16 megabyte b nh . Ti p bư c v i s phát tri n là phiên b n Windows 3.1 ra i năm 1992, Microsoft ưa công ngh Font TrueType, âm nh c (multimedia), liên k t và nhúng i tư ng (OLE- Object Linking and Embedding), và ưa ra các h p tho i chung ã ư c chu n hóa. Trong s phát tri n m nh m c a nh ng th p niên 90, Microsoft công b ti p dòng h i u hành Windows v i ng d ng công ngh m i (1993). H i u hành này l y tên là Windows® NT® (Windows New Technology), ây là phiên b n h i u hành u tiên c a Windows h tr 32 bit cho b x lý 386, 486 và Pentium. Trong h i u hành này thì các ng d ng ph i truy xu t b nh v i a ch là 32-bit và các t p l nh hay ch th 32-bit. Ngoài ra Windows NT cũng ư c thi t k ch y các b vi x lý (CPU) khác ngoài Intel và có th ch y trên các máy tr m (workstation). H i u hành Windows 95 ư c công b năm 1995 cũng là m t h i u hành 32-bit cho Intel 386 tr v sau. Tuy thi u tính b o m t như Windows NT và vi c thích nghi v i máy tr m công ngh RISC, nhưng bù l i h i u hành này yêu c u ph n c ng không cao. Song song v i s phát tri n ph n m m thì công ngh ph n c ng cũng phát tri n không kém. t n d ng s c m nh c a ph n c ng thì các th h Windows ti p theo ngày càng hoàn thi n hơn. Như Windows 98 phát tri n t Window 95 và có nhi u c i thi n như hi u năng làm vi c, h tr các thi t b ph n c ng t t hơn, và cu i cùng là vi c tích h p ch t ch v i Internet và Word Wide Web. Windows 2000 là h i u hành ư c xem là n nh và t t c a dòng Windows, phiên b n này tăng cư ng các tính năng b o m t thích h p trong m i trư ng m ng và giao di n p.

1.2.2.

c i m chung c a h

i u hành Microsoft Windows

Windows là m t h i u hành s d ng giao ti p ngư i dùng h a (GUI), hay còn g i là h i u hành tr c quan (Visual interface). GUI s d ng h a d a trên màn hình nh nh phân (Bitmapped video display). Do ó t n d ng ư c tài nguyên th c c a màn hình, và cung c p m t môi trư ng giàu tính tr c quan và sinh ng. Windows không ơn i u như MS-DOS (hay m t s h i u hành giao di n console) mà màn hình ư c s d ng ch th hi n chu i ký t , do ngư i dùng gõ t bàn phím (keyboard) hay xu t thông tin d ng văn b n. Trong giao di n ngư i dùng h a, màn hình giao ti p v i ngư i s d ng a d ng hơn, ngư i dùng có th nh p d li u thông qua chu t b ng cách nh n vào các nút nh n (button) các hôp ch n (combo box)…thi t b bây gi ư c nh p, có th là bàn phím và thi t b chu t (mouse device). Thi t b chu t là m t thi t b nh v trên màn hình, s d ng thi t b chu t ngư i dùng có th nh p d li u m t cách tr c quan b ng cách kích ho t m t nút l nh, hay làm vi c v i các i tư ng h a liên quan n t a trên màn hình. giao ti p trong môi trư ng h a, Windows ưa ra m t s các thành ph n g i là các i u khi n chung (common control), các i u khi n chung là các i tư ng ư c ưa vào trong

Trang 3

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ h p tho i giao ti p v i ngư i dùng. Bao g m : h p văn b n (text box), nút nh n (button), nút ch n (check box), h p danh sách (list box), h p ch n (combo box)… Th t ra m t ng d ng trên Windows không ph i là quá ph c t p vì chúng có hình th c chung. Chương trình ng d ng thu ng chi m m t ph m vi hình ch nh t trên màn hình g i là m t c a s . Trên cùng c a m i c a s là thanh tiêu (title bar). Các ch c năng c a chương trình thì ư c li t kê trong th c ơn l a ch n c a chương trình (menu) , hay xu t hi n dư i d ng tr c quan hơn là các thanh công c (toolbar). Các thanh công c này ch a các ch c năng ư c s d ng thư ng xuyên trong th c ơn gi m th i gian cho ngư i dùng ph i m th c ơn và ch n. Thông thư ng khi c n l y thông tin hay cung c p thông tin cho ngư i dùng thì m t ng d ng s ưa ra m t h p tho i, trong h p tho i này s ch a các i u khi n chung giao ti p v i ngư i dùng. Windows cũng ra t o m t s các h p tho i chu n như Open Files, và m t s h p tho i tương t như nhau. Windows là m t h i u hành a nhi m, tùy thu c vào b nh mà ta có th ch y nhi u ng d ng cùng m t lúc, và cũng có th ng th i chuy n qua l i gi a các ng d ng và th c thi chúng. Trong các phiên b n c a Windows® 98 và NT® tr v sau, các chương trình ng d ng t b n thân chúng chia thành nhi u ti u trình (thread) x lý và v i t c x lý nhanh t o c m giác nh ng chương trình ng d ng này ch y ng th i v i nhau. Trong Windows, chương trình ng d ng khi th c thi ư c chia s nh ng th t c mà Windows cung c p s n, các t p tin cung c p nh ng th t c trên ư c g i là thư vi n liên k t ng (Dynamic Link Libraries - DLL). Windows có cơ ch liên k t nh ng chương trình ng d ng v i các th t c ư c cung c p trong thư vi n liên k t ng. Kh năng tương thích c a Windows cũng r t cao. Các chương trình ng d ng ư c vi t cho Windows không truy xu t tr c ti p ph n c ng c a nh ng thi t b ho như màn hình và máy in. Mà thay vào ó, h i u hành cung c p m t ngôn ng l p trình h a (g i là Giao ti p thi t b ho - Graphic Device Interface - GDI) cho phép hi n th nh ng i tư ng h a m t cách d dàng. Nh v y m t ng d ng vi t cho Windows s ch y v i b t c thi t b màn hình nào hay b t kì máy in, mi n là ã cài t trình i u khi n thi t b h tr cho Windows. Chương trình ng d ng không quan tâm n ki u thi t b k t n i v i h th ng. Như gi i thi u ph n trên khái ni m liên k t ng là thành ph n quan tr ng c a Windows, nó ư c xem như là h t nhân c a h i u hành, vì b n thân c a Windows là các t p thư vi n liên k t ng. Windows cung c p r t nhi u hàm cho nh ng chương trình ng d ng cài t giao di n ngư i dùng và hi n th văn b n hay h a trên màn hình. Nh ng hàm này ư c cài t trong thư vi n liên k t ng hay còn g i là DLL. ó là các t p tin có d ng ph n m r ng là *.DLL hay *.EXE, h u h t ư c ch a trong thư m c \Windows\System, \Windows\system32 c a Windows® 98 và các thư m c \WinNT\System, \WinNT\System32 c a Windows® NT®. Trong các phiên b n sau này, h th ng liên k t ng ư c t o ra r t nhi u, tuy nhiên, h u h t các hàm ư c g i trong thư vi n này phân thành 3 ơn v sau: Kernel, User, và GDI.

Trang 4

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ Kernel cung c p các hàm và th t c mà m t h t nhân h i u hành truy n th ng qu n lý, như qu n lý b nh , xu t nh p t p tin và tác v . Thư vi n này ư c cài t trong t p tin KRNL386.EXE 16 bit và KERNEL32.DLL 32 bit. User qu n lý giao di n ngư i dùng, cài t t t c khung c a s m c lu n lý. Thư vi n User ư c cài t trong t p tin USER.EXE 16 bit và USER32.DLL 32 bit. GDI cung c p toàn b giao di n thi t b ho (Graphics Device Interface), cho phép chương trình ng d ng hi n th văn b n và ho trên các thi t b xu t ph n c ng như màn hình và máy in. Trong Windows 98, thư vi n liên k t ng ch a kho ng vài ngàn hàm, m i hàm có tên c t , ví d CreateWindow, hàm này dùng t o m t c a s cho ng d ng. Khi s d ng các hàm mà Windows cung c p cho thì các ng d ng ph i khai báo trong các t p tin tiêu .h hay .hpp (header file). Trong m t chương trình Windows, có s khác bi t khi ta g i m t hàm c a thư vi n C và m t hàm c a Windows hay thư vi n liên k t ng cung c p. ó là khi biên d ch mã máy, các hàm thư vi n C s ư c liên k t thành mã chương trình. Trong khi các hàm Windows s ư c g i khi chương trình c n dùng n ch không liên k t vào chương trình. th c hi n ư c các l i g i này thì m t chương trình Windows *.EXE luôn ch a m t tham chi u n thư vi n liên k t ng khác mà nó c n dùng. Khi ó, m t chương trình Windows ư c n p vào b nh s t o con tr tham chi u n nh ng hàm thư vi n DLL mà chương trình dùng, n u thư vi n này chưa ư c n p vào b nh trư c ó thì bây gi s ư c n p.

1.3. L P TRÌNH TRÊN MICROSOFT WINDOWS 1.3.1. c i m chung

Windows là h i u hành h a tr c quan, do dó các tài nguyên c a h th ng cung c p r t a d ng òi h i ngư i l p trình ph i nghiên c u r t nhi u phát hay h t s c m nh c a h i u hành. Theo như nh ng m c ích ti p c n c a các nhà l p trình thì các ng d ng trên Windows ph i h t s c thân thi n v i ngư i dùng thông qua giao di n h a s n có c a Windows. V lý thuy t thì m t ngư i dùng làm vi c ư c v i m t ng d ng c a Windows thì có th làm vi c ư c v i nh ng ng d ng khác. Nhưng trong th c t s d ng m t ng d ng cho t hi u qu cao trong Windows thì c n ph i có m t s hu n luy n tr giúp hay t i thi u thì ph i cho bi t chương trình ng d ng làm vi c như th nào. a s các ng d ng trong Windows u có chung m t giao di n tương tác v i ngư i dùng gi ng nhau. Ví d như các ng d ng trong Windows a s u có thanh th c ơn ch a các m c như : File, Edit, Tool, Help… Và trong h p tho i thì thư ng ch a các ph n t i u khi n chung như : Edit Control, Button Control, Checkbox….

Trang 5

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________

1.3.2. S khác bi t v i l p trình trên MS-DOS
Khi m i bư c vào l p trình trên Windows a s ngư i h c r t l l m, nh t là nh ng ngư i ã t ng làm vi c v i MS-DOS. Do MS-DOS là h i u hành ơn nhi m và giao ti p qua giao di n console. Nên khi vi t chương trình không ph c t p. Còn i v i Windows ngư i l p trình s làm vi c v i b công c l p trình h a a d ng cùng v i cách x lý a nhi m, a lu ng c a Windows. Vì v y vi c l p trình trên Windows s giúp cho ngư i l p trình nhàm chán v i giao di n console c a MS-DOS. Vi c c g ng phát huy các s c m nh tài nguyên c a Windows s làm cho nh ng ng d ng càng m nh m , a d ng, thân thi n, và d s d ng.

1.3.3. M t s yêu c u

i v i ngư i l p trình

i u trư c tiên c a ngư i h c l p trình C trên Windows là ph i bi t l p trình C, sách này không có tham v ng hư ng d n ngư i h c có th thông th o l p trình C trên Windows mà chưa qua m t l p hu n luy n C nào. Tuy nhiên, không nh t thi t ph i hoàn toàn thông th o C m i h c ư c l p trình Windows. có th l p trình trên n n Windows ngoài yêu c u v vi c s d ng công c l p trình, ngư i h c còn c n ph i có căn b n v Windows, t i thi u thì cũng ã dùng qua m t s ng d ng trong Windows. Th t s yêu c u này không quá khó khăn i v i ngư i h c vì hi n t i h u như Windows quá quen thu c v i m i ngư i, nh ng ngư i mà ã s d ng máy tính. Ngoài nh ng yêu c u trên, ôi khi ngư i l p trình trên Windows cũng c n có khi u th m m , vì cách trình bày các hình nh, các i u khi n trên các h p tho i t t thì s làm cho ng d ng càng ti n l i, rõ ràng, và thân thi n v i ngư i dùng.

1.3.4. B công c giao di n l p trình ng d ng API
H i u hành Windows cung c p hàng trăm hàm cho nh ng ng d ng có th s d ng truy c p các tài nguyên trong h th ng. Nh ng hàm này ư c g i là giao di n l p trình ng d ng API (Application Programming Interface). Nh ng hàm trên ư c ch a trong các thư vi n liên k t ng DLL c a h th ng. Nh có c u trúc ng này m i ng d ng u có th truy c p n các hàm ó. Khi biên d ch chương trình, n o n mã g i hàm API thì chương trình d ch không thêm mã hàm này vào mã th c thi mà ch thêm tên DLL ch a hàm và tên c a chính hàm ó. Do ó mã các hàm API th c t không ư c s d ng khi xây d ng chương trình, và nó ch ư c thêm vào khi chương trình ư c n p vào b nh th c thi. Trong API có m t s hàm có ch c năng duy trì s c l p thi t b h a, và các hàm này g i là giao di n thi t b h a GDI (Graphics Device Interface). Do s c l p thi t b nên các hàm GDI cho phép các ng d ng có th làm vi c t t v i nhi u ki u thi t b h a khác nhau.

1.3.5. Cơ ch thông i p
Trang 6

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ Không gi ng như các ng d ng ch y trên MS-DOS, các ng d ng Win32® thì x lý theo các s ki n (event - driven), theo cơ ch này các ng d ng khi ư c vi t s liên t c ch cho h i u hành truy n các d li u nh p vào. H th ng s m nhi m vi c truy n t t c các d li u nh p c a ng d ng vào các c a s khác nhau c a ng d ng ó. M i m t c a s s có riêng m t hàm g i là hàm x lý c a s thư ng ư c t tên là WndProc, h th ng s g i hàm này khi có b t c d li u nh p nào ư c truy n n c a s , hàm này s x lý các d li u nh p ó và tr quy n i u khi n v cho h th ng. H th ng truy n các d li u nh p vào th t c x lý c a c a s thông qua m t hình th c g i là thông i p (message). Thông i p này ư c phát sinh t ng d ng và h th ng. H th ng s phát sinh m t thông i p khi có m t s ki n nh p vào (input even), ví d như khi ngư i dùng nh n m t phím, di chuy n thi t b chu t, hay kích vào các i u khi n (control) như thanh cu n,… Ngoài ra h th ng cũng phát sinh ra thông i p ph n ng l i m t s thay i c a h th ng do m t ng d ng mang n, i u này x y ra khi ng d ng làm c n ki t tài nguyên hay ng d ng t thay i kích thư c c a c a s . M t ng d ng có th phát sinh ra thông i p khi c n yêu c u các c a s c a nó th c hi n m t nhi m v nào ó hay dùng thông tin gi a các c a s . H th ng g i thông i p vào th t c x lý c a s v i b n tham s : nh danh c a c a s , nh danh c a thông i p, và hai tham s còn l i ư c g i là tham s c a thông i p (message parameters). nh danh c a c a s xác nh c a s mà thông i p ư c ch nh. H th ng s dùng nh danh này xác nh c n ph i g i thông i p n th t c x lý c a c a s . nh danh thông i p là m t h ng s th hi n m c ích c a thông i p. Khi th t c x lý c a s nh n thông i p thì nó s dùng nh danh này bi t hình th c c n th c hi n. Ví d , khi m t thông i p ư c truy n n th t c c a s có nh danh là WM_PAINT thì có ý nghĩa r ng c a s vùng làm vi c thay i và c n ph i v l i vùng này. Tham s thông i p lưu giá tr hay v trí c a d li u, ư c dùng b i th t c c a s khi x lý thông i p. Tham s này ph thu c vào lo i thông i p ư c truy n n, nó có th là s nguyên, m t t p các bit dùng làm c hi u, hay m t con tr n m t c u trúc d li u nào ó,… Khi m t thông i p không c n dùng n tham s thì h th ng s thi t l p các tham s này có giá tr NULL. M t th t c c a s ph i ki m tra xem v i lo i thông i p nào c n dùng tham s quy t nh cách s d ng các tham s này. Có hai lo i thông i p : Thông i p ư c nh nghĩa b i h th ng (system-defined messages) :

D ng thông i p này ư c h th ng nh nghĩa cho các c a s , các i u khi n, và các tài nguyên khác trong h th ng. Thư ng ư c b t u v i các ti n t sau : WM_xxx, LB_xxx, CB_xxx,…

Trang 7

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ Thông i p ư c nh nghĩa b i ng d ng (application-defined message) : M t ng d ng có th t o riêng các thông i p truy n thông tin gi a các c a s trong ng d ng. s d ng b i nh ng c a s c a nó hay

N u m t ng d ng nh nghĩa các thông i p riêng thì th t c c a s nh n ư c thông i p này ph i cung c p các hàm x lý tương ng. i v i thông i p h th ng, thì ư c cung c p giá tr nh danh t 0x0000 nh ng ng d ng không ư c nh nghĩa thông i p có giá tr trong kho ng này. Thông i p ư c ng d ng nh nghĩa có giá tr nh danh t 0x0400 n 0x03FF,

n 0x7FFF.

L trình c a thông i p t lúc g i i

n lúc x lý có hai d ng sau:

Thông i p ư c g i vào hàng i thông i p ch x lý (queue message): bao g m các ki u thông i p ư c phát sinh t bàn phím, chu t như thông i p : WM_MOUSEMOVE, WM_LBUTTONDOWN, WM_KEYDOWN, và WM_CHAR. Thông i p ư c g i tr c ti p n th t c x lý không qua hàng i (nonqueue message), bao g m các thông i p th i gian, thông i p v , và thông i p thoát như WM_TIMER, WM_PAINT, và WM_QUIT. X lý thông i p : M t ng d ng ph i xóa và x lý nh ng thông i p ư c g i t i hàng i c a ng d ng ó. i v i m t ng d ng ơn ti u trình thì s d ng m t vòng l p thông i p (message loop) trong hàm WinMain nh n thông i p t hàng i và g i t i th t c x lý c a s tương ng. V i nh ng ng d ng nhi u ti u trình thì m i m t ti u trình có t o c a s thì s có m t vòng l p thông i p x lý thông i p c a nh ng c a s trong ti u trình ó.

1.4. CÁCH VI T M T

NG D NG TRÊN MICROSOFT WINDOWS

1.4.1. Các thành ph n cơ b n t o nên m t ng d ng
1.4.1.1. C a s Trong m t ng d ng h a 32-bit, c a s (window) là m t vùng hình ch nh t trên màn hình, nơi mà ng d ng có th hi n th thông tin ra và nh n thông tin vào t ngư i s d ng. Do u tiên c a m t ng d ng h a 32-bit là t o m t c a s . v y, nhi m v M t c a s s chia s màn hình v i các c a s khác trong cùng m t ng d ng hay các ng d ng khác. Ch m t c a s trong m t th i i m nh n ư c thông tin nh p t ngư i dùng. Ngư i s d ng có th dùng bàn phím, thi t b chu t hay các thi t b nh p li u khác tương tác v i c a s và ng d ng.

Trang 8

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ T t c các c a s u ư c t o t m t c u trúc ư c cung c p s n g i là l p c a s (window class). C u trúc này là m t t p mô t các thu c tính mà h th ng dùng như khuôn m u t o nên các c a s . M i m t c a s ph i là thành viên c a m t l p c a s . T t c các l p c a s này u ư c x lý riêng bi t. 1.4.1.2. H p tho i và các i u khi n H p tho i (Dialog) dùng tương tác v i ngư i dùng trong m t chương trình ng d ng. M t h p tho i thư ng ch a nhi u các u khi n như ô nh p văn b n (edit text), nút b m (button), ghi chú (static control), h p danh sách (list box)… Nút b m (button): g m có Push Button dùng kích ho t m t thao tác, Check Box dùng ch n m t trong hai tr ng thái (TRUE hay FALSE), Radio Button cũng gi ng như Check Box nhưng m t nhóm các Radio Button ph i ư c ch n lo i tr nhau. Chú thích (static): dùng ch a các ghi chú trong h p tho i, ngoài ra n i dung có th thay i trong quá trình s d ng h p tho i. H p li t kê (list box): Ch n m t hay nhi u d li u ư c li t kê trong danh sách, n u h p ch a nhi u dòng và h p không hi n th h t các m u thông tin thì ph i kèm theo m t thanh cu n (scroll bar). Ô nh p văn b n (edit text): Dùng nh p văn b n, n u ô có nhi u dòng thì thư ng kèm theo thanh cu n. Thanh cu n (scroll bar): ngoài vi c dùng kèm v i list box hay edit box thì thanh cu n còn có th s d ng c l p nh m t o các thư c o… Th c ơn (menu): là m t danh sách ch a các thao tác v i m t nh danh mà ngư i dùng có th ch n. H u h t các ng d ng có c a s thì không th thi u th c ơn. Thanh công c (toolbar): ây là m t d ng menu nhưng ch ch a các thao tác c n thi t dư i d ng các bi u tư ng c trưng. Ngoài ra còn r t nhi u các i u khi n mà các công c l p trình cung c p cho ngư i l p trình hay t h t o ra d a trên nh ng thành ph n ư c cung c p s n. 1.4.1.3. ng d ng i n hình trên Windows xây d ng m t ng d ng trên Windows

1.4.1.4. Các ki u t p tin Chương trình ngu n

Tương t như các chương trình C chu n, bao g m các t p tin tiêu (header) ch a trong t p tin *.h, *.hpp. Còn mã ngu n (source code) ch a trong t p tin *.c hay *.cpp. T p tin nh nghĩa

T p tin này có ph n m r ng là *.def, dùng nh nghĩa các i u khi n do chương trình t o ra khi vi t ng d ng t o DLL, ngoài ra còn dùng khai báo vùng nh heap khi ch y chương

Trang 9

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ trình. Lúc trư c do v n tương thích v i Windows 3.1 nên t p tin này thư ng ư c dùng, còn ngày nay chúng ít ư c dùng n. Các file ch a tài nguyên c a ng d ng • Các file *.ico là các bi u tư ng (icon) ư c dùng trong chương trình. Thông thư ng các công c l p trình trên Windows u có các tool t o các nh này. • Con tr chu t c a ng d ng có th ư c v l i dư i d ng các bi u tư ng và lưu trên ĩa v i d ng file *.cur. • Các file d ng nh bitmap dùng minh h a ư c lưu d ng file *.bmp. • T p tin tài nguyên *.rc là ph n khai báo các tài nguyên như th c ơn, h p tho i, và các nh danh ch n các t p tin d ng *.ico, *.cur, *.bmp,... 1.4.1.5. Các ki u d li u m i Các ki u d li u trên Windows thư ng ư c nh nghĩa nh toán t typedef trong t p tin windows.h hay các t p tin khác. Thông thư ng các t p tin nh nghĩa này do Microsoft vi t ra ho c các công ty vi t trình biên d ch C t o ra, nh t thi t nó ph i tương thích v i h i u hành Windows 98, hay NT d a trên ki n trúc 32-bit. M t vài ki u d li u m i có tên vi t t t r t d hi u như UINT là m t d li u thư ng ư c dùng mà ơn gi n là ki u unsigned int, trong Windows 9x ki u này có kích thư c là 32-bit. i v i ki u chu i thì có ki u PSTR ki u này là m t con tr n m t chu i tương t như char*. Tuy nhiên, cũng có m t s ki u ư c khái báo tên thi u rõ ràng như WPARAM và LPARAM. Tên này ư c t vì có ngu n ng c l ch s sâu xa. Khi còn h i u hành Windows 16-bit thì tham s th 3 c a hàm WndProc ư c khai báo là ki u WORD, v i kích thư c 16-bit , còn tham s th 4 có ki u LONG là 32-bit. ây là lý do ngư i ta thêm ti n t "W", "L" vào t "PARAM". Tuy nhiên, trong phiên b n Windows 32-bit, thì WPARAM ư c nh nghĩa như là UINT và LPARAM thì ư c nh nghĩa như m t ki u LONG, do ó c hai tham s này u có giá tr là 32-bit. i u này là m t s nh m l n vì WORD v n là giá tr 16-bit trong Window 98. ư c Trong th t c x lý c a s WndProc giá tr tr v là ki u LRESULT. Ki u này ơn gi n nh nghĩa như là ki u LONG.

Ngoài ra, có m t ki u thư ng xuyên dùng là ki u HANDLE là m t s nguyên 32-bit ư c s d ng như m t ki u nh danh. Có nhi u ki u nh danh nhưng nh t thi t t t c ph i có cùng kích thư c v i HANDLE. B ng sau mô t m t s ki u d li u m i: Ki u HANDLE Ý nghĩa S nguyên 32-bit, Trang 10 nh danh.

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam nh danh.

____________________________________________________________________________________ HWND BYTE WORD DWORD UINT LONG BOOL LPSTR LPCSTR WPARAM LPARAM BSTR LPVOID LPTSTR LPCTSTR S nguyên 32-bit,

Giá tr 8-bit không d u. S nguyên 16-bit không d u. S nguyên 32-bit không d u. S nguyên không d u 32-bit. long 32-bit. Bool. Con tr chu i. H ng con tr chu i. 32-bit. 32-bit. Giá tr 32-bit tr Con tr 32-bit n kí t . n m t ki u không xác nh.

Gi ng như LPSTR nhưng có th chuy n sang d ng Unicode và DBCS. Gi ng như LPCTSTR nhưng có th chuy n sang d ng Unicode và DBCS.
B ng 1.1 Mô t các ki u d li u m i

1.4.2. Khuôn m u chung t o m t ng d ng
M t ng d ng ơn gi n nh t c a Windows bao g m có hai hàm là WinMain và x lý c a s WinProc. Do ó hai hàm này là quan tr ng và không th thi u trong các ng d ng Windows. Hàm WinMain th c hi n các ch c năng sau : • • • • nh nghĩa l p c a s ng d ng. ăng ký l p c a s v a nh nghĩa. T o ra th hi n c a s c a l p ã cho. Hi n th c a s . Trang 11

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ • Kh i ng chu trình x lý thông i p. Hàm x lý WinProc có ch c năng x lý t t c các thông i p có liên quan nc as .

1.4.3. Hàm WinMain
Hàm chính c a m t ng d ng ch y trên Windows là hàm WinMain, ư c khai báo như sau: int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow); Chúng ta s tìm hi u m t hàm WinMain m u sau ây. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT("HelloWin"); // tên ng d ng HWND hwnd; MSG msg; WNDCLASS wndclass; // bi n /* nh nghĩa ki u c a s */ nh nghĩa m t c a s

wndclass.style = SC_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; // Hàm th t c c a s wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; // nh danh ng d ng

wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION); wndclass.hCursor = LoadCusor (NULL, IDC_ARROW); Trang 12

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.lpszMenuName = NULL; // Không có menu wndclass.lpszClassName = szAppName; // tên ng d ng /* ăng ký l p c a s */ if (!RegisterClass(&wndclass)) return 0; /* T o l p c a s */ hwnd = CreateWindow (szAppName, // Tên c a s "Hello Program", // Tiêu WS_OVERLAPPEDWINDOW, // Ki u c a s CW_USEDEFAULT, // T a CW_USEDEFAULT, // T a x y

CW_USEDEFAULT, // Chi u r ng CW_USEDEFAULT, // Chi u dài NULL, // C a s cha NULL, // Không có menu hInstacne, // nh danh ng d ng

NULL); // Tham s b sung /* Hi n th c a s */ ShowWindow (hwnd, iCmdShow); UpdateWindow (hwnd); /* Chu trình x lý các thông i p*/ while (GetMessage (&msg, NULL, 0, 0)) { Trang 13

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ TranslateMessage (&msg); DispatchMessage (&msg); } return msg.wParam; } nh nghĩa m t l p c a s : u tiên c a viêc xây d ng m t ng d ng Windows là ph i nh nghĩa m t l p c a s cho ng d ng. Windows cung c p m t c u trúc WNDCLASS g i là l p c a s , l p này ch a nh ng thu c tính t o thành m t c a s . typedef struct _WNDCLASS { UINT style; WNDPROC lpfnWndProc; int cbClsExtra; HINSTANCE hInstance; HICON hIcon; HCURSOR hCursor; HBRUSH hbrBackground; LPCSTR lpszMenuName; LPCSTR lpszClassName; } WNDCLASS, *PWNDCLASS; Ý nghĩa thu c tính c a c u trúc WNDCLASS ư c mô t trong b ng sau : Thu c tính Ý nghĩa ghi chú

Trang 14

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam K t h p nhi u ki u giá tr khác nhau b ng toán t OR.

____________________________________________________________________________________ style lpfnWndProc cbClsExtra cbWndExtra hInstance hIcon hCursor hbrBackground lpszMenuName Con tr Ki u l p n th t c window M c M c nh nh

S byte ư c c p phát thêm sau c u trúc window-class S byte ư c c p phát thêm sau m t instance c a window nh danh ch a th t c c a s c a l p window nh danh c a bi u tư ng nh danh c a con tr chu t nh danh c a ch i tô n n Tên th c ơn

Dùng hàm LoadIcon Dùng hàm LoadCursor Dùng hàm GetStockObject Tên th c ơn g n v i c a s , th c dơn này ư c khai báo trong t p tin tài nguyên.

lpszClassName

Tên l p
B ng 1.2 Mô t thu c tính c a l p c a s

ăng ký l p c a s : Sau khi nh nghĩa m t l p c a s , ph i ăng ký l p c a s ó b ng hàm RegisterClass :

ATOM RegisterClass( CONST WNDCLASS * lpWndClass ); T oc as : L pc as nh nghĩa nh ng c tính chung c a c a s , cho phép t o ra nhi u c a s d a trên m t l p. Khi t o ra m t c a s c a hàm CreateWindow, ta ch nh các c tính riêng c a c a s này, và phân bi t nó v i các c a s khác t o ra cùng m t l p. Khai báo hàm t o c a s : HWND CreateWindow( LPCSTR lpClassName, // Tên l p c a s ã ăng ký

Trang 15

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ LPCSTR lpwindowName, // Tên c a c a s DWORD dwStyle, // Ki u c a c a s int x, // V trí ngang ban int y, // V trí d c ban int nWidth, // int nHeight, // u u u nh danh c a c a s cha u

r ng ban cao ban

HWND hWndParent, // MENU hMenu, //

nh dang c a th c ơn nh danh th hi n ng d ng u

INSTANCE hInstance, //

PVOID lpParam // Các tham s ban ); Hi n th c a s :

Sau khi g i hàm CreateWindow, m t c a s ư c t o ra bên trong Windows, i u này có ý nghĩa là Windows ã cáp phát m t vùng nh lưu gi t t c các thông tin v c a s ã ư c ch nh trong hàm CreateWindow. Nh ng thông s này s ư c Windows tìm l i khi c n thi t d a vào nh danh mà hàm t o c a s tr v . Tuy nhiên, lúc này c a s chưa xu t hi n trên màn hình Windows, xu t hi n c n ph i g i hàm ShowWindow. Hàm ShowWindow có khai báo như sau: BOOL ShowWindow( HWND hWnd, // nh danh c a c a s c n th hi n

int nCmdShow // Tr ng thái hi n th ); M t s tr ng thái c a tham s nCmdShow: • • • SW_HIDE : n c a s . SW_MAXIMIZE : Phóng c a s ra toàn b màn hình. SW_MINIMIZE : thu nh thành bi u tư ng trên màn hình. Trang 16

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ • SW_RESTORE : Hi n th dư i d ng chu n.

1.4.4. Hàm x lý c a s WndProc
M t chương trình Windows có th ch a nhi u hơn m t hàm x lý c a s . M t hàm x lý c a s luôn k t h p v i m t l p c a s c thù. Hàm x lý c a s thư ng ư c t tên WndProc. Hàm WndProc có ch c năng giao ti p v i bên ngoài, t c là v i Windows, toàn b các thông i p g i n c a s i u ư c x lý qua hàm này. Hàm này thư ng ư c khai báo như sau : LRESULT CALLBACK WndProc ( HWND, UINT, WPARAM, LPARAM ); u tiên là nh danh c a c a s , tham s th 2 là nh danh thông Trong ó tham s i p, và cu i cùng là 2 tham s WPARAM và LPARAM b sung thông tin kèm theo thông i p. Chúng ta s tìm hi u m t hàm x lý c a s WndProc sau:

LRESULT CALLBACK WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; RECT rect; /*X lý các thông i p c n thi t v i ng d ng*/ switch (msg) { case WM_CREATE: /*Vi t o n mã khi t o c a s */ return 0;

Trang 17

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
case WM_PAINT: /*Vi t o n mã khi tô v l i c a s */ hdc = BeginPaint ( hwnd, &ps); GetClientRect (hwnd, &rect); DrawText(hdc, "Hello", -1, &rect, DT_SINGLELINE| DT_CENTER| DT_VCENTER); EndPaint ( hwnd, &ps); return 0; case WM_SIZE: /*Vi t o n mã khi kích thư c c a s thay return 0; case WM_DESTROY: /*C a s b óng*/ i*/

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

Thông thư ng chúng ta ch ch n x lý các thông i p c n thi t có liên quan n ch c năng c a ng d ng. Các thông i p khác thì giao cho hàm x lý m c nh làm vi c (hàm DefWindowProc).

1.4.5. X lý thông i p
Sau khi c a s ư c hi n th trên màn hình, thì chương trình ph i c các thông tin nh p c a ngư i dùng t bàn phím hay thi t b chu t. Windows s duy trì m t hàng i thông i p cho m i chương trình ch y trên nó. Khi m t s ki n nh p thông tin xu t hi n, Windows s d ch s ki n này thành d ng thông i p và ưa nó vào hàng i thông i p c a ng d ng tương ng. Trang 18

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ M t ng d ng nh n các thông i p t hàng i thông i p b ng cách th c thi m t o n mã sau:
while ( GetMessage(&msg, NULL, 0 ,0) ) { TranslateMessage (&msg); DispatchMessage (&msg); }

Trong ó msg là m t bi n c u trúc ki u MSG ư c WINUSER.H. typedef struct tagMSG { HWND hwnd; UINT message; WPARAM wParam; LPARAM lParam; DWORD time; POINT pt; } MSG, *PMSG; Ki u d li u POINT là m t ki u c u trúc khác, ư c WINDEF.H, và có mô t : typedef struct tagPOINT { LONG x; LONG y;

nh nghĩa trong t p tin tiêu

nh nghĩa trong t p tin tiêu

Trang 19

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ } POINT, *PPOINT; Ý nghĩa c a các trư ng trong c u trúc MSG hwnd : nh danh c a c a s mà thông i p phát sinh. message : nh danh c a thông i p, ví d như thông i p phát sinh khi b m nút chu t trái là WM_LBUTTONDOWN có giá tr 0x0201. wParam : Tham s 32-bit ch a các thông tin ph thu c vào t ng thông i p c th . lParam : Tham s 32-bit ph thu c vào thông i p. time : Th i gian t thông i p trong hàng i. pt : T a c a chu t khi t thông i p vào hàng i Hàm GetMessage s tr v 0 n u msg ch a thông i p có nh danh WM_QUIT (0x0012), khi ó vòng l p thông i p ngưng và ng d ng k t thúc. Ngư c l i thì hàm s tr v m t giá tr khác 0 v i các thông i p khác.

1.4.6. Xây d ng m t ng d ng

u tiên

M t ng d ng thư ng có giao di n n n t ng là m t khung c a s , t o ư c c a s này c a s tương chúng ta th c hi n b ng cách khai báo m t l p c a s và ăng ký l p c a s ó. tác ư c thì chúng ta ph i vi t hàm x lý c a s WndProc khi ó t t c các thông i p liên quan n c a s s ư c truy n vào cho hàm này. o n chương trình sau là khung sư n cho các chương trình vi t trên Windows, bao g m 2 hàm chính là : WinMain : hàm chính c a chương trình th c hi n các ch c năng : • • • • Khai báo l p c a s . ăng ký l p c a s v a khai báo. T o và hi n th l p c a s trên. Vòng l p nh n thông i p. nc as .

WndProc : Hàm x lý thông i p g i
/* HELLOWORLD.C */

#include <windows.h> LRESULT CALLBACK WndProc ( HWND, UINT, WPARAM, LPARAM ); int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow ) {

Trang 20

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
static TCHAR szAppName [] = TEXT ("HelloWorld"); 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 (" The program requires Windows"), szAppName, MB_ICONERROR ); return 0; } hwnd = CreateWindow ( szAppName, // Tên l p c a s TEXT (" The Hello World Program"), // Tiêu WS_OVERLAPPEDWINDOW, // Ki u c a s c as

Trang 21

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam
x y

____________________________________________________________________________________
CW_USEDEFAULT, // T a CW_USEDEFAULT, // T a

CW_USEDEFAULT, // Chi u ngang CW_USEDEFAULT, // Chi u d c NULL, // C a s cha NULL, // Th c ơn hInstance, // nh danh

NULL ); // Tham s ShowWindow ( hwnd, iCmdShow ); UpdateWindow ( hwnd ); while ( GetMessage ( &msg, NULL, 0, 0) ) { TranslateMessage (&msg); DispatchMessage (&msg) ; } return msg.wParam; } // End WinMain LRESULT CALLBACK WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; RECT rect; switch ( msg )

Trang 22

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
{ case WM_CREATE: return 0; case WM_PAINT: hdc = BeginPaint ( hwnd, &ps); GetClientRect ( hwnd, &rect ); DrawText( hdc, TEXT("Hello World"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER ); EndPaint ( hwnd, &ps); return 0; case WM_DESTROY: PostQuitMessage (0); return 0; } // End switch return DefWindowProc ( hwnd, msg, wParam, lParam); }

B ng dư i ây li t kê ý nghĩa c a các hàm ư c s d ng trong 2 hàm WinMain và WndProc c a chương trình HELLOWORLD.C. Tên hàm LoadIcon trình. LoadCursor GetStockObject RegisterClass Nap m t con tr chu t cho chương trình. Nh n m t i tư ng h a, trong trư ng h p c a chương trình thì l y m t ch i tô tô l i n n c a c a s . ăng ký m t l p c a s cho c a s Trang 23 ng d ng trong Ý nghĩa N p m t bi u tư ng s d ng trong chương

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ chương trình. MessageBox CreateWindow ShowWindow UpdateWindow GetMesssage TranslateMessage DispatchMessage BeginPaint GetClientRect DrawText EndPaint PostQuitMessage DefWindowProc Hi n th m t thông i p. T o m t c a s d a trên m t l p c a s . Hi n th c a s lên màn hình. Yêu c u c a s v l i chính b n thân nó. Nh n m t thông i p t hàng D ch thông i p bàn phím. G i thông i p n hàm x lý c a s . i thông i p.

Kh i t o ch c năng v c a c a s . L y hình ch nh t lưu vùng làm vi c. Hi n th m t chu i văn b n. K t thúc vi c v c a s . ưa thông i p thoát vào hàng Th c hi n vi c x lý m c i thông i p.

nh các thông i p.

B ng 1.3 Mô t các hàm ư c s d ng trong chương trình minh h a

1.4.7. M t s qui ư c

t tên bi n

Khi vi t m t chương trình ng d ng l n v i nhi u ki u khai báo bi n khác nhau, n u vi c khai báo các tên bi n không thích h p s làm cho chương trình ph c t p thêm, ôi khi làm khó ngay c ngư i vi t ra các mã ngu n ó. Vì v y các l p trình viên thư ng qui ư c sao cho m t tên bi n v a g i ư c ch c năng c a nó v a xác nh ư c ki u lo i. Có r t nhi u phong cách t tên, trong s ó thì có phong cách t tên theo cú pháp Hungary (Hungarian Notation) là ư c dùng nhi u nh t. Qui ư c r t ơn gi n là b t u tên bi n thì vi t ch thư ng và các ch u th hi n ki u d li u c a bi n, và ư c g i là các ti n t . Ví d như bi n szCmdLine là m t bi n lưu chu i nh p t dòng l nh, sz là th hi n cho bi n ki u chu i k t thúc ký t 0, ngoài ra ta hay th y hInstance và hPrevInstance, trong ó h vi t t t cho ki u handle, ki u d li u nguyên thư ng ư c khai báo d ng ti n t là ch i. Cú pháp Hungary này giúp cho ngư i l p trình r t nhi u trong khâu ki m tra l i c a chương trình, vì khi nhìn vào hai bi n ta có th d dàng nh n bi t ơc s không tương thích gi a hai ki u d li u th hi n trong tên c a hai bi n. Trang 24

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ B ng mô t m t s ti n t khi t tên bi n c a các ki u d li u : Ti n t c by n i x,y b w l dw s sz h p Lpsz Ki u d li u char, WCHAR, TCHAR BYTE short int bi n lưu t a BOOL WORD long DWORD string chu i k t thúc b i kí t 0 handle pointer con tr dài chu i ký t k t thúc kí t 0
B ng 1.4 Mô t ki u t tên bi n

x, y

Trang 25

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________

Chương 2 H P THO I VÀ THANH TRÌNH ƠN
2.1. M U
H p tho i (dialog) và thanh trình ơn (menu) là các thành ph n không th thi u trong vi c t ch c giao ti p gi a ngư i s d ng và chương trình. H p tho i ư c xem như là m t lo i c as c bi t, là công c m m d o, linh ho t ưa thông tin vào chương trình m t cách d dàng. Trong khi menu là công c giúp ngư i dùng th c hi n các thao tác ơn gi n hơn, thông qua các nhóm ch c năng thư ng s d ng.

2.2. H P THO I
H p tho i ph i h p gi a ngư i s d ng v i chương trình b ng m t s ph n t i u khi n mà các ph n t này nh n nhi m v thu nh n thông tin t ngư i dùng và cung c p thông tin n ngư i dùng khi ngư i dùng tác ng n các ph n t i u khi n. Các ph n t i u khi n này nh n c a s cha là m t h p tho i. Các ph n t i u khi n thư ng là các Button, List Box, Combo Box, Check Box, Radio Button, Edit Box, Scroll Bar, Static. Tương t như các thông i p g i n th t c WndProc c a c a s chính.Windows s g i các thông i p x lý h p tho i n th t c x lý h p tho i DlgProc. Hai th t c WndProc và th t c DlgProc tuy cách làm vi c gi ng nhau nhưng gi a chúng có nh ng i m khác bi t c n lưu ý. Bên trong th t c x lý h p tho i b n c n kh i t o các ph n t i u khi n bên trong h p tho i b ng thông i p WM_INITDIALOG, cu i cùng là óng h p tho i, còn th t c x lý WndProc thì không có. Có ba lo i h p tho i cơ b n. H p tho i tr ng thái (modal), h p tho i không tr ng Trang 26

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ thái (modeless) và h p tho i thông d ng (common dialog) mà chúng ta s c p c th trong các ph n dư i.

2.2.1. H p tho i tr ng thái
H p tho i tr ng thái (modal) là lo i h p tho i thư ng dùng trong các ng d ng c a chúng ta. Khi h p tho i tr ng thái ư c hi n th thì b n không th chuy n i u khi n n các c a s khác, i u này có nghĩa b n ph i óng h p tho i hi n hành trư c khi mu n chuy n i u khi n n các c a s khác. 2.2.1.1. Cách t o h p tho i ơn gi n Sau ây là chương trình t o ra m t h p tho i ơn gi n. H p tho i ư c t o ra có n i dung như sau. Khi h p tho i hi n lên có xu t hi n dòng ch "HELLO WORLD", bên trên h p tho i có m t bi u tư ng c a h p tho i ó là m t icon, và phía dư i h p tho i là m t nút b m (Button) có tên là OK, khi nh p chu t vào nút OK thì h p tho i "HELLO WORLD" ư c óng l i.

Hình 2.1 H p tho i ơn gi n

o n code chương trình như sau (Ví d 2.1): DIALOG.CPP (trích d n)
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); BOOL CALLBACK DialogProc (HWND, UINT, WPARAM, LPARAM) ; LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static HINSTANCE hInstance ;

Trang 27

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
switch (message) { case WM_CREATE : hInstance = ((LPCREATESTRUCT) lParam)->hInstance ; return 0 ; case WM_COMMAND : switch (LOWORD (wParam)) { case IDC_SHOW : DialogBox (hInstance, TEXT ("DIALOG1"), hwnd, DialogProc) ; break; } return 0 ; case WM_DESTROY : PostQuitMessage (0) ; return 0 ; } return DefWindowProc (hwnd, message, wParam, lParam) ; } /*----------------------hàm x lý thông i p h p tho i-------------------------------*/ BOOL CALLBACK DialogProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { switch (message)

Trang 28

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
{ case WM_INITDIALOG : return TRUE ; case WM_COMMAND : switch (LOWORD (wParam)) { case IDOK : EndDialog (hDlg, 0) ; return TRUE ; } break ; } return FALSE ; }

DIALOG1.RC (trích d n)
/*---------------------------------------dialog--------------------------------------------*/ DIALOG1 DIALOG DISCARDABLE 40, 20, 164, 89 STYLE DS_MODALFRAME | WS_POPUP FONT 9, "MS Sans Serif" BEGIN DEFPUSHBUTTON "OK",IDOK,54,65,50,14 CTEXT "HELLO WORLD ",IDC_STATIC,53,38,72,10 ICON IDI_ICON1,IDC_STATIC,68,9,20,20 END /* -----------------------------------------Menu------------------------------------------*/

Trang 29

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
MENU1 MENU DISCARDABLE BEGIN POPUP "Dialog1" BEGIN MENUITEM "&Show", IDC_SHOW END END

2.2.1.2. H p tho i và t o m u template cho h p tho i Trong ví d 2.1 trên, ta ã t o h p tho i b ng cách dùng các câu l nh ch a trong file tài nguyên DIALOG1.RC. Cách làm này giúp ta hi u c u trúc l nh c a Windows, tuy nhiên công c Visual C++ Developer Studio, ta có th thi t l p m t h p tho i tr c quan hơn như sau : Ch n Insert t th c ơn Resource View thêm m t h p tho i, màn hình ư c th hi n như trong hình 2.2. Miscrosoft s hi n th h p tho i tr c quan cùng v i thanh công c b n có th thêm các thành ph n i u khi n vào h p tho i. Chúng ta có th i u ch nh các thu c tính c a h p tho i như tên h p tho i, ID h p tho i, ví trí hi n th c a h p tho i trên c a s chính, kích thư c ch và ki u ch th hi n trên h p tho i...vv b ng cách nh n chu t ph i trên h p tho i thì c a s Properties c a h p tho i ư c hi n th (hình 2.3).

Hình 2.2 Thêm m t Dialog trong Resource View

Trang 30

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________

Hình 2.3 H p tho i Properties c a Dialog

tiêu

Trong c a s Properties này ch n tab Styles, b m c ch n Title Bar và không c n t o cho c a s . Sau ó óng c a s Properties c a h p tho i l i.

Bây gi b t u thi t k di n m o cho h p tho i. Xóa nút Cancel vì không c n n nút này. thêm m t bi u tư ng vào h p tho i ta nh n nút Picture lên thanh công c và kích chu t vào h p tho i r i kéo khung ch nh t theo kích thư c mong mu n. ây là nơi mà bi u tư ng ư c hi n th . Nh n chu t ph i vào khung ch nh t v a t o, ch n Properties t trình ơn xu t hi n và nguyên nh danh c a bi u tư ng là IDC_STATIC. nh danh này s ư c Windowns t khai báo trong file Resource.h v i giá tr -1. Giá tr -1 là giá tr c a t t c các nh danh mà chương trình không c n tham chi u n. Ti p n là ch n i tư ng Icon trong trong m c Type, r i gõ nh danh c a Icon c n thêm vào trong m c Image. N u ã t o ra bi u tư ng Icon trư c thì ch vi c ch n Icon t danh sách các Icon trong m c Image. thêm dòng ch "HELLO WORLD" vào h p tho i, ch n Static Text t b ng công c và t i tư ng vào h p tho i. Nh n chu t ph i hi n th Properties c a Static Text, sau ó vào m c caption ánh dòng ch "HELLO WORD" vào ây. D ch và ch y chương trình sau ó xem file DIALOG1.RC dư i d ng text, n i dung h p tho i ư c Windows phát sinh như sau : DIALOG1 DIALOG DISCARDABLE 40, 20, 164, 90 STYLE DS_MODALFRAME | WS_POPUP FONT 9, "MS Sans Serif" BEGIN DEFPUSHBUTTON "OK",IDOK,54,65,50,14 CTEXT "HELLO WORLD ",IDC_STATIC,53,38,72,10 ICON IDI_ICON1,IDC_STATIC,68,9,21,20

Trang 31

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ END Dòng u tiên là tên c a h p tho i "DIALOG1" k ti p là t khóa DIALOG, DISCARDABLE và ti p sau ó là 4 s nguyên. Hai s nguyên u tiên ch v trí dòng, c t c a h p tho i s ư c hi n th trên c a s chính. Hai s nguyên ti p theo xác nh kích thư c c a h p tho i theo th t c t và dòng. Lưu ý : Các thông s nh t a và kích thư c c a h p tho i không tính theo ơn v Pixel mà tính theo kích c c a Font ch . S o c a t a x và chi u r ng d a trên 1/4 ơn v r ng trung bình c a Font ch . S o c a t a y và chi u cao d a trên 1/8 ơn v cao trung bình c a Font ch . Theo sau l nh STYLE là các thu c tính c a h p tho i mà b n c n thêm vào. Thông thư ng h p tho i modal s d ng các h ng WS_POPUP và DS_MODALFRAME ngoài ra còn có các h ng WS_CAPTION, WS_MAXIMIZEBOX, WS_MINIMIZEBOX, WS_POPUP, WS_VSCROLL, WS_HSCROLL, WS_SYSMENU, .... L nh BEGIN và l nh END có th ư c thay b ng { và }. Trong ví d trên, h p tho i s d ng 3 ki u i u khi n là DEFPUSHBUTTON (ki u nút b m m c nh), ICON (bi u tư ng), và ki u CTEXT (văn b n ư c canh gi a). M t ki u i u khi n ư c khai báo t ng quát như sau. Control-type "text", id , xPos, yPos, xWidth, yHeight, iStyle. Control-type là các t khóa khai báo ki u i u khi n như DEFPUSHBUTTON, ICON, CTEXT, …. id là nh danh c a các i u khi n, thông thư ng m t i u khi n có m t nh danh riêng ư c g i cùng v i thông i p WM_COMMAND n các th t c x lý thông i p c a c a s cha. xPos, yPos là v trí c t, dòng hi m th c a i u khi n ó trên c a s cha. xWidth, yHeight là chi u r ng và chi u cao c a i u khi n ó. i s cu i cùng là iStyle, i s này tùy ch n dùng nh nghĩa thêm các ki u c a s mà i u khi n c n th hi n chúng thư ng là các h ng WS_ ư c khai báo trong t p tin “.h" c a Windows. 2.2.1.3. Th t c x lý thông i p c a h p tho i Th t c x lý thông i p c a h p tho i dùng x lý t t c các thông i p t b qu n lý h p tho i c a Windows g i n hôp tho i. Th t c này ư c Windows g i khi có s tác ng lên các ph n t i u khi n n m trong h p tho i. Xét th t c x lý h p tho i DialogProc trong ví d 2.1. Th t c này có 4 tham s như th t c WndProc, và th t c này ư c nh nghĩa ki u tr v là CALLBACK.Tuy hai th t c này tương t gi ng nhau nhưng th c s gi a chúng có m t vài s khác bi t áng chú ý. Th t c DialogProc tr v giá tr ki u BOOL, trong khi th t c WindProc thì tr v giá tr LRESULT. Th t c DialogProc tr v giá tr TRUE (giá tr khác 0) n u nó x lý thông i p và ngư c l i n u không x lý các thông i p thì th t c tr v giá th là FALSE (tr 0). Còn th t c WindProc thì g i hàm DefWindowProc v i các thông i p không c n x lý. Trang 32

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ Th t c DialogProc không c n x lý thông i p WM_DESTROY, cũng không c n x lý thông i p WM_PAINT và cũng không nh n ư c thông i p WM_CREATE mà là thông i p WM_INITDIALOG dùng kh i t o h p tho i. Ngoài x lý thông i p WM_INITDIALOG, th t c x lý thông i p h p tho i ch x lý m t thông i p duy nh t khác là WM_COMMAND. ây cũng là thông i p ư c g i n c a s cha khi ta kích ho t (nút nh n ang nh n ư c focus) lên các thành ph n i u khi n. Ch danh ID c a nút “OK" là IDOK s ư c ch a trong word th p c a i s wParam. Khi nút này ư c nh n, th t c DialogProc g i hàm EndDialog k t thúc x lý và óng h p tho i. Các thông i p g i n h p tho i không i qua hàng i mà nó ư c Windows g i tr c ti p hàm DialogProc truy n các thông i p vào cho th t c x lý h p tho i.Vì v y, không ph i b n tâm v hi u ng c a các phím t t ư c quy nh trong chương trình chính. 2.2.1.4. G i hi n th h p tho i và các v n liên quan nh danh

Trong th t c WndProc khi x lý thông i p WM_CREATE Windows l y v hInstance c a chương trình và lưu nó trong bi n tĩnh hInstance như sau. hInstance = ((LPCREATESTRUCT) lParam)->hInstance;

Dialog1 ki m tra thông i p WM_COMMAND xem word th p c a i s wParam có b ng giá tr IDC_SHOW (ch danh c a thành ph n Show trong th c ơn). N u ph i, t c ã ch n m c Show trên trình ơn c a c a s chính và yêu c u hi n th h p tho i, lúc này chương trình g i hi n th h p tho i b ng cách g i hàm. DialogBox (hInstance, TEXT ("DIALOG1"), hwnd, DialogProc) is u tiên c a hàm này ph i là hInstance c a chương trình g i, i s th hai là tên c a h p tho i c n hi n th , i s th 3 là c a s cha mà h p tho i thu c v , cu i cùng là a ch c a th t c x lý các thông i p c a h p tho i. Chương trình không th tr i u khi n v hàm WndProc cho n khi h p tho i ư c óng l i. Giá tr tr v c a hàm DialogBox là giá tr c a i s th hai trong hàm EndDialog n m bên trong th t c x lý thông i p h p tho i. Tuy nhiên chúng ta cũng có th g i thông i p n hàm WndProc yêu c u x lý ngay c khi h p tho i ang m nh hàm SendMessage như sau : SendMessage(GetParent(hDlg), message, wParam, lParam) Tuy Visual C++ Developer ã cung c p cho chúng ta b so n th o h p tho i tr c quan mà ta không c n ph i quan tâm n n i dung trong t p tin .RC. Tuy nhiên v i cách thi t k m t h p tho i b ng các câu l nh giúp chúng ta hi u chi ti t hơn c u trúc l nh c a Windows hơn th n a t p l nh dùng thi t k h p tho i phong phú và a d ng hơn r t nhi u so v i nh ng gì mà ta tr c quan ư c trên b so n th o c a Developer. B ng cách s d ng các l nh c bi t trong Trang 33

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ t p tin Resource editor c a Visual C++ ta có th t o ra nhi u i tư ng mà trong b so n th o không có. Thêm h ng WS_THINKFRAME vào m c STYLE v i trong boder ta ch n m c Resizing). t n i dung tiêu STYLE. STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION CAPTION "Hello Dialog1" Có th dùng cách khác thêm tiêu cho h p tho i, b ng cách trong khi x lý thông i p WM_INITDIALOG thêm vào dòng l nh: SetWindowText(hDlg,TEXT("Hello Dialog")); Khi h p tho i có tiêu r i, có th thêm các ch c năng phóng to và thu nh h p tho i b ng h ng WS_MINIMIZEBOX, WS_MAXIMIZEBOX. Có th thêm trình ơn vào h p tho i n u mu n b ng o n l nh.
DIALOG1 DIALOG DISCARDABLE 40, 20, 164, 90 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION CAPTION "Hello Dialog1" MENU MENU1

co gi n h p tho i (tương ương

cho h p tho i ta ch vi c thêm h ng WS_CAPTION trong

Trong ó MENU1 là tên c a trình ơn ta ã t o. Trong Visual C++ Developer ta ch c n ch n tên th c ơn trong m c Menu như hình sau.

Hình 2.4 Ch n menu trong Dialog Propertier

T c a s Properties trên th ch n m c "Font" Trang 34

nh Font ch cho h p tho i.

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ G i hàm DialogBoxIndirect t o ra m t h p tho i mà không c n dùng resource script. H p tho i t o ra b ng hàm này trong khi chương trình ang th c hi n ư c g i là h p tho i t o t ng. Trong ví d 3-1 ta ch dùng 3 ki u i u khi n ó là các ki u ‘ICON’, ‘CTEXT’, ‘DEFPUSHBUTTON’. Ngoài ra còn có các ki u i u khi n ư c li t kê trong b ng sau. Ki u i u khi n PUSHBUTTON DEFPUSHBUTTON CHECKBOX RADIOBUTTON GROUPBOX LTEXT CTEXT RTEXT ICON EDITTEXT SCROLLBAR LISTBOX COMBOBOX L pc as Button Button Button Button Button Static Static Static Static Edit Scrollbar Listbox Combobox Ki u c a s BS_BUSHBUTTON BS_DEFBUSHBUTTON | WS_TABSTOP BS_CHECKBOX | WS_TABSTOP BS_RADIOBUTTON | WS_TABSTOP BS_GROUPBOX | WS_TABSTOP SS_LEFT | WS_GROUP SS_CENTER | WS_GROUP SS_RIGHT | WS_GROUP SS_ICON ES_LEFT | WS_BORDER | WS_STABSTOP SBS_HORZ LBS_NOTIFY | WS_BORDER | WS_VSCROLL CBS_SIMPLE | WS_TABSTOP
B ng 2.1 Các ki u i u khi n

Các ki u i u khi n ư c khai báo trong resource script có d ng như sau, ngo i tr ki u i u khi n LISTBOX, COMBOBOX, SCROLLBAR, EDITTEXT. Control-type "text", id, xPos, yPos, xWidth, yHeight, iStyle Các ki u i u khi n LISTBOX, COMBOBOX, SCROLLBAR, EDITTEXT ư c khai báo trong resource script v i c u trúc như trên nhưng không có trư ng "text".

Trang 35

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ Thêm thu c tính cho các ki u i u khi n b ng cách thay i tham s iStyle. Ví d ta mu n t o radio button v i chu i di n t n m bên trái c a nút thì ta gán trư ng iStyle b ng BS_LEFTTEXT c th như sau. RADIOBUTTON Radio1",IDC_RADIO1,106,10,53,15,BS_LEFTTEXT Trong resource script ta cũng có th t o m t ki u i u khi n b ng l nh t ng quát sau. CONTROL "text", id, "class", iStyle, xPos, yPos, xWidth, yHeight Trong ó class là tên l p mu n t o ví d thay vì t o m t radio button b ng câu l nh.
RADIOBUTTON "Radio1",IDC_RADIO1,106,10,53,15,BS_LEFTTEXT

Thay b ng o n l nh sau:
CONTROL"Radio1",IDC_RADIO1,"button",106,10,53,15,BS_LEFTTEXT

2.2.1.5. Ví d chương trình v h p tho i. minh h a cho vi c trao i thông i p gi a các thành ph n i u khi n bên trong h p tho i ( óng vai trò là m t c a s cha) v i các thành ph n i u khi n con n m bên trong h p tho i, và cơ ch qu n lý h p tho i c a Windows. Chúng ta ti n hành xem xét ví d 2-2. K t qu th c hi n c a chương trình như trong hình 2.5. C a s h p tho i g m có ba nhóm nút ch n radio.Nhóm th nh t dùng ch n i tư ng v là hình ch nh t hay hình ellipse, nhóm th hai dùng ch n màu tô cho hình v , nhóm th 3 dùng ch n ki u tô cho hình v . Khi thay i vi c ch n màu tô, ki u tô thì màu tô và ki u tô c a hình v c nh bên s thay i theo màu tô, và ki u tô v a m i ch n. Khi nh n nút OK thì h p tho i óng l i và màu tô, ki u tô cùng hình v v a m i v s ư c hi n th lên c a s chính. N u nh n nút Cancel ho c nh n phím Esc thì h p tho i ư c óng l i nhưng hình v , màu tô và ki u tô không ư c hi n th lên c a s chính. Trong ví d này nút OK và nút Cancel có ch danh ID l n lư t là IDOK và IDCANCEL.Thông thư ng t ch danh cho các ph n t i u khi n n m trong h p tho i ư c b t u b ng ch ID. Bi u tư ng chi c xe p trên h p tho i ó là m t icon. Trên thanh tiêu c a c a s chính có m t bi u tư ng, bi u tư ng ó cũng là m t icon ( ó là m t ly trà). Khi t các nút radio vào h p tho i b ng công c Developer studio nh ph i t các nút ó theo th t như hình 2-5. Thì khi ó Windows m i phát sinh mã cho các nút ó theo th t tăng d n, i u này giúp chúng ta d dàng ki m soát các thao tác trên t p các nút radio. B n nh b luôn m c ch n Auto trong ph n thi t l p Properties c a các nút ch n radio. B i vì các nút radio mang thu c tính Auto yêu c u vi t ít mã l nh hơn ngưng chúng thư ng khó hi u so v i các nút không có thu c tính Auto. Ch n thu c tính Group, Tab stop trong ph n thi t k Properties c a nút OK, nút Cancel, và hai nút radio u tiên trong ba nhóm radio có th chuy n focus (ch n) b ng phím Tab trên bàn phím.

Trang 36

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________

Hình 2.5 Minh h a trao

i thông i p qua các i u khi n

Chương trình minh h a (Ví d 2.2) : DIALOG2.CPP (trích d n)
#include <windows.h> #include "resource.h" LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); BOOL CALLBACK DialogProc (HWND, UINT, WPARAM, LPARAM); int iCurrentColor = IDC_BLACK, iCurrentFigure = IDC_RECT; int iCurrenBrush = IDC_HS_BDIAGONAL; void PaintWindow(HWND hwnd, int iColor, int iFigure, int iBrush) { static COLORREF crColor[8] = { RGB(0, 0, 0), RGB(0, 0, 255), RGB(0, 255, 0), RGB(0, 255, 255), RGB(255, 0, 0), RGB(255, 0, 255), RGB(255, 255, 0), RGB(255, 255, 255) } ; HBRUSH hBrush,hbrush; HDC hdc ; RECT rect ; hdc = GetDC (hwnd) ; GetClientRect (hwnd, &rect) ;

Trang 37

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
if(iBrush==IDC_HS_BDIAGONAL) hbrush=CreateHatchBrush(HS_BDIAGONAL, crColor[iColor-IDC_BLACK]); if(iBrush == IDC_HS_CROSS) hbrush=CreateHatchBrush(HS_CROSS, crColor[iColor - IDC_BLACK]); if(iBrush == IDC_HS_DIAGCROSS) hbrush=CreateHatchBrush(HS_DIAGCROSS, crColor[iColor - IDC_BLACK]); if(iBrush == IDC_HS_FDIAGONAL) hbrush=CreateHatchBrush(HS_FDIAGONAL, crColor[iColor - IDC_BLACK]); if(iBrush == IDC_HS_HORIZONTAL) hbrush=CreateHatchBrush(HS_HORIZONTAL, crColor[iColor - IDC_BLACK]); if(iBrush == IDC_HS_VERTICAL) hbrush=CreateHatchBrush(HS_BDIAGONAL, crColor[iColor - IDC_BLACK]); hBrush = (HBRUSH) SelectObject (hdc, hbrush) ; if (iFigure == IDC_RECT) Rectangle (hdc, rect.left, rect.top, rect.right, rect.bottom) ; else Ellipse(hdc, rect.left, rect.top, rect.right, rect.bottom) ; DeleteObject (SelectObject (hdc, hBrush)) ;

Trang 38

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
ReleaseDC (hwnd, hdc) ; } void PaintTheBlock(HWND hCtrl, int iColor, int iFigure, int iBrush) { InvalidateRect (hCtrl, NULL, TRUE) ; UpdateWindow (hCtrl) ; PaintWindow (hCtrl, iColor, iFigure,iBrush) ; } LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static HINSTANCE hInstance ; PAINTSTRUCT ps ; switch (message) { case WM_CREATE: hInstance = ((LPCREATESTRUCT) lParam)->hInstance ; return 0 ; case WM_COMMAND: switch (LOWORD (wParam)) { case IDC_SHOW: if (DialogBox (hInstance, TEXT ("DIALOG"), hwnd, DialogProc)) InvalidateRect (hwnd, NULL, TRUE) ;

Trang 39

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
return 0 ; } break; case WM_PAINT: BeginPaint (hwnd, &ps) ; EndPaint (hwnd, &ps) ; PaintWindow (hwnd, iCurrentColor, iCurrentFigure, iCurrenBrush) ; return 0 ; case WM_DESTROY: PostQuitMessage (0) ; return 0 ; } return DefWindowProc (hwnd, message, wParam, lParam) ; } BOOL CALLBACK DialogProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { static HWND hCtrlBlock ; static int iColor, iFigure,iBrush; switch (message) { case WM_INITDIALOG: iColor = iCurrentColor ; iFigure = iCurrentFigure ;

Trang 40

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
iBrush = iCurrenBrush; CheckRadioButton(hDlg,IDC_BLACK,IDC_WHITE, iColor); CheckRadioButton(hDlg,IDC_RECT,IDC_ELLIPSE,iFigure);CheckRadioButton (hDlg, IDC_HS_BDIAGONAL, IDC_HS_VERTICAL, iBrush); hCtrlBlock = GetDlgItem (hDlg, IDC_PAINT) ; SetFocus (GetDlgItem (hDlg, iColor)) ; return FALSE ; case WM_COMMAND: switch (LOWORD (wParam)) { case IDOK: iCurrentColor = iColor ; iCurrentFigure = iFigure ; iCurrenBrush = iBrush; EndDialog (hDlg, TRUE) ; return TRUE ; case IDCANCEL: EndDialog (hDlg, FALSE) ; return TRUE ; case IDC_BLACK: case IDC_RED: case IDC_GREEN: case IDC_YELLOW: case IDC_BLUE:

Trang 41

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
case IDC_MAGENTA: case IDC_CYAN: case IDC_WHITE: iColor = LOWORD (wParam) ; CheckRadioButton (hDlg, IDC_BLACK, IDC_WHITE, LOWORD (wParam)) ; PaintTheBlock (hCtrlBlock, iColor, iFigure,iBrush) ; return TRUE ; case IDC_RECT: case IDC_ELLIPSE: iFigure = LOWORD (wParam) ; CheckRadioButton (hDlg, IDC_RECT, IDC_ELLIPSE, LOWORD (wParam)) ; PaintTheBlock (hCtrlBlock, iColor, iFigure,iBrush) ; return TRUE ; case IDC_HS_BDIAGONAL: case IDC_HS_CROSS: case IDC_HS_DIAGCROSS: case IDC_HS_FDIAGONAL: case IDC_HS_HORIZONTAL: case IDC_HS_VERTICAL: iBrush = LOWORD (wParam) CheckRadioButton(hDlg,IDC_HS_BDIAGONAL,IDC_HS_VERTICAL, LOWORD (wParam)) ; PaintTheBlock (hCtrlBlock, iColor, iFigure,iBrush) ; return TRUE ;

Trang 42

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
} break; case WM_PAINT: PaintTheBlock (hCtrlBlock, iColor, iFigure,iBrush) ; break ; } return FALSE ; }

2.2.1.6. Làm vi c v i các thành ph n i u khi n trong h p tho i Các thành ph n i u khi n con u g i thông i p WM_COMMAND n c a s cha c a nó và c a s cha có th thay i tr ng thái c a các thành ph n i u khi n con như kích ho t, ánh d u (check), b d u check (uncheck) b ng cách g i các thông i p n các thành ph n i u khi n con n m trong nó. Tuy nhiên trong Windows ã cung c p cơ ch trao i thông i p gi a các thành ph n i u khi n con v i c a s cha. Chúng ta b t u tìm hi u các cơ ch trao i thông i p ó. Trong ví d 2.2 m u template c a h p tho i Dialog2 ư c th hi n trong t p tin tài nguyên DIALOG2.RC g m có các thành ph n. Thành ph n GROUPBOX có tiêu do chúng ta gõ vào, thành ph n này ch ơn gi n là m t khung vi n bao quanh hai nhóm nút ch n radio, và hai nhóm này hoàn toàn c l p v i nhau trong m i nhóm. Khi m t trong nh ng nút radio ư c kích ho t thì c a s i u khi n con g i thông i p WM_COMMAND n c a s cha ( ây là h p tho i) v i word th p c a i s wParam ch a thành ph n ID c a i u khi n con, word cao c a i s wParam cho bi t mã thông báo. Sau cùng là i s lParam mang handle c a c a s i u khi n con. Mã thông báo c a nút ch n radio luôn luôn là BN_CLICKED (mang giá tr 0). Windows s chuy n thông i p WM_COMMAND cùng v i các i s wParam và lParam n th t c x lý thông i p c a h p tho i (DialogProc). Khi h p tho i nh n ư c thông i p WM_COMMAND cùng v i các i s lParam và wParam, h p tho i ki m tra tr ng thái c a t t c các thành ph n i u khi n con n m trong nó và thi t l p các tr ng thái cho các thành ph n i u khi n con này. Có th ánh d u m t nút ch n b ng cách g i thông i p

SendMessage (hwndCtrl ,MB_SETCHECK, 1, 0); Và ngư c l i mu n b ch n m t nút nào ó thì dùng hàm. Trang 43

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ SendMessage (hwndCtrl, MB_SETCHECK, 0, 0); Trong ó i s hwndCtrl là handle c a c a s i u khi n con.

Chúng ta có th g p r c r i khi mu n s d ng hai hàm trên b i vì không bi t handle c a các thành ph n i u khi n con. Chúng ta ch bi t handle c a các thành ph n i u khi n con khi nh n ư c thông i p WM_COMMAND. gi i quy t ư c vư ng m c trên, trong Windows cung c p m t hàm l y handle c a c a s con khi bi t ư c nh danh ID c a nó b ng hàm. hwndCtrl = GetDlgItem (hDlg, id); // hDlg là handle c a h p tho i Có th l y ư c ch danh ID c a thành ph n i u khi n con khi bi t ư c handle c a nó b ng hàm sau. id = GetWindowLong (hwndCtrl, GWL_ID); Tuy nhiên, chúng ta có th qu n lý ID c a các thành ph n i u khi n con, còn handle là do Windows c p ng u nhiên, do ó vi c dùng handle nh n v ID c a các thành ph n i u khi n con là ít dùng n. Khi h p tho i nh n ư c thông i p WM_COMAND thì chúng ta ph i ki m tra nút radio nào ư c ch n (xác nh màu c n ch n), và ti n hành b ch n các nút khác b ng o n l nh sau.
case WM_COMMAND: switch (LOWORD (wParam)) { case IDC_BLACK: case IDC_RED: case IDC_GREEN: case IDC_YELLOW: case IDC_BLUE: case IDC_MAGENTA: case IDC_CYAN: case IDC_WHITE: iColor = LOWORD (wParam) ;

Trang 44

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
for( i = IDC_BLACK, i < IDC_WHITE,i++) SendMessage(GetDlgItem(hDlg, i),MB_SETCHECK, i == LOWORD( wParam), 0). return TRUE ; }

Trong ó iColor dùng lưu giá tr màu hi n hành ư c ch n. Vòng l p for dùng ki m tra tr ng thái c a t t c các nút radio thông qua ID c a chúng. Hàm GetDlgItem dùng l y handle c a nút ư c ch n và lưu vào bi n i. Hàm SendMessage dùng g i thông i p MB_SETCHECK t i các nút radio. N u word th p c a i s wParam b ng ch danh ID c a nút ư c ch n thì nút ó ư c ánh d u và các nút khác s không ư c ch n. Chú ý :Trong các ví d trên thư ng dùng hai nút OK và nút Cancel, hai nút này ư c Windows t nh danh m c nh theo th t là IDOK và IDCANCEL. Thông thư ng óng h p tho i b ng cách nh n chu t vào m t trong hai nút OK ho c Cancel. Trong Windows, khi nh n nút Enter thì Windows luôn phát sinh thông i p WM_COMMAND, b t kỳ i tư ng nào ang nh n focus. LOWORD c a i s wParam mang giá tr ID c a nút nh n m c nh (nút OK), ngoài tr có m t nút ang nh n focus (trong trư ng h p này thì LOWORD c a i s wParam mang ch danh c a nút ang nh n focus). N u nh n nút Esc hay nh n Ctrl+Break, thì Windows g i thông i p WM_COMMAND v i thành ph n LOWORD c a i s wParam có giá tr IDCANCEL ( nh danh m c nh c a nút Cancel). Do ó không c n ph i x lý thêm các phím gõ óng h p tho i. Trong ví d 2.2 chương trình sau. x lý hai trư ng h p khi nh n nút Cancel và nút OK ta dùng o n

switch (LOWORD (wParam)) { case IDOK: iCurrentColor = iColor ; iCurrentFigure = iFigure ; EndDialog (hDlg, TRUE) ; return TRUE ; case IDCANCEL: EndDialog (hDlg, FALSE) ; return TRUE ;

Trang 45

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
… }

Hàm EndDialog dùng k t thúc và óng h p tho i.Trong trư ng h p nh n nút OK thì hai giá tr iCurrentColor và giá tr iCurrentFigure ư c lưu l i cho c a s cha (c hai bi n trên u là bi n toàn c c). Chú ý r ng, hai giá tr khác bi t (TRUE, FALSE) c a i s th hai trong l i g i hàm EndDialog. Giá tr này s ư c tr ngư c v t l i g i hàm DialogBox trong th t c WndProc.
case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_SHOW: if(DialogBox(hInstance, TEXT("DIALOG"), hwnd, DialogProc)) InvalidateRect (hwnd, NULL, TRUE) ; return 0 ; } break;

Có nghĩa n u hàm DialogBox tr v giá tr TRUE, t c nút OK ư c nh n. Lúc ó th t c WndProc s c p nh t l i n i dung c a c a s chính, b ng cách ghi l i s thay i giá tr c a hai bi n toàn c c iCurrentColor và giá tr iCurrentFigure dùng v l i hình ch nh t hay hình ellipse v i màu ư c ch n là iCurrentColor. Và ngư c l i n u nh n nút Cancel thì giá tr iCurrentColor và giá tr iCurrentFigure s không thay i, t c th t c WndProc s d ng l i giá tr cũ. Giá tr TRUE hay FALSE thông báo cho c a s chính bi t r ng ngư i dùng t ch i hay ch p thu n tùy ch n trong h p tho i. Vì TRUE và FALSE có ki u s nguyên (1,0) nên i s th hai trong l i g i hàm EndDialog có ki u s nguyên (int). Do ó k t qu tr v c a hàm này cũng có ki u là s nguyên. Ví d n u b n b m nút OK thì tr tr v c a hàm b ng 1. N u b n b m nút Cancel thì tr tr v c a hàm b ng 0, và n u trong chương trình có s d ng nút b m m c nh Inoge thì khi b m nút này tr tr c a hàm s là 2. 2.2.1.7. V trong h p tho i Trong ví d 2.2 chúng ta ã dùng phương pháp v trên h p tho i ây là công vi c khác thư ng. Bây gi ta tìm hi u công vi c ó ti n hành như th nào. Trang 46

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ Trong file RESOURCE.RC có thành ph n i u khi n là. LTEXT "",IDC_PAINT, 5, 22, 92, 93 Khi chúng ta ch n nút radio thay i màu, hình v hay nh n ư c thông i p WM_PAINT thì th t c DialogProc th c hi n thao tác v vào thành ph n i u khi n c a h p tho i b ng hàm PaintTheBlock. Hàm này ư c khai báo như sau. PaintTheBlock(hCtrBlock, iColor, iFigure); Trong ó hCtrBlock là handle c a thành ph n i u khi n có Handle c a thành ph n i u khi n này ư c l y v b i hàm. hCtrBlock=GetDlgItem(hDlg, IDC_PAINT); N i dung c a hàm PaintTheBlock như sau.
void PaintTheBlock(HWND hCtrl, int iColor, int iFigure) { InvalidateRect(hCtrl, NULL, TRUE); UpdateWinDow(hCtrl); PaintWinDow(hCtrl, iColor, iFigure); }

nh danh là IDC_PAINT.

Hàm InvalidateRect(hCtrl, NULL, TRUE) và UpdateWindow(hCtrl) có nhi m v làm cho c a s con c n ph i v l i. Hàm PaintWindow dùng v ra màn hình ellipse hay ch nh t. u tiên hàm này l y DC (device context) c a thi t b có handle là hCtrl, và v lên thi t b này d ng hình nh cùng v i màu tô ư c ch n. Kích thư c c a c a s con c n v ư c l y b ng hàm GetClientRect.Hàm này tr v kích thư c c a vùng client c n v theo ơn v tính là pixel. Chúng ta v trên vùng client c a các i u khi n con ch không v tr c ti p lên vùng client c a h p tho i. Khi h p tho i nh n ư c thông i p WM_PAINT thì thành ph n i u khi n có nh danh IDC_PAINT ư c v l i. Cách x lý thông i p WM_PAINT gi ng như th t c x lý WndProc c a c a s chính, nhưng th t c x lý h p tho i không g i hàm BeginPaint và hàm EndPaint b i vì nó không t v lên c a s c a chính nó. N u mu n vô hi u hóa m t ph n t thì dùng hàm. i u ki n, t c bi n i nút sang tr ng thái vô hi u hóa

EnableWindow(hwndCtrl, bEnable);

Trang 47

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ i s hwndCtrl là ch danh c a thành ph n i u khi n mu n vô hi u hóa, thành ph n th hai là bEnable mang hai giá tr TRUE hay FALSE, n u thành ph n này mang giá tr FALSE thì i u khi n này ư c vô hi u hóa, còn ngư c l i n u thành ph n này mang giá tr TRUE thì i u khi n ó có hi u hóa tr l i.

2.2.2. H p tho i không tr ng thái
Trong ph n trên ã th o lu n lo i h p tho i, th nh t ó là h p tho i tr ng thái, và bây gi ti p t c th o lu n n lo i h p tho i th hai, h p tho i không tr ng thái (modeless). hi u rõ cách s d ng cũng như nh ng thao tác trên h p tho i không tr ng thái, chúng ta th t tìm hi u qua các m c sau. 2.2.2.1. S khác nhau gi a h p tho i tr ng thái và h p tho i không tr ng thái H p tho i không tr ng thái khác v i h p tho i tr ng thái ch . Sau khi hi n th h p tho i không tr ng thái chúng ta có th chuy n thao tác n các c a s khác mà không c n óng h p tho i d ng này l i. i u này thu n ti n i v i ngư i dùng khi ngư i dùng mu n tr c quan các s thao tác cùng m t lúc. Ví d như trình so n th o Studio Deverloper b n có th thao tác qua l i gi a hai h p tho i, ó là h p tho i b n c n thi t k và m t h p tho i ch a các lo i i u khi n mà b n dùng thi t k . V i cách làm này giúp ngư i dùng tr c quan hơn so v i cách ch cho phép ngư i dùng ch thao tác trên m t c a s . S d ng hàm DialogBox g i h p tho i tr ng thái và ch nh n ư c k t qu tr v khi h p tho i này b óng cùng v i hàm DialogBox k t thúc. Giá tr tr v c a hàm này do i s th hai c a hàm k t thúc h p tho i (EndDialog) quy nh. Còn i v i h p tho i không tr ng thái thì ư c t o ra b ng hàm. hDlgModeless=CreateDialog(hInstance, szTemplate, hwndParent, DialogProc); Nhưng hàm này tr quy n i u khi n v cho nơi g i ngay l p t c và giá tr trà v là handle c a c a h p tho i hi n hành. Vì có th có nhi u c a s thao tác cùng m t lúc nên b n lưc handle này d dàng truy c p khi b n c n. Ph i t ch WS_VISIBLE cho h p tho i không tr ng thái, b ng cách ch n m c More Styles trong c a s Properties c a h p tho i. N u như không b t ch VISIBLE lên thì chương trình ph i có câu l nh ShowWindow sau l i g i hàm CreateDialog khi mu n hi n th h p tho i d ng này lên màn hình. hDlgModeless=CreateDialog(hInstance, szTemplate, hwndParent, DialogProc); ShowWindow(hDlgModeless,SW_SHOW);

Trang 48

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ Các thông i p g i n h p tho i d ng modal do trình qu n lý Windows i u khi n cũng khác v i các thông i p g i n h p tho i d ng modeless ph i i qua h ng i c a chương trình chính. B i vì các thông i p c a h p tho i d ng modeless dùng chung v i các thông i p c a c a s chương trình chính. Như v y chúng ta ph i l c ra thông i p nào là thông i p g i n h p tho i khi thao tác trên h p tho i t trong vòng l p nh n thông i p. làm ư c i u này chúng ta dùng handle c a h p tho i (lưu trong bi n toàn c c) ư c tr v t l i g i hàm CreateDialog và chuy n hư ng chúng b ng o n l nh như sau.
while(GetMessage(&msg, NULL, 0, 0)) { if (hDlgModeless==0 || !IsDialogMessage (hDlgModeless, &msg); { TranslateMessage(&msg); DispatchMessage(&msg); } }

N u thông i p l y ra t h ng i dành cho h p tho i thì hàm IsDialogMessage ki m tra và g i n các th t c x lý h p tho i. Và lúc này hàm tr v giá tr TRUE, còn ngư c l i thì hàm tr v giá tr FALSE. N u dùng thêm ch c năng phím tăng t c thì o n chương trình trên ư c
vi t l i như sau. while(GetMessage(&msg, NULL, 0, 0)) { if (hDlgModeless==0 || !IsDialogMessage(hDlgModeless, &msg); { if(TranslateAccelerator (hwnd, hAccel, &msg) { TranslateMessage(&msg); DispatchMessage(&msg); } }

Trang 49

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
}

Nên chú ý r ng bi n hDlgModeless luôn mang giá tr 0 cho n lúc có m t h p tho i ư c kh i t o b ng câu l nh CreateDialog thì giá tr c a nó m i ư c thay i. Khi c a s h p tho i b h y nh t hDlgModeless v giá tr 0. i u này giúp Windows không g i nh m thông i p x lý n các c a s khác. k t thúc và óng h p tho i d ng Modeless b n dùng hàm DestroyWindow ch không ph i dùng hàm EndDialog như h p tho i d ng Modal. 2.2.2.2. Ví d v h p tho i không không tr ng thái minh h a cách dùng h p tho i không tr ng thái (modeless) ta xét ví d 2.3. Chương trình ví d 2.3 sau khi ch y có k t qu như sau.

Hình 2.6 Minh h a h p tho i không tr ng thái

Khi dùng chu t ch n lo i hình v trên radio button, lo i hình v ư c ch n s v cùng lúc lên control tĩnh c a h p tho i và c a s chính. Dùng chu t ch n màu tô cho hình v ư c ch n, b ng cách rê chu t lên 3 thanh cu n Scrollbar. Chương trình minh h a (Ví d 2.3) : *MODELESS.CPP (trích d n)
void PaintWindow (HWND hwnd, int iColor[], int iFigure) { HBRUSH hBrush ; HDC hdc ; RECT rect ;

Trang 50

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
hdc = GetDC(hwnd) ; GetClientRect (hwnd, &rect) ; hBrush = CreateSolidBrush(RGB(iColor[0], iColor[1], iColor[2])); hBrush = (HBRUSH) SelectObject (hdc, hBrush) ; if (iFigure == IDC_RECT) Rectangle (hdc, rect.left, rect.top, rect.right, rect.bottom) ; else Ellipse(hdc, rect.left, rect.top, rect.right, rect.bottom) ; DeleteObject (SelectObject (hdc, hBrush)) ; ReleaseDC (hwnd, hdc) ; } LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_PAINT: PaintTheBlock(hwnd, iColor, iFigure) ; return 0 ; case WM_DESTROY : DeleteObject((HGDIOBJ)SetClassLong(hwnd, GCL_HBRBACKGROUND,(LONG)GetStockObject (WHITE_BRUSH))) ; PostQuitMessage (0) ; return 0 ; } return DefWindowProc (hwnd, message, wParam, lParam) ;

Trang 51

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
} void PaintTheBlock (HWND hCtrl, int iColor[], int iFigure) { InvalidateRect (hCtrl, NULL, TRUE); UpdateWindow (hCtrl) ; PaintWindow (hCtrl, iColor, iFigure) ; } BOOL CALLBACK ColorScrDlg (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { HWND hwndParent, hCtrl ; static HWND hCtrlBlock ; int iCtrlID, iIndex ; switch (message) { case WM_INITDIALOG : hCtrlBlock = GetDlgItem (hDlg, IDC_PAINT) ; for (iCtrlID = 10 ; iCtrlID < 13 ; iCtrlID++) { hCtrl = GetDlgItem (hDlg, iCtrlID) ; PaintTheBlock (hCtrlBlock, iColor, iFigure) ; PaintTheBlock (hwndParent, iColor, iFigure) ; SetScrollRange (hCtrl, SB_CTL, 0, 255, FALSE) ; SetScrollPos(hCtrl, SB_CTL, 0, FALSE) ; }

Trang 52

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
return TRUE ; case WM_COMMAND: { switch( LOWORD(wParam)) { case IDC_RECT: case IDC_ELLIPSE: iFigure = LOWORD(wParam) ; hwndParent = GetParent (hDlg) ; CheckRadioButton(hDlg, IDC_RECT, IDC_ELLIPSE, LOWORD (wParam)) ; PaintTheBlock(hCtrlBlock, iColor, iFigure) ; PaintTheBlock (hwndParent, iColor, iFigure) ; return TRUE ; } break; } case WM_VSCROLL : hCtrl = (HWND) lParam ; iCtrlID = GetWindowLong (hCtrl, GWL_ID) ; iIndex = iCtrlID - 10 ; hwndParent = GetParent (hDlg) ; PaintTheBlock (hCtrlBlock, iColor, iFigure) ; PaintTheBlock (hwndParent, iColor, iFigure) ; switch (LOWORD (wParam)) {

Trang 53

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
case SB_PAGEDOWN : iColor[iIndex] += 15 ; case SB_LINEDOWN : iColor[iIndex] = min (255, iColor[iIndex] + 1) ; break; case SB_PAGEUP : iColor[iIndex] -= 15 ; case SB_LINEUP : iColor[iIndex] = max (0, iColor[iIndex] - 1); break; case SB_TOP : iColor[iIndex] = 0 ; break; case SB_BOTTOM : iColor[iIndex] = 255 ; break; case SB_THUMBPOSITION : case SB_THUMBTRACK : iColor[iIndex] = HIWORD (wParam) ; break; default : return FALSE ; } SetScrollPos(hCtrl, SB_CTL, iColor[iIndex], TRUE) ; SetDlgItemInt (hDlg, iCtrlID + 3, iColor[iIndex], FALSE) ;

Trang 54

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
InvalidateRect(hwndParent,NULL,TRUE); DeleteObject ( (HGDIOBJ)SetClassLong( hwndParent, GCL_HBRBACKGROUND, (LONG) CreateSolidBrush( RGB(iColor[0], iColor[1], iColor[2]) ) ) ) ; return TRUE ; case WM_PAINT: PaintTheBlock(hCtrlBlock, iColor, iFigure) ; break; } return FALSE ; }

2.3. MENU
Trong giao di n ng d ng Windows, thành ph n quan tr ng thư ng không th thi u là menu c a chương trình. Menu xu t hi n ngay dư i thanh tiêu c a chương trình ng d ng. Ngoài ra trong m t s ng d ng thanh menu có th di chuy n ư c. Th t ra menu cũng khá ơn gi n, vì chúng ư c t ch c thành các nhóm trên thanh chính (File, Edit, View,…), m i m c li t kê trong menu chính có th ch a m t hay nhi u m c li t kê g i là menu popup hay dropdown, và v i m i m c li t kê trong menu popup này có th có các m c con c a nó,…. Các m c li t kê trên menu có th dùng kích ho t m t l nh, hay ch n tr ng thái (check, uncheck). Các m c li t kê trên menu có 3 d ng: có hi u l c (enabled), không có hi u l c (disabled), và màu xám (grayed). V i quan i m l p trình thì ta ch c n hai tr ng thái là có hi u l c và không có hi u l c mà thôi, do ó tr ng thái màu xám s ch cho ngư i dùng bi t là tr ng thái c a m c li t kê có hi u l c hay không. Vì v y khi vi t chương trình nh ng m c nào không có hi u l c thì ta thi t l p tr ng thái màu xám, khi ó ngư i dùng s bi t r ng m c li t kê ó không có hi u l c.

2.3.1. Thi t l p Menu
t o m t menu và ưa vào chương trình bao g m các bư c sau: *T o menu trong t p tin tài nguyên *.RC: t o menu trong t p tin tài nguyên, thư ng có 2 cách chính là: dùng m t trình so n th o m t p tin tài nguyên và so n th o theo c u trúc Trang 55

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ t p tin RC cung c p cho tài nguyên menu. Thông thư ng, cách này ít s d ng, vì các môi trư ng phát tri n C trên Windows (Borland C for Windows, Visual C) u cung c p các công c cho phép t o menu m t cách d dàng. *Cài t menu vào c a s c a chương trình ng d ng: ph n này ơn gi n là khi nh nghĩa l p c a s ta thi t l p thu c tính lpszMenuName c a c u trúc l p WNDCLASS b ng tên menu ư c khai báo trong t p tin tài nguyên. Ví d : wndclass.lpszMenuName = "MENU1"; Ngoài ra, có th cài t menu vào c a s b ng cách dùng l nh :

hMenu = LoadMenu ( hInstance, TEXT("MENU1") ); L nh này s tr v m t nh danh c a menu ư c n p, khi có ư c thì khi ưa vào c a s có 2 cách sau: *Trong hàm t o c a s CreateWindow, tham s th 9 c a hàm là thi t l p tham s này là nh danh c a menu v a t o. nh danh menu này nh danh cho menu,

hwnd = CreateWindow ( TEXT("MyClass"), TEXT("Window Caption"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, hMenu, hInstance, NULL ); *Khi g i hàm t o c a s CreateWindow, tham s th 9 ư c thi t l p NULL, sau ó trong chương trình dùng l nh: SetMenu(hWnd, hMenu); thi t l p menu cho c a s . *Thêm các o n chương trình x lý menu: Windows phát sinh thông i p WM_COMMAND và g i n chương trình khi ngư i dùng ch n m t m c li t kê có hi u l c trên thanh menu. Khi ó ch c n x lý thông i p WM_COMMAND b ng cách ki m tra 16 bit th p c a tham s wParam là xác nh ư c ID c a m c li t kê nào trên menu ư c ch n.

2.3.2. Ví d minh h a Menu
*T p tin tài nguyên ch a khai báo menu : MENUDEMO.RC
MENUDEMO MENU DISCARDABLE BEGIN POPUP "&File" BEGIN MENUITEM "&New", IDM_FILE_NEW

Trang 56

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
MENUITEM "&Open", IDM_FILE_OPEN MENUITEM "&Save", IDM_FILE_SAVE MENUITEM "Save &As...", IDM_FILE_SAVE_AS MENUITEM SEPARATOR MENUITEM "E&xit", IDM_APP_EXIT END POPUP "&Edit" BEGIN MENUITEM "&Undo", IDM_EDIT_UNDO MENUITEM SEPARATOR MENUITEM "C&ut", IDM_EDIT_CUT MENUITEM "&Copy", IDM_EDIT_COPY MENUITEM "&Paste", IDM_EDIT_PASTE MENUITEM "De&lete", IDM_EDIT_CLEAR END POPUP "&Background" BEGIN MENUITEM "&White", IDM_BKGND_WHITE, CHECKED MENUITEM "&Light Gray", IDM_BKGND_LTGRAY MENUITEM "&Gray", IDM_BKGND_GRAY MENUITEM "&Dark Gray", IDM_BKGND_DKGRAY MENUITEM "&Black", IDM_BKGND_BLACK END POPUP "&Help" BEGIN

Trang 57

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
MENUITEM "&Help...", IDM_APP_HELP MENUITEM "&About ...", IDM_APP_ABOUT END END

*T p tin tiêu

ch a các

nh nghĩa : MENUDEMO.H

#define IDM_FILE_NEW 40001 #define IDM_FILE_OPEN 40002 #define IDM_FILE_SAVE 40003 #define IDM_FILE_SAVE_AS 40004 #define IDM_APP_EXIT 40005 #define IDM_EDIT_UNDO 40006 #define IDM_EDIT_CUT 40007 #define IDM_EDIT_COPY 40008 #define IDM_EDIT_PASTE 40009 #define IDM_EDIT_CLEAR 40010 #define IDM_BKGND_WHITE 40011 #define IDM_BKGND_LTGRAY 40012 #define IDM_BKGND_GRAY 40013 #define IDM_BKGND_DKGRAY 40014 #define IDM_BKGND_BLACK 40015 #define IDM_APP_HELP 40018 #define IDM_APP_ABOUT 40019

*T p tin ch a mã ngu n : MENUDEMO.C
#include <windows.h> #include "menudemo.h"

Trang 58

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); /* Khai báo tên dùng chung cho cáctài nguyên trong chương trình.*/ TCHAR szAppName[] = TEXT ("MenuDemo") ; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { 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 = szAppName ; wndclass.lpszClassName = szAppName ; if (!RegisterClass (&wndclass)) { MessageBox(NULL, TEXT("This program requires Windows "), szAppName, MB_ICONERROR) ; return 0 ; }

Trang 59

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
hwnd = CreateWindow (szAppName, TEXT("Menu Demonstration"), WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL) ; ShowWindow (hwnd, iCmdShow) ; UpdateWindow (hwnd) ; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage (&msg) ; DispatchMessage (&msg) ; } return msg.wParam ; } LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { /* Khao báo danh sách các màu ch i tô, các h ng này ư c nh nghĩa trong file WINGDI.H */

static int idColor[5] = { WHITE_BRUSH, LTGRAY_BRUSH, GRAY_BRUSH, DKGRAY_BRUSH, BLACK_BRUSH } ; static int iSelection = IDM_BKGND_WHITE ; HMENU hMenu ; switch (message) { case WM_COMMAND: hMenu = GetMenu (hwnd) ; // L y nh danh c a menu nh danh m c ch n

switch (LOWORD (wParam)) // Ki m tra { case IDM_FILE_NEW:

Trang 60

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
case IDM_FILE_OPEN: case IDM_FILE_SAVE: case IDM_FILE_SAVE_AS: MessageBeep(0) ; //Phát ra ti ng kêu bíp return 0 ; case IDM_APP_EXIT: /*G i thông i p óng ng d ng l i*/

SendMessage (hwnd, WM_CLOSE, 0, 0) ; return 0 ; case IDM_EDIT_UNDO: case IDM_EDIT_CUT: case IDM_EDIT_COPY: case IDM_EDIT_PASTE: case IDM_EDIT_CLEAR: MessageBeep (0) ; return 0 ; case IDM_BKGND_WHITE: case IDM_BKGND_LTGRAY: case IDM_BKGND_GRAY: case IDM_BKGND_DKGRAY: case IDM_BKGND_BLACK: /* B check c a m c ch n trư c ó*/ CheckMenuItem(hMenu,iSelection, MF_UNCHECKED); iSelection = LOWORD (wParam) ; /*L y ID m c m i*/ /* Check m c ch n m i*/

Trang 61

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
CheckMenuItem (hMenu, iSelection, MF_CHECKED) ; /* Thi t l p màu tương ng v i m c ch n m i*/ SetClassLong(hwnd,GCL_HBRBACKGROUND, (LONG) GetStockObject(idColor[iSelectionIDM_BKGND_WHITE]));

InvalidateRect (hwnd, NULL, TRUE) ; return 0 ; case IDM_APP_HELP: MessageBox(hwnd, TEXT("Help not yet implemented!"), szAppName, MB_ICONEXCLAMATION | MB_OK) ; return 0 ; case IDM_APP_ABOUT: MessageBox (hwnd, TEXT ("Menu Demonstration Program\n (c) Charles Petzold, 1998"), szAppName, MB_ICONINFORMATION | MB_OK) ; return 0 ; } break; case WM_DESTROY: PostQuitMessage(0) ; return 0 ; } return DefWindowProc(hwnd, message, wParam, lParam) ; }

Trang 62

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________

Chương 3 CÁC
3.1. M U

I TƯ NG I U KHI N

Các i tư ng i u khi n (control) là các thành ph n tương tác tr c quan, th hi n rõ cơ ch giao ti p h a gi a ng d ng và ngư i dùng. Nh các i tư ng này, các chương trình ng d ng trong Windows tr nên thân thi n và d dùng. Ví th , chúng là các thành ph n cơ b n không th thi u trong h u h t các ng d ng. Trong chương này, chúng ta s tìm hi u các t o l p và x lý cho các thông qua các l p (class) sau : • • • • • • L L L L L L p Button (nút b m). p Static (tĩnh). p Edit Box (so n th o). p List Box (danh sách). p Combo Box. p Scroll Bar (thanh cu n). i tư ng i u khi n

3.2. GI I THI U T NG QUAN

Trang 63

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ M t ki u i u khi n ư c xem như là m t c a s con. Có th t o nhi u c a s con trong cùng m t c a s cha. Các c a s con xác nh handle c a s c a cha b ng cách g i hàm : hwndParent = GetParent (hwnd); hwnd là handle c a c a s con c n l y handle c a c a s cha. Và khi ã l y ư c handle c a c a s cha, c a s con có quy n g i các thông i p n c a s cha thông qua hàm. SendMessage(hwndParent, message, wParam, lParam); message là thông i p c n g i n th t c x lý c a c a s cha. wParam là ch danh ID c a c a s con, còn lParam ghi l i tr ng thái c a c a s con. V y chúng ta có th t o m t thành ph n i u khi n d ng c a s con hay còn g i là "child window control". C a s con có nhi m v x lý các thông i p như bàn phím, thông i p chu t và thông báo cho c a s cha khi tr ng thái c a c a s con thay i. Như v y c a s con tr thành công c giao ti p (cho phép nh p và xu t) gi a ngư i dùng v i chương trình. Tuy chúng ta có th t o ra m t c a s con cho chính mình, nhưng chúng ta nên t n d ng các l p c a s con ã ư c Windows nh nghĩa s n hay còn g i là nh ng ki u i u khi n chu n. Nh ng ki u i u khi n chu n này thư ng là các nút b m (button), h p ki m tra (check box), h p so n th o (edit box), h p danh sách (list box), combo box, các thanh cu n và chu i ch . Ví d mu n t o ra m t nút b m trên màn hình ch c n g i hàm CreateWindows, mà ch ng c n ph i quan tâm n cách v , cách nh n chu t hay là ch p khi b kích ho t. T t c i u này u do Windows x lý. i u quan tr ng làph i ch n thông i p WM_COMMAND c a các i u khi n x lý thông i p này theo nh ng m c ích khác nhau. Các ki u i u khi n con thư ng ư c dùng trong h p tho i. Như ã minh h a trong ó các i u khi n nh n h p tho i làm c a s cha. Tuy nhiên, cũng có th t o các chương 2, ki u i u khi n con tr c ti p trên vùng c a s chính, b ng cách g i hàm CreateWindow và i u ch nh v trí cùng v i kích thư c c a nó cho thích h p b ng hàm MoveWindow. Th t c x lý thông i p c a c a s cha g i các thông i p n các khi u i u khi n con, và ngư c l i các child window control g i các thông i p yêu c u c a s cha x lý các thông i p ó. t o m t c a s ng d ng bình thư ng. u tiên ph i ăng ký l p c a s b ng hàm RegisterClass. Ti p theo là kh i t o l p ã ăng ký thông qua hàm CreateWindow. Còn trư ng h p mu n t o m t l p ã ư c nh nghĩa s n thì không c n ăng ký cho l p c a s con mu n t o. S d ng các ki u i u khi n tr c ti p trên c a s chính òi h i các tác v c p th p hơn so v i dùng các ki u i u khi n trên h p tho i. Và các ki u i u khi n t o ra trên c a s chính không có h tr các ti n ích. Ví d như chúng ta không th s d ng phím b m tab chuy n focus gi a các ki u i u khi n v i nhau.

3.3. L P BUTTON
Trang 64

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ tìm hi u các ki u i u khi n, xem xét ví d 3.1 sau. Trong ví d này ã t o ra 9 c a s con chu n trên m t c a s cha như hình 3.1.

Hình 3.1 Minh h a các l p Button

Nh p chu t vào các nút, lúc ó các nút s g i thông i p WM_COMMAND n th t c x lý thông i p WndProc c a c a s cha. Th t c WndProc x lý và in ra màn hình các thông s lParam và wParam c a thông i p g i t i này.Trong ó lParam là handle c a c a s con g i thông i p n c a s cha. wParam có hai ph n LOWORD và HIWORD, LOWORD cho bi t ID c a c a s con, HIWORD là mã thông báo. Mã thông báo nút b m là m t trong nh ng giá tr sau. nh danh mã thông báo Button BN_CLICKED BN_PAINT BN_HILETE hay BN_PUSHED BN_UNHILITE hay BN_UNPHUSHED BN_DISABLE BN_DOUBLECLICKED hay BN_DBCLICK BN_SETFOCUS BN_KILLFOCUS Giá tr 0 1 2 3 4 5 6 7

Trang 65

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam
nh danh mã thông báo Button

____________________________________________________________________________________
B ng 3.1

Không bao gi th y ư c các giá tr c a nút b m, ch bi t r ng giá tr t 1 n 4 dành cho ki u button BS_USERBUTTON, giá tr 5 dành cho ki u BS_RADIOBUTTON, BS_AUTORADIOBUTTON, BS_OWNEDRAW, hay các nút b m khác n u nút b m ó bao g m ki u BS_NOTYFY. Giá tr 5,6 dành cho các ki u nút b m bao g m c c NOTYFY. Sau ây là chương trình chính. *CONTROL1.CPP (trích d n)
struct { int iStyle ; TCHAR *szText ; } button[ ] = { BS_PUSHBUTTON, TEXT ("PUSHBUTTON"), BS_DEFPUSHBUTTON, TEXT ("DEFPUSHBUTTON"), BS_CHECKBOX, TEXT ("CHECKBOX"), BS_AUTOCHECKBOX, TEXT ("AUTOCHECKBOX"), BS_RADIOBUTTON, TEXT ("RADIOBUTTON"), BS_3STATE, TEXT ("3STATE"), BS_AUTO3STATE, TEXT ("AUTO3STATE"), BS_GROUPBOX, TEXT ("GROUPBOX"), BS_AUTORADIOBUTTON, TEXT ("AUTORADIO") }; #define NUM (sizeof(button) / sizeof(button[0])) LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

Trang 66

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static HWND hwndButton[NUM] ; static RECT rect ; static TCHAR szTop[] = TEXT("message wParam lParam"), szUnd[] = TEXT("_______ ______ ______"), szFormat[] = TEXT("%-16s%04X-%04X %04X-%04X"), szBuffer[50]; static int cxChar, cyChar ; HDC hdc ; PAINTSTRUCT ps ; int i ; switch (message) { case WM_CREATE : cxChar = LOWORD(GetDialogBaseUnits()) ; cyChar = HIWORD(GetDialogBaseUnits()) ; for (i = 0 ; i < NUM ; i++) hwndButton[i] = CreateWindow(TEXT("button"), button[i].szText, WS_CHILD|WS_VISIBLE|button[i].iStyle, cxChar, cyChar*(1+2*i), 20*cxChar, 7*cyChar/4, hwnd, (HMENU)i, ((LPCREATESTRUCT)lParam)->hInstance, NULL) ; return 0 ; case WM_SIZE : rect.left = 24*cxChar ; rect.top = 2*cyChar ;

Trang 67

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
rect.right = LOWORD(lParam) ; rect.bottom = HIWORD(lParam) ; return 0 ; case WM_PAINT : InvalidateRect (hwnd, &rect, TRUE) ; hdc = BeginPaint (hwnd, &ps) ; SelectObject(hdc,GetStockObject(SYSTEM_FIXED_FONT)); SetBkMode (hdc, TRANSPARENT) ; TextOut (hdc, 24 * cxChar, cyChar, szTop, lstrlen (szTop)); TextOut (hdc, 24 * cxChar, cyChar, szUnd, lstrlen (szUnd)) ; EndPaint (hwnd, &ps) ; return 0 ; case WM_DRAWITEM : case WM_COMMAND : ScrollWindow (hwnd, 0, -cyChar, &rect, &rect) ; hdc = GetDC (hwnd) ; SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT)); TextOut (hdc, 24*cxChar, cyChar*(rect.bottom/cyChar-1), szBuffer, wsprintf (szBuffer, szFormat, message==WM_DRAWITEM ? TEXT ("WM_DRAWITEM") : TEXT ("WM_COMMAND"), HIWORD (wParam), LOWORD (wParam), HIWORD (lParam), LOWORD (lParam))) ; ReleaseDC (hwnd, hdc); ValidateRect (hwnd, &rect); break; case WM_DESTROY : PostQuitMessage(0) ; return 0 ;

Trang 68

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

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

t o ra m t child window control b n dùng c u trúc CreateWindow v i các thông s như sau. • • • • • • • • • • • Tên l p : TEXT ("button") Text c a s : Button[i].szText Ki u c a s : WS_CHILD | WS_VISIBLE | button[i].iStyle V trí x : cxChar V trí y : cyChar*( 1+2*i ) Chi u r ng : 20*xChar Chi u cao : 7*yChar*4 Handle c a s cha : hwnd Ch danh c a c a s con : (HMENU) i Th qu n Handle : ((LPCREATESTRUCT) lParam-> hInstance, NULL) ; Các thông s thêm : NULL

nh. Tên c a s do chúng ta t. Ki u c a s s d ng là Trong ó tên l p là c WS_CHILD, WS_VISIBLE và m t trong 9 ki u button (BS_PUSHBUTTON, BS_CHECKBOX,...). Ti p theo là 4 thông s xác nh ví trí x, ví trí y, kích thư c theo chi u r ng, kích thư c chi u cao c a c a s con trên vùng client c a c a s cha. hwnd là handle c a c a s cha. ID là ch danh c a m i c a s con (m i c a s con có duy nh t m i s ID). ID này ph i ép ki u HMENU ch nh trình ơn. lParam th c ch t là m t con tr n c u trúc LPCREATESTRUCT có thành ph n hInstance. Dó ó mu n l y th qu n hInstance thì ph i ép ki u lParam.

3.3.1. L p Push Button
Trong ví d 3.1 có hai Push Button ư c t o ra b ng hàm CreateWindow v i kích thư c và ví trí ư c xác nh b i ngư i l p trình. Các Push Button ư c s d ng b t t t m t hành ng t c th i ch không gi ư c tr ng thái b t hay t t lâu dài như checkbox ư c. Trên ây là hai ki u c a s BS_PUSHBUTTON và BS_DEFBUTTON (ki u nút b m m c nh). Hai ki u này khi thi t k thì khác nhau nhưng khi s d ng thì nó có ch c năng hoàn toàn gi ng nhau. Khi nh n chu t vào nút này thì nút này g i thông i p WM_COMMAND n c a s cha v i mã thông báo BN_CLICK. Có th tác ng n nút b m này b ng cách g i hàm. SendMessage( hwndButton, BM_SETSTASE, 1, 0 ); N u mu n nút nh n này tr l i tr ng thái bình thư ng thì g i hàm : Trang 69

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ SendMessage(hwndButton, BM_SETSTASE, 0, 0 ); hwndButton là nh danh c a c a s con ư c tr v b i hàm CreateWindow.

3.3.2. L p Check Box
M t check box là là m t h p vuông kèm theo ch . Thông thư ng ch n m bên trái c a h p. Tuy nhiên, cũng có th t ch n m bên ph i b ng cách thêm vào ki u BS_LEFTTEXT khi t o m t button. Các check box cho phép ngư i dùng ch n các tùy ch n, nó ho t ng như m t công t c. Có hai lo i check box thông d ng ó là BS_CHECKBOX và BS_AUTOCHECKBOX. Khi s d ng lo i BS_CHECKBOX, chúng ta t t d u check box b ng cách g i n ki u i u khi n này thông i p BS_SETCHECK. Thông s wParam trong hàm SendMessage ư c t giá tr 1 t o ánh d u, và b ng 0 khi mu n h y ánh d u. L y tr ng thái c a m t check box b ng cách g i n ki u i u khi n này thông i p BM_GETCHECK. Dùng o n chương trình sau b t t t d u check khi x lý thông i p WM_COMMAND ư c g i n t các ki u i u khi n.
SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)!SendMessage( (HWND)lParam, BM_GETCHECK, 0, 0), 0);

Chú ý toán t ! (NOT) ng trư c hàm SendMessage. Giá tr lParam là handle c a c a s con g i n c a s cha trong thông i p WM_COMMAND. Mu n bi t tr ng thái c a check kh i ng m t check box lo i box nào ó thì g i t i nó thông i p BM_GETCHECK. BS_CHECKBOX v i tr ng thái ư c ánh d u, b ng cách g i n nó m t thông i p BM_SETCHECK theo c u trúc. SendMessage (hwndButton,BM_SETCHECK, 1, 0); Còn check box BS_AUTOCHECK là lo i nút b m mà t nó ánh d u b t hay t t cho chính nó. Mu n l y tr ng thái c a check box hi n hành, ch c n g i thông i p BM_GETCHECK n ki u i u khi n này theo c u trúc. iCheck = SendMessage (hwndButton, BM_SETCHECK, 1, 0); iCheck mang giá tr TRUE n u check box giá tr FALSE. tr ng thái ch n, còn ngư c l i iCheck mang

Ngoài ra còn có hai lo i check box khác là BS_3STATE và BS_AUTO3STATE. Hai lo i này còn có thêm tr ng thái th 3, ó là tr ng thái nút check box có màu xám xu t hi n khi b n g i thông i p WM_SETCHECK v i tham s wParam b ng 2 n check box này. Màu xám cho bi t ngư i dùng ch n l a không thích h p hay không xác nh.

3.3.3. L p Radio Button

Trang 70

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ M t radio button là m t vòng tròn có kèm theo ch . T i m t th i i m ch có m t radio button ư c nh n. Các radio thư ng ư c nhóm l i s d ng cho vi c l a ch n duy nh t trong nhóm. Tr ng thái các radio button không b t t t như check box. Có nghĩa, khi nh n chu t vào radio button thì button này ư c ánh d u, và khi ta nh n chu t vào m t l n n a thì radio ó cũng v n tr ng thái ánh d u. Có hai ki u radio button là BS_RADIOBUTTON và BS_AUTORADIOBUTTON, nhưng ki u th hai ch s d ng trong h p tho i. Khi nh n thông i p WM_COMMAND t radio button, thì chúng ta ph i ánh d u radio ó b ng cách g i thông i p BM_SETCHECK v i thông s wParam b ng 1 như sau. SendMessage(hwndButton, BM_SETCHECK, 1, 0); T t c các radio button trong cùng m t nhóm, n u b n mu n t t d u check thì b n g i chúng thông i p BM_SETCHECK v i thông s wParam b ng 0 như sau. SendMessage(hwndButton, BM_SETCHECK, 0, 0); n

3.3.4. L p Group Box
Group box có ki u BS_GROUPBOX, ây là lo i button c bi t. M t group box ch ơn gi n là m t ư ng vi n có dòng tiêu trên nh. Group box không x lý các thông i p bàn phím, không x lý các thông i p chu t và cũng không g i thông i p WM_COMMAND n c a s cha c a nó. Các group box thư ng ư c s d ng bao quanh các ki u i u khi n khác.

3.4. L P STATIC
T o ra m t l p tĩnh b ng cách s d ng "static" khi t o l p c a s trong hàm CreateWindow. L p tĩnh không nh n nh p d li u t bàn phím cũng như t chu t, và không g i thông i p WM_COMMAND n c a s cha. Khi di chuy n hay nh n chu t vào các c a s con tĩnh, c a s con này b y thông i p WM_NCHITTEST và tr v giá tr HTTRANSPARENT n Windows. i u này làm cho Windows g i cùng thông i p WM_NCHITTEST cho c a s cha. C a s cha thư ng g i thông i p này n th t c DefWindowProc. Các ki u c a s tĩnh sau ây dùng v m t hình ch nh t hay m t khung lên vùng client c a c a s con. Các ki u FRAME là nh ng ư ng bao hình ch nh t, các ki u RECT là nh ng hình ch nh t : SS_BLACKRECT, SS_GRAYRECT, SS_ WHITERECT. SS_BLACKFRAME, SS_GRAYFAME, SS_WHITEFRAME.

3.5. L P EDIT TEXT
Trong m t phương di n nào ó thì l p so n th o (edit text) ư c xem là m t c a s ư c nh nghĩa s n ơn gi n nh t. Nhưng xét m t khía c nh khác thì nó l i ph c t p nh t. Dùng tên Trang 71

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ l p "edit" cùng v i các thông s ví trí x, v trí y, chi u r ng, chi u cao trong hàm CreateWindow t o ra c a s so n th o. Khi c a s so n th o nh n focus thì chúng ta có th gõ ch vào, xoá các ch , ánh d u các ch …vv. Các thao tác trên ư c Windows h tr hoàn toàn. M t trong nh ng ng d ng thư ng xuyên nh t, và ơn gi n nh t c a l p so n th o là t o ra m t c a s cho phép ngư i dùng nh p các ch vào. minh h a cho c a s nh p ta xét ví d 3.2 sau. *EDITTEXT.CPP
#include <windows.h> #define ID_EDIT 1 LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); TCHAR szAppName[] = TEXT ("PopPad1") ; LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static HWND hwndEdit ; switch (message) { case WM_CREATE : hwndEdit = CreateWindow (TEXT("edit"), NULL, WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL | WS_BORDER | ES_LEFT | ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0, 0, 0, 0, hwnd, (HMENU)ID_EDIT, ((LPCREATESTRUCT) lParam) -> hInstance, NULL) ; return 0 ; case WM_SETFOCUS : SetFocus (hwndEdit) ; return 0 ; case WM_SIZE : MoveWindow (hwndEdit, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);

Trang 72

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
return 0 ; case WM_COMMAND : if (LOWORD (wParam) == ID_EDIT) if ( HIWORD(wParam)==EN_ERRSPACE || HIWORD(wParam)==EN_MAXTEXT ) MessageBox(hwnd, TEXT("Edit control out of space."), szAppName, MB_OK | MB_ICONSTOP) ; return 0 ; case WM_DESTROY : PostQuitMessage(0) ; return 0 ; } return DefWindowProc (hwnd, message, wParam, lParam) ; }

H n ch c a edit box ư c quá 30.000 ký t ch .

nh nghĩa s n là s ký t ngư i dùng nh p vào ph i không

3.5.1. Các ki u l p Edit Text
Trong ví d trên ã t o m t edit box b ng cách g i hàm CreateWindow. Có ki u c a s là WS_CHILD, cùng m t s tùy ch n. Chúng ta có th canh trái, ph i, gi a các ch trong vùng c a s edit box b ng cách thay i thông s ki u c a s ES_LEFT, ES_RIGHT, ES_CENTER trong hàm CreateWindow. Có th t o m t edit control cho phép hi n th nhi u hàng b ng cách ch n ki u c a s ES_MULTILINE. M t edit control m c nh ch cho phép nh p m t hàng ký t cho n cu i edit box. S d ng ES_AUTOHSCROLL, ES_AUTOVSCROLL t o m t edit control có thanh cu n ngang, và cu n ng t ng. Có th thêm thanh cu n ngang và ng vào edit control b ng cách s d ng ki u c a s WS_HSCROLL, WS_VSCROLL. Dùng ki u c a s WS_BORDER t o ư ng vi n cho edit control. Kích thư c c a edit control ư c xác nh b ng cách g i hàm MoveWindow khi hàm WndProc x lý thông i p WM_SIZE. Trong ví d trên thì kích thư c c a edit control ư c b ng kích thư c c a c a s chính. MoveWindow(hwndEdit, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE); t

Trang 73

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ Các edit control g i thông i p WM_COMMAND cùng các thông s wParam, lParam n window c a s cha. V i ý nghĩa : LOWORD(wParam) là ID c a s con, HIWORD(wParam) là mã thông báo. lParam là handle c a edit control. Mã thông báo EN_SETFORCUS EN_KILLFORCUS EN_CHANGE EN_UPDATE EN_ERRSPACE EN_MAXTEXT EN_HSCROLL EN_VSCROLL ý nghĩa Endit control nh n focus nh p. Endit control m t focus nh p. N i dung c a edit control s thay N i dung c a edit control thay Edit control ch y quá th i gian. Edit control ch y quá không gian khi chèn. Thanh cu n ng c a edit control b tác ng. ng. i. i.

Thanh cu n n m c a edit control b tác
B ng 3.2 Danh sách mã thông báo c a edit Control.

3.5.2. Các thông i p

n m t l p Edit Text
ư c ch n (selected).

Các th t thông i p sau cho phép c t, sao chép, xoá các ph n ch SendMessage (hwndEdit, WM_CUT, 0, 0); SendMessage (hwndEdit, WM_COPY, 0, 0); SendMessage (hwndEdit, WM_CLEAR, 0, 0);

V i WM_CUT c t ph n ch ã ư c ánh d u ưa vào vùng Clipboard. WM_COPY sao chép ph n ch ã ư c ánh d u ưa vào Clipboard nhưng ph n ánh d u v n còn trên edit control. WM_CLEAR xóa ph n ch ã ư c ánh d u mà không ưa vào clipboard. Chèn ph n ch n m trong clipboard vào vùng so n th o edit control b ng cách g i hàm. SendMessage (hwndEdit, WM_PASTE , 0, 0); Nh n b t u và k t thúc c a ph n ch ã ch n b ng cách g i hàm :

Trang 74

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ SendMessage (hwndEdit, EM_GETSEL, (WPARAM)&iStart, (LPARAM)&iEnd ); iStart lưu v trí b t thay th ph n ch u và iEnd lưu ví trí k t thúc. ã ch n b ng ch khác, ta dùng hàm ;

SendMessage(hwndEdit,EM_REPLACESEL,0,(LPARAM)szString); Trong ó szString là chu i mu n thay th . i v i edit control nhi u dòng, ta m s dòng ch b ng hàm.

iCount = SendMessage (hwndEdit, EM_GETLINECOUNT, 0, 0); Các dòng trong edit control ư c ánh s b t th t t 0. L y chi u dài c a m t dòng b ng l nh. iLength = SendMessage (hwndEdit, EM_LINELENGTH, iLine, 0). Chép hàng này vào b m b ng cách g i hàm.

iLength = SendMessage ( hwdEdit, EM_GETLINE, iLine, (LPARAM)Buffer ).

3.6. L P LIST BOX
List box là t p h p các chu i kí t ư c gói g n trong m t hình ch nh t. M t chương trình có th thêm ho c xóa các chu i trong list box b ng cách g i các thông i p n th t c window c a list box. List box control g i thông i p WM_COMMAND n c a s cha khi có m t m c trong list box b ánh d u. C a s cha xác nh n các m c trong list box ã b ánh d u. M t list box có th ch n ư c m t m c hay nhi u m c cùng m t lúc (tùy theo lo i list box ơn hay kép).

3.6.1 Các ki u List Box
Chúng ta t o m t c a s con list box b ng hàm CreateWindow v i l p c a s là "listbox" cùng v i lo i c a s WS_CHILD. Tuy nhiên ki u c a s con m t nh này không g i thông i p WM_COMMAND n c a s cha, có nghĩa chương trình t ki m tra vi c ánh d u các danh m c trong list box. Vì th , các ki u i u khi n list box thư ng nh nghĩa ki u list box LBS_NOTYFY, i u này cho phép c a s cha nh n thông i p WM_COMMAND t list box. N u mu n s p x p các m c trong list box thì s d ng ki u LBS_SORT. Theo m c nh, nh ng list box t o ra là nh ng list box ơn. Vì th , n u mu n t o ra m t list box kép (t c list box cho phép ngư i dùng ch n nhi u dòng cùng lúc) thì ph i s d ng lo i list box LBS_MULTIPLESEL.Thông thư ng, List box s t c p nh t khi m t m c ư c thêm Trang 75

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ vào. Tuy nhiên có th ngăn c n vi c c p nh t này b ng ki u LBS_NOREDRAW. Vi c làm này ôi khi không thích l m, thay vào ó chúng ta có th s d ng thông i p WM_SETREDRAW ngăn ch n t m th i vi c v l i c a list box. Theo m c nh, các m c trong list box không có ư ng vi n bao quanh khi hi n th trên màn hình. Tuy nhiên, có th thêm ư ng vi n cho các m c b ng nh danh c a s WS_BORDER. Thêm thanh cu n ng vào list box b ng cách thêm nh danh c a s WS_VSCROLL. Thông thư ng windows nh nghĩa m t list box g m các thông s sau : LBS_NOTIFY | LBS_SORT | WS_VSCROLL | WS_BORDER. Ngoài ra còn có các thông s WS_SIZEBOX và WS_CAPTION dùng thay i kích thư c và thêm tiêu cho list box. Nên t o ra m t list box có chi u r ng b ng chi u dài c a chu i dài nh t trong list box c ng v i chi u dài c a thanh cu n d c. Chi u dài c a thanh cu n d c ư c xác nh b ng hàm. GetSystemMetrics(SM_CXVCROLL);

3.6.2.

t các chu i vào List Box

thêm m t chu i vào list box ta g i các thông i p n th t c Windows list box b ng hàm SendMessage. Khi truy n chu i cho hàm SendMessage thì thông s wParam là m t con tr , tr n chu i ư c k t thúc b i ký t NULL. Hàm SendMessage tr v mã LB_ERRSPACE (giá tr -2) khi Windows ch y quá không gian b nh dành cho list box. Hàm SendMessage tr v mã LB_ERR ( -1) khi x y ra l i khác và tr v mã LB_OKAY ( 0 ) n u thao tác thêm thành công. N u s d ng ki u LBS_SORT thì khi thêm m t chu i vào list box ch c n dùng ch th LB_ADDSTRING theo c u trúc. SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM) szString); V i szString là chu i c n thêm vào list box. N u trong list box không dùng ki u LBS_SORT thì có th chèn m t chu i v i ch th LB_INSERTSTRING cùng v trí mu n chèn b ng hàm. SendMessage(hwndList, LB_INSERTSTRING, iIndex, (LPARAM) szString); iIndex là v trí mu n chèn chu i vào. N u giá tr này b ng -1 thì chu i ư c chèn vào áy c a list box. Xóa m t chu i trong list box b ng ch th LB_DELETESTRING.

Trang 76

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ SendMessage(hwndList, LB_DELETESTRING, iIndex, 0); Xóa h t các ph n t n m trong list box thì dùng ch th LB_RESETCONTENT v i c u trúc. SendMessage(hwndList, LB_LB_RESETCONTENT, 0, 0 ); Khi thêm vào hay xóa thì Windows t c p nh t l i list box. Tuy nhiên ta cũng có th t m th i c n s c p nh t này b ng cách t t c v l i list box. SendMessage(hwndList, WMSETREDRAW, FALSE, 0); Sau khi th c hi n xong ta b t c v l i list box b ng hàm. SendMessage(hwndList, WMSETREDRAW, TRUE, 0);

3.6.3. Ch n và l y các m c trên List Box
Tương t như t chu i vào List box , ch n và l y m c trong List box cũng ph i g i các thông i p n th t c Window List box b ng hàm SendMessage. Dùng ch th LB_GETCOUNT m s m c trong List box.

iCount = SendMessage (hwndList, LB_GETCOUNT, 0, 0 ); Làm sáng m c ch n m c nh thì dùng LB_SETCURSEL.

SendMessage (hwndList, LB_SETCURSEL, iIndex, 0 ); N u t giá tr iIndex b ng -1 thì window s b t t c các m c ch n. d a trên ch b t u c a m c, ta dùng hàm. ch n các m c

iIndex = SendMessage (hwndlist, LB_SELECTSTRING, iIndex, (LPARAM) szSearchString); iIndex là v trí b t u c a vi c tìm v i kí t u gi ng szSearchString. N u giá tr iIndex b ng -1 thì vi c tìm b t u t v trí u tiên. Hàm s tr v giá tr tìm ư ci. N u chu i không t n t i thì hàm tr v mã l i LB_ERR. Xác hàm. iIndex = SendMessage(hwndList, LB_GETCURSEL, 0, 0); nh m c ã ch n khi nh n ư c thông i p WM_COMMAND t list box b ng

Trang 77

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ Hàm tr v v trí c a m c ư c ch n, còn ngư c l i n u không có m c nào ư c ch n thì hàm tr v mã l i LB_ERR. Mu n xác nh chi u dài c a m t chu i b t kỳ có trong list box dùng hàm.

iLength = SendMessage(hwndList, LB_GETTEXTLEN, iIndex, 0); V i iIndex là ví trí c a chu i c n xác Buffer, ta dùng hàm. nh chi u dài. chép chu i trên vào vùng p

iLength = SendMessage(hwndList, LB_GETTEXT, iInde, (LPARAM) Buffer); Giá tr tr v c a hai hàm trên là chi u dài c a chu i ký t . Nên nh kích thư c vùng buffer sao cho ch a chi u dài c a chu i c ng thêm ký t k t thúc chu i c n ghi vào. Tuy nhiên, i v i list box ch n kép thì chúng ta không th dùng các ch th LB_SETCURSEL, LB_GETCURSEL, ho c LB_SELECTSTRING. Thay vào ó ph i dùng ch th LB_SETSEL ch n m t m c mà không làm nh hư ng n các m c ã ch n khác. SendMessage(hwndList, LB_SETSEL, wParam, iIndex); Tham s wParam khác 0 Xác ch n và làm sáng m c, b ng 0 h y vi c ch n.

nh tr ng thái c a m t m c nào ó trong list box (lo i list box ch n kép) dùng hàm.

iSelect = SendMessage(hwndList, LB_GETSEL, iIndex, 0); Hàm tr v giá tr khác 0 n u m c có v trí iIndex ư c ch n, và b ng 0 n u m c ó không ư c ch n. v trí

3.6.4. Nh n các thông i p t List Box
Khi dùng chu t nh n vào list box, khi ó list box nh n focus nh p. C a s cha có th focus nh p n list box b ng hàm. SetFocus (hwndList); Khi list box nh n focus nh p, chúng ta dùng con chu t, các phím ch , phím Spacebar ch n các m c trong list box. List box g i thông i p WM_COMMAND v i các thông s wParam, lParam n c a s cha v i ý nghĩa : LOWORD (wParam) ID c a s con. HIWORD (wParam) Mã thông báo. t

Trang 78

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ lParam Handle c a s con.
Mã thông báo LBN_ERRSPACE LBN_SELCHANGE Giá tr Ý nghĩa

-2 1 2 3 4 5

Con trol list box ch y quá không gian Cho bi t m c ch n hi n hành ã thay i

LBN_DBLCLK
LBN_SELCANCEL

Cho bi t m t m c ã b double click v i chu t Cho bi t ngư i dùng thay i m c ch n trong list box

LBN_SETFOCUS
LBN_KILLFOCUS

Cho bi t list box ang nh n ư c focus nh p Cho bi t list box ã m t focus nh p
B ng 3.3 Các giá tr c a mã thông báo

Mã thông báo LBN_ERRSPACE, LBN_SELCHANGE ư c g i ki u c a s list box bao g m LBS_NOTIFY.

n c a s cha khi

3.6.5. M t ng d ng List Box
Sau ây là m t ví d v list box, k t qu chương trình sau khi ch y th hi n trong hình 3.2. Trong ví d này, ta t o ra m t list box g m các ph n t cam, chanh, nho… . Khi dùng chu t hay dùng phím Spacebar c ng v i phím mũi tên ch n các m c trong list box, m c ư c ch n s có màu tô th hi n ư c ch n l a (m c nh trong Windows là màu xanh) và n i dung m c ch n này ư c hi n th lên ki u i u khi n tĩnh n m bên trên vùng thao tác c a c a s chính. Chương trình minh h a như sau (ví d 3.2).

Hình 3.2

ng d ng minh h a l p List Box

Trang 79

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ *LISTBOX.CPP (trích d n)
#include <windows.h> #define ID_LIST 1 #define ID_TEXT 2 LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); void FillListBox (HWND hwndList) { int i; static TCHAR *tc[]={TEXT("cam"), TEXT("quyt"), TEXT("buoi"), TEXT("tao"), TEXT("chanh"), TEXT("xoai"), TEXT("nho")}; for(i=0; i<7; i++) SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM)tc[i]); } LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static HWND hwndList, hwndText ; int iIndex, iLength, cxChar, cyChar ; TCHAR *pVarName; switch (message) { case WM_CREATE : cxChar = LOWORD (GetDialogBaseUnits ()) ; cyChar = HIWORD (GetDialogBaseUnits ()) ; // T o m t listbox

Trang 80

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
hwndList = CreateWindow ( TEXT("listbox"), NULL, WS_CHILD | WS_VISIBLE | LBS_NOTIFY | LBS_STANDARD, cxChar, cyChar * 3, cxChar * 16 + GetSystemMetrics (SM_CXVSCROLL), cyChar * 5, hwnd, (HMENU) ID_LIST, (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), NULL ) ; // t o m t control "static" hwndText = CreateWindow ( TEXT("static"), NULL, WS_CHILD | WS_VISIBLE | SS_LEFT, cxChar, cyChar, GetSystemMetrics (SM_CXSCREEN), cyChar, hwnd, (HMENU) ID_TEXT, (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), NULL) ; FillListBox (hwndList) ; return 0 ; case WM_SETFOCUS : // SetFocus (hwndList) ; return 0 ; //x lý các thông i p khi ch n m c trong list box case WM_COMMAND : if (LOWORD (wParam) == ID_LIST && HIWORD (wParam) == LBN_SELCHANGE) { // l y ch ví trí c a m c ư c ch n iIndex=SendMessage(hwndList,LB_GETCURSEL, 0, 0); iLength = SendMessage (hwndList, LB_GETTEXTLEN, iIndex, 0) + 1 ; pVarName =(char*) calloc (iLength, sizeof (TCHAR)) ; SendMessage ( hwndList, LB_GETTEXT, iIndex, (LPARAM)pVarName) ; SetWindowText (hwndText, pVarName) ; free (pVarName) ; } return 0 ; case WM_DESTROY : PostQuitMessage (0) ; t focus nh p cho list box

Trang 81

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

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

Khi dùng chu t hay bàn phím ch n m c trong list box, thì list box g i thông i p WM_COMMAND cho th t c WndProc c a c a s cha x lý. Khi th t c WndProc nh n ư c thông i p WM_COMMAND, nó ki m tra word th p c a tham s wParam có b ng nh danh c a list box ( ví d trên là ID_LIST) không và word cao c a tham s wParam(mã thông báo) có b ng LBN_SELCHANGE không. N u b ng, nó l y ch s c a m c ư c ch n thông qua hàm: SendMessage (hwndList, LB_GETCURSEL, 0, 0) ; Và ti p t c l y n i dung c a m c ư c ch n thông qua hàm. SendMessage ( hwndList, LB_GETTEXT, iIndex, (LPARAM) pVarName); Sau cùng, hi n th m c ư c ch n lên control tĩnh thông qua hàm. SetWindowText (hwndText, pVarName);

3.7. L P COMBO BOX
Cũng gi ng như List box, Combo box cũng là t p h p các chu i kí t ư c gói g n trong m t hình ch nh t. M t chương trình có th thêm ho c xóa các chu i trong Combo box b ng cách g i các thông i p n th t c window c a Combo box. Combo box control g i thông i p WM_COMMAND n c a s cha khi có m t m c trong Combo box ư c ánh d u. C a s cha xác nh n m c ư c ánh d u trong Combox box. Trong Combox box ch cho phép ch n m t m c trong danh sách các m c có trong Combo box.

3.7.1. S khác và gi ng nhau gi a Combo Box và List Box
Các thao tác trên list box và combo box là hoàn toàn gi ng nhau, ch khác nhau hình th c th hi n. List box hi n th các m c khi chúng ư c c p nh t, còn combo box ch hi n th các m c khi ta nh p chu t vào nó. Khi t o ki u i u khi n combo box v i hàm CreateWindow ph i s d ng l p c a s "combobox" cùng v i ki u c a s là WS_CHILD. List box có th cho phép ch n nhi u m c cùng lúc, còn combo box thì ch cho phép ch n m t m c mà thôi. Trang 82

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ Không gi ng như list box, combo box có hai ph n. Ph n dư i là danh sách các m c ư c thêm vào combo box, ph n trên là m t edit control dùng hi n th m c ch n hi n hành.

3.7.2. Thêm, xóa m t chu i trênCombo Box
thêm m t chu i vào combo box dùng hàm SendMessage v i thông i p CB_ADDSTRING: SendMessage (hWnd, CB_ADDSTRING, 0, (LPARAM) szString); hWnd là handle c a Combo box control, szString là chu i c n thêm vào. H n ch chi u dài c a chu i c n thêm vào b ng thông i p CB_LIMITTEXT. SendMessage (hWnd, CB_LIMITTEXT, (WPARAM)length, 0). length là chi u dài c a chu i c n thêm vào không k kí t k t thúc chu i. chèn m t chu i vào Combo box t i ví trí xác nh, ta dùng thông i p CB_INSERTSTRING. SendMessage (hWnd, CB_INSERTSTRING, iIndex, (LPARAM) szString). iIndex là v trí c n chèn chu i vào Combo box. ta dùng thông i p CB_RESETCONTENT. xóa t t c các m c trong Combo box,

SendMessage (hWnd, CB_RESETCONTENT, 0, 0). Tương t , ta có th xóa m t m c trong Combo box b ng thông i p CB_DELETESTRING. SendMessage (hWnd, CB_DELETESTRING, iIndex, 0);

3.7.3. Ch n và l y m c trên Combo box
m s m c có trong Combo box b ng thông i p CB_GETCOUNT. iCount = SendMessage (hWnd, CB_GETCOUNT, 0, 0). Hàm trên tr v s m c có trong Combo box. Thông thư ng ta ch n m c t Combo box. Tuy nhiên, ta cũng có th ch n m c b ng thông i p CB_SETCURSEL. SendMessage (hWnd, CB_SETCURSEL, (WPARAM) iIndex, 0). V i iIndex là v trí c n ch n, n u giá tr này b ng –1 thì Windows lo i b vi c ch n v i t t c các m c trong Combo box. Trang 83 i

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ Khi nh n thông i p WM_COMMAND t Combo box, chúng ta có th xác nh m c ư c ch n có ví trí th m y trong Combo box (v trí b t u là 0) b ng cách dùng thông i p CB_GETCURSEL. iIndex = SendMessage (hWnd, CB_GETCURSEL, 0, 0); iIndex là v trí c a m c ư c ch n. N u không có m c nào ư c ch n thì hàm trên s tr v mã l i CB_ERR (giá tr b ng –1). xác nh chi u dài iLength c a m t chu i có trong Combo box, ta dùng thông i p CB_GETLBTEXTLEN. iLength=SendMessage (hwnd, CB_GETLBTEXTLEN, iIndex, 0); Hàm tr v chi u dài chu i v i iIndex là ví trí c a chu i c n l y chi u dài. N u mu n l y n i dung c a m c nào ó, ta s d ng thông i p CB_GETLBTEXT. SendMessage ( hWnd, CB_GETLBTEXT, iIndex, (LPARAM)szString); iIndex là v trí chu i c n l y, szString dùng ch a chu i l y ư c.

3.7.4. M t ng d ng Combo box
minh h a cách cách s d ng Combo box cùng v i các th t c x lý thông i p trong Combo box chúng ta cùng nhau kh o sát ví d sau (ví d 3.3). K t qu th c hi n chương trình.

Hình 3.3

ng d ng minh h a l p Combo Box

*COMBOBOX.CPP ( trích d n)

Trang 84

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
void FillCombo (HWND hwndCombo) { int i; static TCHAR *tc[ ] = {TEXT("MAI XUAN HUNG"), TEXT("LE HOAN VU"), TEXT("LE LU NHA"), TEXT("PHAM THANH PHONG"), TEXT("LE LUC"), TEXT("NGUYEN TIEN"), TEXT("DINH QUYEN")}; for(i=0; i<7; i++) SendMessage(hwndCombo,CB_ADDSTRING,0,(LPARAM)tc[i]); } LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static HWND hwndCombo, hwndText ; int iIndex, iLength, cxChar, cyChar ; TCHAR *pVarName; switch (message) { case WM_CREATE : cxChar = LOWORD (GetDialogBaseUnits ()) ; cyChar = HIWORD (GetDialogBaseUnits ()) ; hwndCombo = CreateWindow (TEXT ("combobox"), NULL, WS_CHILD | WS_VISIBLE | LBS_STANDARD, cxChar, cyChar * 3, cxChar * 20 + GetSystemMetrics (SM_CXVSCROLL), cyChar * 10, hwnd, (HMENU)ID_COMBO, (HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE), NULL) ; hwndText = CreateWindow (TEXT ("static"), NULL, WS_CHILD | WS_VISIBLE | SS_LEFT, cxChar, cyChar, GetSystemMetrics (SM_CXSCREEN), cyChar, hwnd, (HMENU) ID_TEXT, (HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE), NULL) ; FillListBox (hwndCombo) ; return 0 ; case WM_SETFOCUS :

Trang 85

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
SetFocus (hwndCombo) ; return 0 ; case WM_COMMAND : if (LOWORD(wParam) == ID_COMBO && HIWORD(wParam) == LBN_SELCHANGE) { iIndex=SendMessage(hwndCombo,CB_GETCURSEL,0,0); iLength=SendMessage(hwndCombo,CB_GETLBTEXTLEN,iIndex, 0)+1; pVarName =(char*) calloc (iLength, sizeof (TCHAR)) ; SendMessage(hwndCombo, CB_GETLBTEXT, iIndex, (LPARAM)pVarName) ; SetWindowText (hwndText, pVarName) ; free (pVarName) ; } return 0 ; case WM_DESTROY : PostQuitMessage (0) ; return 0 ; } return DefWindowProc (hwnd, message, wParam, lParam) ; }

3.8. L P SCROLL BAR
Trong các chương trư c thanh cu n c a s ư c t o ra b ng cách s d ng hai thông s WS_VSCROLL hay WS_HSCROLL, thanh cu n ư c t o ra trong trư ng h p này n m bên dư i ho c bên ph i vùng client. Bây gi t o l p m t control thanh cu n mà ki u i u khi n thanh cu n này xu t hi n b t c nơi nào trong vùng thao tác. B ng cách s d ng l p "scrollbar" cùng v i hai ki u thanh cu n nh nghĩa s n SBS_VERT và SBS_HORZ. Không gi ng như các ki u control i u ki n ã c p trên, các control thanh cu n ây không g i thông i p WM_COMMAND, mà l i g i thông i p WS_VSCROLL và WS_ Trang 86

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ HSCROLL cho c a s cha. Có th phân bi t ư c thanh cu n c a s và ki u i u khi n thanh cu n thông qua tham s lParam. Tham s này s b ng 0 n u như thanh cu n này là thanh cu n c a s , còn tham s này s b ng handle c a c a s thanh cu n n u như thanh cu n ó là m t ki u i u khi n. Còn tham s wPram thì gi ng nhau cho c hai lo i thanh cu n c a s và ki u i u khi n thanh cu n. B n có th t o m t ki u i u khi n thanh cu n v i chi u dài và chi u r ng tùy ý. N u b n mu n t o m t ki u i u khi n thanh cu n có kích thư c b ng kích thư c c a thanh cu n c a s . Thì dùng hai hàm sau l y ch u cao và chi u r ng c a thanh cu n c a s . GetsystemMetrics (SM_CYHCROLL) ; GetsystemMetrics (SM_CXVCROLL) ; Tương t như thanh cu n c a s chúng ta có th thanh cu n hàm. t vùng và v trí cho ki u i u khi n

SetScrollRange (hwndScroll, SB_CTL, iMin, iMax, bRedraw) ; hwnScroll là handle c a control thanh cu n. Tham s SB_CTL là m t trong hai ki u SBS_VERT tương ng v i thanh cu n ngang và SBS_HORZ tương ng v i thanh cu n ng. Theo m c nh thì thanh cu n n m trong vùng có giá tr t 0 n 100 ơn v chi u dài, tuy nhiên có th t l i vùng thanh cu n thông qua hai tham s iMin tương ng v i ch n dư i c a vùng và iMax tương ng v i ch n trên c a vùng. Tham s nRedraw mang m t trong hai giá tr TRUE ho c FALSE, n u mu n Windows v l i thanh cu n d a trên vùng m i thì ph i t giá tr này b ng TRUE, còn ngư c l i thì t giá tr này b ng FALSE. Dùng hàm sau t l i v trí con ch y trên thanh cu n.

SetScrollPos (hwndScroll, SB_CTL, iPos, bRedraw); V i iPos là v trí c n t con ch y trên vùng control thanh cu n.

3.8.1. Giao di n bàn phím

i v i thanh cu n

Có th dùng bàn phím di chuy n con ch y trên vùng control thanh cu n khi thanh cu n ó nh n ư c focus nh p. Sau ây là các phím di chuy n cùng v i các ch c năng c a nó trên control thanh cu n.
Các phím di chuy n Giá tr wParam c a thông i p thanh cu n

Home End

SB_TOP SB_BOTTOM

Trang 87

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam SB_PAGEUP SB_PAGEDOWN SB_LINEUP SB_LINEDOWN

____________________________________________________________________________________ Page Up Page Down Left hay Up Right hay Down

B ng 3.4 Các giá tr wParam c a thông i p thanh cu n

t focus nh p cho các thanh cu n b ng hàm. SetFocus (hwndScroll); V i hwnScroll là handle c a control thanh cu n. Mu n t focus cho m t thanh cu n nào ó khi kh i ng chương trình thì ph i t focus này khi x lý thông i p WM_SETFOCUS trong th t c WndProc. Vì lý do, thanh cu n ch quan tâm n các phím di chuy n, nó không quan tâm n phím Tab. i u này làm cho vi c s d ng phím Tab di chuy n focus nh p t thanh cu n này n thanh cu n khác g p nhi u khó khăn. Tuy nhiên gi i quy t v n này ta nguyên c u các k thu t sau. Nh n a ch th t c window c a các control thanh cu n b ng hàm GetWindowLong v i nh danh GWL_ID. B n có th t th t c Windows cho thanh cu n b ng hàm SetWindowLong v i nh danh GWL_WNDPROC. Trong ví d sau ây, hàm SetWindownLong t th t c window cho thanh cu n m i và tr v a ch th t c window thanh cu n c . hàm x lý thanh cu n ScrollProc trong ví d sau nh n t t c các thông i p g i n th t c window thanh cu n. Hàm này ch ơn gi n thay i focus nh p gi a các thanh cu n khi b m phím Tab hay Shift-Tab, b ng cách g i window thanh cu n c thông qua hàm CallWindowProc.

3.8.2. Tô màu các thanh cu n và các static text
Màu c a các thanh cu n ư c th c hi n b ng cách x lý các thông i p WM_CTLCOLORSCROLLBAR. Trong ví d sau hàm WinProc ta nh nghĩa m t m ng g m có 3 ph n t m i ph n t là m t handle ch i tô (brush) cho m t thanh cu n.
static HBRUSH hBrush[3];

Các ch i tô trên ư c t o ra b ng hàm CreateSolidBrush trong th t c x lý thông i p WM_CREATE . Trang 88

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
for (i = 0; i < 3; i++) { hBrush [i] = CreateSolidBrush (color [i]); }

Trong ó color ch a các giá tr màu sơ c p RGB (Red, Green, Blue). M t trong 3 ch i tô (brush) ư c tr v khi x lý thông i p WM_CTLCOLORCROLLBAR trong th t c WinProc b ng o n chương trình sau.
case WM_CTLCOLORCROLLBAR: i = GetWindowLong (HWND) lParam, GWL_ID) : return (LRESULT) hBrush [i];

Chú ý : Các ch i tô ph i ư c h y b trư c khi k t thúc chương trình thông qua hàm DeleteOject khi x lý thông i p WM_DESTROY trong th t c x lý WinProc.
for (i = 0; i < 3; i++) DeleteObject (hBrush [i]);

Các static text ư c tô màu tương t như các thanh cu n, b ng cách x lý thông i p WM_CTLCOLORSTATIC trong th t c WinProc thông qua hàm SetTextColor. Dùng hàm SetBkColor t màu n n ch , trong ví d sau thì màu n n ch trùng v i màu h th ng COLOR_BTNHIGHLIGHT. i v i các Static text tĩnh ta ch áp d ng màu n n ch cho hình ch nh t n m sau m i ký t ch không ph i toàn b chi u r ng c a c a s control. th c hi n i u này, trong th t c WndProc hàm x lý WM_CTLCOLORSTATIC ph i tr v m t handle cho m t ch i tô (brush) c a màu COLOR_BTNHIGHLIGHT. Các ch i tô này ư c t o ra khi x lý thông i p WM_CREATE và ph i ư c h y khi x lý thông i p WM_DESTROY.

3.8.3. Tô màu n n c a s
Trong ví d dư i ây ã t o ra c a s và m t ch i tô màu en cho vùng thao tác cho c a s này. Wndclass.hbrBackground = CreateSolidBrush (0) ; Khi thay i vi c ch n trên các thanh cu n thì chương trình t o ra m t ch i tô (brush) m i và chèn handle c a ch i tô m i này vào c a s trên. Nh n hay t handle c a ch i tô (brush) b ng hàm GetClassWord và hàm SetClassWord. Có th t o m t ch i tô (brush) m i và chèn handle c a ch i tô này vào c u trúc c a c a s , sau ó xóa ch i tô (brush) cũ. Trang 89

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ DeleteObject ( (HBRUSH)SetClassLong( hwnd, GCL_HBRBACKGROUND, (LONG)CreateSolidBrush(RGB (icolor[0], icolor[1], icolor[2])))) ; Windows s dùng ch i tô m i này tô vùng thao tác cho l n tô k ti p. Dùng hàm sau xóa 2/3 bên ph i c a vùng thao tác trư c khi v l i vùng này. InvalidateRect (hwnd, &icolor, TRUE) ; Hàm InvalidateRect làm cho window t thông i p WM_PAINT vào trong h ng i các thông i p c a th t c x lý window. Mà thông i p WM_PAINT có ưu tiên th p hơn các thông i p x lý bàn phím hay chu t nên nó ư c x lý sau. N u mu n vùng c a s ư c c p nh t l i màu ngay sau khi di chuy n con ch y trên thanh cu n thì dùng hàm. UpdateWindow (hwnd) ; Tuy nhiên n u chúng ta dùng hàm này thì làm cho t c phím ch m l i. x lý thông i p chu t và bàn

Hàm WndProc không x lý thông i p WM_PAINT mà ưa cho hàm DefWindowProc. Như chúng ta bi t windows x lý m c nh thông i p WM_PAINT ch ơn gi n là l i g i hàm BeginPaint và EndPaint. Nhưng trên chúng ta ch nh InvalidateRect là ph n n n c n ph i xóa, chính i u này hàm BeginPaint s khi n cho Windows t ng phát sinh thông i p xóa n n WM_ERASEBKGND. Chú ý : ph i d n d p các ch i tô trư c khi chương trình k t thúc b ng hàm DeleteOject trong khi x lý thông i p WM_DESTROY.

Hình 3.4

ng d ng minh h a l p Scroll Bar

3.8.4. M t ng d ng c a thanh cu n

Trang 90

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ Hình 3.4 minh h a m t ng d ng v thanh cu n (Scroll Bar). Trong ví d này, ta s d ng 3 thanh cu n và 6 static text. B ng cách dùng chu t hay bàn phím, ta di chuy n con trư t trên thanh cu n thay i giá tr màu. Màu thay i tương ng s là màu tô c a vùng client bên c nh. Ba stactic text dư i m i thanh cu n dùng ghi nh n giá tr màu thay i tương ng v i các thanh cu n. *SCROLLBAR.CPP (trích d n)
int idFocus ; WNDPROC OldScroll[3] ; LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static COLORREF crPrim[3] = { RGB (255, 0, 0), RGB (0, 255, 0), RGB (0, 0, 255) }; static HBRUSH hBrush[3], hBrushStatic; static HWND hwndScroll[3], hwndLabel[3], hwndValue[3], hwndRect; static int color[3], cyChar ; static RECT rcColor ; static TCHAR *szColorLabel[] = { TEXT("Red"), TEXT("Green"), TEXT("Blue") } ; HINSTANCE hInstance ; int i, cxClient, cyClient ; TCHAR szBuffer[10] ; switch (message) { case WM_CREATE : hInstance = (HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE) ; hwndRect = CreateWindow (TEXT("static"), NULL, WS_CHILD | WS_VISIBLE | SS_WHITERECT, 0, 0, 0, 0, hwnd, (HMENU) 9, hInstance, NULL) ;

Trang 91

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
for (i = 0 ; i < 3 ; i++) { hwndScroll[i] = CreateWindow (TEXT ("scrollbar"), NULL, WS_CHILD | WS_VISIBLE | WS_TABSTOP | SBS_VERT, 0, 0, 0, 0, hwnd, (HMENU) i, hInstance, NULL) ; SetScrollRange(hwndScroll[i], SB_CTL, 0, 255, FALSE); SetScrollPos (hwndScroll[i], SB_CTL, 0, FALSE) ; hwndLabel[i] = CreateWindow ( TEXT("static"), szColorLabel[i], WS_CHILD|WS_VISIBLE|SS_CENTER, 0, 0, 0, 0, hwnd, (HMENU) (i + 3), hInstance, NULL) ; hwndValue [i] = CreateWindow (TEXT ("static"), TEXT ("0"), WS_CHILD | WS_VISIBLE | SS_CENTER, 0, 0, 0, 0, hwnd, (HMENU) (i + 6), hInstance, NULL) ; OldScroll[i] = (WNDPROC) SetWindowLong ( hwndScroll[i], GWL_WNDPROC, (LONG) ScrollProc) ; hBrush[i] = CreateSolidBrush (crPrim[i]) ; } hBrushStatic = CreateSolidBrush ( GetSysColor (COLOR_BTNHIGHLIGHT)) ; cyChar = HIWORD (GetDialogBaseUnits ()) ; return 0 ; case WM_SIZE : cxClient = LOWORD (lParam) ; cyClient = HIWORD (lParam) ; SetRect (&rcColor, 0, 0, cxClient/1.5, cyClient) ; MoveWindow (hwndRect, cxClient/1.5, 0, cxClient/2, cyClient, TRUE) ; for (i = 0 ; i < 3 ; i++) { MoveWindow (hwndScroll[i], ((int)(1.2 * i + 1) * cxClient) / 13 + (int)cxClient/1.5, 2*cyChar, cxClient / 17, cyClient - 4 * cyChar, TRUE) ; MoveWindow (hwndLabel[i], (2.3 * i + 1) * cxClient / 28+ cxClient/1.5, cyChar / 2, cxClient / 8, cyChar, TRUE) ;

Trang 92

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
MoveWindow (hwndValue[i], (2.3 * i + 1) * cxClient / 28+ cxClient/1.5, cyClient - 3 * cyChar / 2, cxClient / 8, cyChar, TRUE) ; } SetFocus (hwnd) ; return 0 ; case WM_SETFOCUS : SetFocus (hwndScroll[idFocus]) ; return 0 ; case WM_VSCROLL : i = GetWindowLong ((HWND) lParam, GWL_ID) ; switch (LOWORD (wParam)) { case SB_PAGEDOWN : color[i] += 15 ; case SB_LINEDOWN : color[i] = min (255, color[i] + 1) ; break; case SB_PAGEUP : color[i] -= 15 ; case SB_LINEUP : color[i] = max (0, color[i] - 1) ; break; case SB_TOP : color[i] = 0 ; break ;

Trang 93

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
case SB_BOTTOM : color[i] = 255 ; break ; case SB_THUMBPOSITION : case SB_THUMBTRACK : color[i] = HIWORD (wParam) ; break ; default : break ; } SetScrollPos (hwndScroll[i], SB_CTL, color[i], TRUE) ; wsprintf (szBuffer, TEXT ("%i"), color[i]) ; SetWindowText (hwndValue[i], szBuffer) ; DeleteObject ( (HBRUSH)SetClassLong( hwnd, GCL_HBRBACKGROUND, (LONG)CreateSolidBrush ( RGB( color[0], color[1], color[2] ) ) ) ) ; InvalidateRect (hwnd, &rcColor, TRUE) ; return 0 ; case WM_CTLCOLORSCROLLBAR : i = GetWindowLong ((HWND) lParam, GWL_ID) ; return (LRESULT) hBrush[i] ; case WM_CTLCOLORSTATIC : i = GetWindowLong ((HWND) lParam, GWL_ID) ; if (i >= 3 && i <= 8) { SetTextColor ((HDC) wParam, crPrim[i % 3]) ;

Trang 94

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
SetBkColor ( (HDC) wParam, GetSysColor ( COLOR_BTNHIGHLIGHT ) ); return (LRESULT) hBrushStatic ; } break ; case WM_SYSCOLORCHANGE : DeleteObject (hBrushStatic) ; hBrushStatic = CreateSolidBrush ( GetSysColor (COLOR_BTNHIGHLIGHT)) ; return 0 ; case WM_DESTROY : DeleteObject ((HBRUSH) SetClassLong (hwnd, GCL_HBRBACKGROUND, (LONG) GetStockObject (WHITE_BRUSH))) ; for (i = 0 ; i < 3 ; i++) DeleteObject (hBrush[i]) ; DeleteObject (hBrushStatic) ; PostQuitMessage (0) ; return 0 ; } return DefWindowProc (hwnd, message, wParam, lParam) ; } LRESULT CALLBACK ScrollProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { int id = GetWindowLong (hwnd, GWL_ID) ; switch (message) { case WM_KEYDOWN :

Trang 95

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
if (wParam == VK_TAB) SetFocus (GetDlgItem (GetParent (hwnd), (id + (GetKeyState (VK_SHIFT) < 0 ? 2 : 1)) % 3)) ; break ; case WM_SETFOCUS : idFocus = id ; break ; } return CallWindowProc(OldScroll[id],hwnd,message,wParam,lParam); }

Trang 96

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________

Chương 4 X LÝ BÀN PHÍM, THI T B CHU T, VÀ B TH I GIAN
4.1. M U

NH

Các chương trư c ã trình bày các thành ph n i u khi n chung và h p tho i. Trong các thành ph n này, vi c giao ti p v i ngư i dùng ã ư c các h p tho i hay các i u khi n x lý, thư ng không c n quan tâm l m vi c giao ti p v i các thi t b ó. Tuy nhiên, l p trình trên Windows cũng c n ph i hi u vi c x lý các thi t b nh p như bàn phím và thi t b chu t. M t s ng d ng như h a hay thao tác văn b n ít nhi u cũng ph i vi t các x lý liên quan t i bàn phím và thi t b chu t. Trong chương này, hai ph n u s trình bày cách ngư i l p trình s d ng bàn phím và thi t b chu t xây d ng m t ng d ng trên Windows. Th c ch t c a vi c x lý bàn phím hay thi t b chu t cũng ơn gi n, vì v i cơ ch thông i p c a Windows thì ta ch c n tìm hi u các thông i p ư c phát sinh t bàn phím hay t thi t b chu t vi t các x lý tương ng v i t ng thi t b . Ph n cu i c a chương trình bày m t thành ph n cũng không kém quan tr ng là b nh th i gian. Windows cung c p cơ ch này truy n thông v i ng d ng theo nh kì. V i cơ ch này, ng d ng ch c n khai báo m t b nh th i gian v i m t kho ng th i gian cho trư c. Và khi ng d ng ho t ng thì h th ng s truy n m t tín hi u cho ng d ng theo t ng kho ng th i gian nh kì ã ư c khai báo. Tóm l i vi c tìm hi u bàn phím, thi t b chu t, và b nh th i gian s em l i s hi u bi t sâu s c v thành ph n nh p li u căn b n c a m t ng d ng trên Windows.

4.2. BÀN PHÍM
Trong môi trư ng tương tác ho ngày nay có hai thành ph n nh p li u không th thi u là bàn phím (keyboard) và thi t b chu t (mouse). Tuy m t s ng d ng không ti n l i khi dùng bàn phím, như các chương trình trò chơi (game), hay các mô ph ng h a v i thi t b nh v là thi t b chu t ch ng h n, nhưng bàn phím v n là thi t b không th thay th c a m t máy tính. Bàn phím h tr nh p li u r t phong phú : m t chương trình so n th o văn b n thì không th thi u vi c nh p d li u t bàn phím. N u máy tính b hư thi t b chu t b ta v n có th th c thi các tác v c a ng d ng m t cách bình thư ng. Trong ph n này chúng ta s tìm hi u các thông i p ư c phát sinh t bàn phím và cách can thi p x lý chúng.

4.2.1. N n t ng cơ s v bàn phím
Trang 97

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ Windows nh n và x lý thông tin nh n ư c t bàn phím, qua hình th c các thông i p và g i cho ng d ng. Trong ng d ng Windows các thông i p s ư c h i u hành chuy n cho hàm x lý c a s WndProc c a ng d ng. Windows cung c p 8 lo i thông i p khác nhau phân bi t các tình hu ng c a các phím ư c gõ. Tuy nhiên không ph i lúc nào chúng ta cũng ph i x lý toàn b các thông i p ó, thông thư ng thì ch c n x lý m t n a các thông i p ư c phát sinh t bàn phím, và các thông i p còn l i s ư c Windows x lý m c nh. Ví d , trong Windows có th b qua khi nh n phím Ctrl, Alt, Shift cùng v i các phím khác, n u không mu n ch n x lý riêng cho ng d ng. Trong trư ng h p n u chúng ta mu n ch n x lý riêng cho mình, ch ng h n t o phím nóng (hotkey) ph i chú ý tránh dùng trùng h p v i các phím nóng mà Windows cung c p. Vì khi ó theo quy n ưu tiên, ng d ng c a chúng ta s x lý thông i p ó và s làm cho h th ng không ho t ng như bình thư ng. Thành ph n giao ti p chung như h p tho i (dialog) cũng có nhi u giao ti p v i bàn phím, nhưng chúng ta không c n quan tâm n vi c giao ti p v i bàn phím khi h p tho i ư c kích ho t. X lý bàn phím trong h p tho i thư ng ư c giao cho Windows x lý. Các i u khi n ư c dùng trong h p tho i như h p nh p li u (edit box), h p l a ch n (check box), hay các nút nh n (button)... i u có kh năng t x lý phím gõ vào và ch tr l i thông báo c a các phím gõ cho c a s cha (parent window). Tuy v y, v i m t s các i u khi n nh t nh theo ng d ng ta có th ph i x lý các thông i p tăng cư ng thêm s c m nh c a thành ph n i u khi n này. Tóm l i trong các ng d ng ư c c u thành t các thành ph n i u khi n cơ b n này thì chúng ta không quan tâm n vi c x lý các thông i p t bàn phím.

4.2.2. Khái ni m focus trong các ng d ng trong môi trư ng Windows
Windows ưa ra khái ni m s quan tâm (focus) cho các ng d ng ư c ch y ng th i trong m t th i i m. Vì ch có m t bàn phím, nên Windows ph i qu n lý và phân ph i các thông i p ư c gõ vào cho các ng d ng. Thông thư ng, có các trư ng h p trên Windows là : m t trong s các ng d ng ang ch y ư c kích ho t (active) hay không có ng d ng nào ch y. Khi có m t chương trình ng d ng ư c kích ho t thì Windows xem như ng d ng ó nh n ư c s quan tâm.Trong m t ng d ng có nhi u các c a s , m i th i i m ch m t c a s nh n ư c s quan tâm. Theo cơ ch này, Windows cung c p m t d ng g i là hàng i thông i p. M i thông i p s ư c ưa vào hàng i x lý thông i p và ư c Windows phân ph i n các ng d ng tương ng. Hàm DispatchMessage trong vòng l p x lý thông i p s ch u trách nhi m chuy n thông i p n th t c x lý c a s WndProc c a các c a s tương ng. M t c a s có th xác nh ư c tr ng thái quan tâm c a mình b ng cách ch n các thông i p WM_SETFOCUS, WM_KILLFOCUS trong hàm x lý WndProc. Thông i p WM_SETFOCUS s cho c a s bi t ư c th i i m nh n ư c quan tâm c a Windows và

Trang 98

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ ngư c l i WM_KILLFOCUS s thông báo cho c a s bi t ư c ã m t s quan tâm t Windows. Ph n sau s gi i thi u k hơn v x lý thông i p.

4.2.3. Cơ ch hàng

i và qu n lý hàng

i

Trong Windows khi ngư i dùng nh n và nh phím trên bàn phím, thì thông qua trình i u khi n thi t b bàn phím (keyboard driver) s di n d ch mã quét (scan code) c a ph n c ng sang hình th c thông i p. Trư c h t Windows s t m th i lưu tr thông i p này vào hàng i thông i p c a h th ng (system message queue). Hàng i thông i p h th ng c a Windows là m t hàng i duy nh t và qu n lý các thao tác ti n x lý thông tin nh p t bàn phím và chu t. Windows s l n lư t l y các thông i p trong hàng i x lý và s g i n hàng i c a ng d ng khi ng d ng ã x lý xong thông i p bàn phím và thi t b chu t trư c ó.

Hình 4.1 Quá trình x lý bàn phím

Lý do mà Windows ph i chia thành hai giai o n trong quá trình nh n và g i thông i p t bàn phím n hàng i c a ng d ng là do vi c ng b hóa v i m i ti n trình. N u Windows không qu n lý hàng i h th ng thì r t khó ng b các ti n trình c a các ng d ng. Ví d , khi m t c a s nh n ư c s quan tâm và chu n b x lý các thông i p. Ngư i dùng có th gõ phím nhanh trong khi thông i p trư c v n chưa x lý xong. Gi s ngư i dùng mu n chuy n qua ng d ng khác và nh n Alt-Tab, khi ó thông i p bàn phím m i này s ư c ưa vào hàng i c a h th ng và phân phát cho ng d ng kia ch không ph i ưa vào hàng i c a ng d ng. V i tính năng ng b hóa c a Windows thì các thông i p t bàn phím m b o ư c chuy n giao úng cho các c a s tương ng.

4.2.4. X lý thông i p t bàn phím
4.2.4.1. Thông i p t thao tác nh n và nh c a m t phím Thao tác căn b n c a nh p li u t bàn phím là thao tác nh n và nh m t phím. Khi thao tác nh n m t phím trên bàn phím ư c th c hi n thì Windows s phát sinh thông i p WM_KEYDOWN hay WM_SYSKEYDOWN và ưa vào hàng i thông i p c a ng d ng hay c a s nh n ư c s quan tâm (focus). Cũng tương t , khi ta nh phím thì thông i p WM_KEYUP hay WM_SYSKEYUP s ư c h i u hành phân phát t i hàng i ó. Khi th c hi n thao tác nh p t bàn phím thì vi c nh n (down) và nh (up) ph i i ôi v i nhau. Tuy nhiên, n u chúng ta nh n m t phím và gi luôn thì Windows s phát sinh hàng lo t các thông i p WM_KEYDOWN hay WM_SYSKEYDOWN, nhưng v i thao tác nh thì ch phát sinh m t thông i p WM_KEYUP hay WM_SYSKEYUP. Các thông i p này s ư c g i tu n t n các hàm WndProc c a các c s nh n ư c s quan tâm c a Windows. Ngoài ra chúng ta có th bi t ư c th i i m mà thông i p phím ư c gõ vào lúc nào b ng cách dùng hàm GetMessageTime.

Trang 99

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ Như chúng ta ã th y trong dòng trên m t thao tác nh n hay th thì có hai d ng thông i p khác nhau như WM_KEYDOWN và WM_SYSKEYDOWN c a thao tác nh n, và tương t i v i thao tác nh . Thông i p có ti p u ng là "SYS" thư ng ư c phát sinh khi ngư i dùng nh n các phím gõ h th ng. Khi ngư i dùng nh n phím Alt k t h p v i phím khác thì thư ng phát sinh thông i p WM_SYSKEYDOWN và WM_SYSKEYUP. i v i t h p các phím Alt, ch c năng thư ng là g i m t m c ch n trên trình ơn menu c a ng d ng hay trình ơn h th ng system menu và ngoài ra dùng chuy n i các tác v gi a nhi u ng d ng khác nhau (phím Alt+Tab hay Alt+Esc), và óng c a s ng d ng khi k t h p v i phím ch c năng F4. Khi xây d ng m t chương trình ng d ng, thư ng ít quan tâm n các thông i p WM_SYSKEYDOWN và thông i p WM_SYSKEYUP. Chúng ta ch c n dùng hàm DefWindowProc cu i m i hàm WndProc c a c a s nh n thông i p. Windows s ch u trách nhi m x lý các thông i p d ng h th ng này, n u có nh ng tác v c bi t thì chúng ta có th ch n các thông i p này x lý. Tuy nhiên ta không nên làm như v y vì khi ó chương trình c a chúng ta s ch y không bình thư ng như các ng d ng khác. Không ph i chúng ta giao phó hoàn toàn cho Windows x lý các thông i p h th ng c a ng d ng, mà Windows s x lý các thông i p h th ng này và ưa ra các thông i p bình thư ng khác n ng d ng. Ví d khi nh n phím Alt+Tab thì Windows s t o m t thông i p h th ng g i vào hàng i c a ng d ng và khi không x lý thông i p này thì theo m c nh hàm DefWindowProc s x lý và tr v thông i p WM_KILLFOCUS cho ng d ng, khi ó ng d ng c a chúng ta s d dàng x lý hơn. Tóm l i thông i p WM_KEYDOWN và WM_KEYUP thư ng ư c sinh ra b i các phím nh n thông thư ng không k t h p v i phím Alt. N u chương trình c a chúng ta b qua không x lý các thông i p này thì Windows cũng không t o ra các thông i p hay x lý gì c bi t. 4.2.4.2. Các thông i p phát sinh t bàn phím Sau ây là b ng mô t các thông i p phát sinh t bàn phím (theo th t Alphabet). Thông i p WM_ACTIVATE Nguyên nhân phát sinh Thông i p này cùng ư c g i n các c a s b kích ho t và c a s không b kích ho t. N u các c a s này cùng m t hàng i nh p li u, các thông i p này s ư c truy n m t cách ng b , u tiên th t c Windows c a c a s trên cùng b m t kích ho t, sau ó n th t c c a c a s trên cùng ư c kích ho t. N u các c a s này không n m trong cùng m t hàng i thì thông i p s ư c g i m t cách không ng b , do ó c a s s ư c kích ho t ngay l p t c. Thông báo n c a s r ng ngư i dùng ã t o m t s

WM_APPCOMMAND

Trang 100

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ ki n l nh ng d ng, ví d khi ngư i dùng kích vào button s d ng chu t hay ánh vào m t kí t kích ho t m t l nh c a ng d ng. WM_CHAR Thông i p này ư c g i t i c a s có s quan tâm khi thông i p WM_KEYDOWN ã ư c d ch t hàm TranslateMessage. Thông i p WM_CHAR có ch a mã kí t c a phím ư c nh n. Thông i p này ư c g i t i c a s có s quan tâm khi thông i p WM_KEYUP ã ư c x lý t hàm TranslateMessage. Thông i p này xác nh n mã kí t khi m t phím dead key ư c nh n. Phím dead key là phím k t h p t o ra kí t ngôn ng không có trong ti ng anh (xu t hi n trong bàn phím h tr ngôn ng khác ti ng Anh). ng d ng g i thông i p này xác nh m t phím nóng liên quan n m t c a s . g i thông i p này thì dùng hàm SendMessage. Thông i p này ư c g i khi ngư i dùng nh n m t phím nóng ư c ăng kí trong RegisterHotKey. Thông i p này ư c g i cho c a s nh n ư c s quan tâm khi ngư i dùng nh n m t phím trên bàn phím. Phím này không ph i phím h th ng (Phím không có nh n phím Alt). Thông i p này ư c g i cho c a s nh n ư c s quan tâm khi ngư i dùng nh m t phím ã ư c nh n trư c ó.Phím này không ph i phím h th ng (Phím không có nh n phím Alt). Thông i p này ư c g i t i c a s quan tâm trư c khi nó m t quy n này. ang nh n ư c s

WM_DEADCHAR

WM_GETHOTKEY

WM_HOTKEY WM_KEYDOWN

WM_KEYUP WM_KILLFOCUS WM_SETFOCUS WM_SETHOTKEY

Thông i p này ư c g i t i c a s sau khi c a s nh n ư c s quan tâm c a Windows ng d ng s g i thông i p này n c a s liên quan n phím nóng, khi ngư i dùng nh n m t phím nóng thì c a s tương ng liên quan t i phím nóng này s ư c kích ho t. Thông i p này s ư c g i t i c a s nh n ư c s quan tâm khi hàm TranslateMesage x lý xong thông i p WM_SYSKEYDOWN. Thông i p WM_SYSCHAR ch a mã c a phím h th ng. Phím h th ng là phím có ch a phím Alt và

WM_SYSCHAR

Trang 101

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ t h p phím khác. WM_SYSDEADCHAR Thông i p này ư c g i t i c a s nh n ư c s quan tâm khi m t thông i p WM_SYSKEYDOWN ư c biên d ch trong hàm TranslateMessage. Thông i p này xác nh n mã kí t c a phím h th ng deadkey ư c nh n. Thông i p này ư c g i t i c a s nh n ư c s quan tâm khi ngư i dùng nh n phím F10 hay nh n Alt trư c khi nh n phím khác. Thông i p này cũng ư c g i khi không có c a s nào nh n ư c s quan tâm và lúc này thì c a s nh n ư c là c a s ang ư c kích ho t (Active). Thông i p này ư c g i t i c a s nh n ư c s quan tâm khi ngư i dùng nh n m t phím mà trư c ó ã gi phím Alt. Cũng tương t n u không có c a s nào nh n ư c s quan tâm thì thông i p này s ư c g i cho c a s ang ư c kích ho t.
B ng 4.1 Mô t thông i p phát sinh t bàn phím

WM_SYSKEYDOWN

WM_SYSKEYUP

4.2.4.3 Mã phím o (Virtual key code) Windows cung c p khái ni m phím o nh m tách r i v i thi t b bàn phím hay nói cách khác là ti n t i c l p thi t b v i bàn phím. Khi m t phím ư c nh n thì ph n c ng v t lý phát sinh ra m t mã quét (scan code), trên bàn phím tương thích IBM các phím ư c gán v i các mã ví d phím W là 17, phím E là 18, và phím R là 19... Cách s p x p này thu n túy d a trên v trí v t lý c a phím trên bàn phím. Nh ng ngư i xây d ng nên Windows nh n th y r ng n u dùng tr c ti p mã quét thì s không thích h p khi b l thu c vào bàn phím hi n t i và tương lai. Do ó h c x lý bàn phím b ng cách c l p thi t b hơn, b ng cách t o ra m t b ng nh nghĩa t p giá tr phím t ng quát mà sau này ư c g i là mã phím o. M t s giá tr bàn phím o mà ta không th y xu t hi n trên bàn phím IBM tương thích nhưng có th tìm th y chúng trong bàn phím c a các nhà s n xu t khác hay chúng ư c dành cho bàn phím trong tương lai. Các giá tr c a phím o này ư c nh nghĩa trong t p tin tiêu WINUSER.H và ư c b t u v i các ti p u ng VK_xxxxx. sau ây là b ng mô t các phím o thông d ng trong Windows giao ti p v i bàn phím IBM tương thích.
Th p phân Th p l c phân H ng phím nh nghĩa trong WINUSER.H Windows dùng Bàn phím IBM tương thích

1 2

01 02

VK_LBUTTON VK_RBUTTON

Nút chu t trái Nút chu t ph i

Trang 102

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam X Ctrl –Break Nút chu t gi a

____________________________________________________________________________________ 3 4 03 04 VK_CANCEL VK_MBUTTON
B ng 4.2 Mô t các phím o

Các thông i p trên ch ư c nh n khi dùng chu t, ta không bao gi nh n ư c thông i p trên n u gõ t bàn phím. Không nên dùng phím Ctrl–Break trong ng d ng Windows, phím này thư ng ư c ng t các ng d ng trong DOS. Nh ng giá tr phím o ti p sai dành cho các phím Backspace, Tab, Enter, Escape, và Spacebar ư c dùng nhi u trong chương trình Windows.

Th p phân

Th p l c phân

H ng phím nh nghĩa trong WINUSER.H

Windows dùng

Bàn phím IBM tương thích

8 9 12 13 16 17 18 19 20 27 32

08 09 0C 0D 10 11 12 13 14 1B 20

VK_BACK VK_TAB VK_CLEAR VK_RETURN VK_SHIFT VK_CONTROL VK_MENU VK_PAUSE VK_CAPITAL VK_ESCAPE VK_SPACE

X X X X X X X X X X X

Backspace Tab Phím s 5 trong NumPad v i n Numlock t t. Enter (cho hai phím) Shift (cho hai phím) Ctrl (cho hai phím) Alt (cho hai phím) Pause Caps Lock Esc Spacebar

B ng 4.3 Mô t các phím o

B ng mô t phím o ti p sau ây là các phím thư ng ư c s d ng nhi u trong Windows.

Trang 103

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam
Windows dùng Bàn phím IBM tương thích

____________________________________________________________________________________
Th p phân Th p l c phân H ng phím nh nghĩa trong WINUSER.H

33 34 35 36 37 38 39 40 41 42 43 44 45 46 47

21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F

VK_PRIOR VK_NEXT VK_END VK_HOME VK_LEFT VK_UP VK_RIGHT VK_DOWN VK_SELECT VK_PRINT VK_EXECUTE VK_SNAPHOT VK_INSERT VK_DELETE VK_HELP

X X X X X X X X

Page Up Page Down End Home Phím trái Phím mũi tên lên Phím ph i Phím xu ng Print Screen

X X

Insert Delete

B ng 4.4 Mô t các phím o (ti p theo)

M t s các phím o như VK_SELECT, VK_PRINT, VK_EXECUTE, hay VK_HELP thư ng ch xu t hi n trong các bàn phím gi l p mà chúng ta ít khi nhìn th y. Ti p sau là mã phím o c a các phím s và phím ch trên bàn phím chính. Trong bàn phím b sung phím Num Pad ư c qui nh riêng.
Th p phân Th p l c phân H ng phím nh nghĩa trong WINUSER.H Windows dùng Bàn phím IBM tương thích

48-57

30-39

Không

X

T phím 0 n phím 9 trên bàn phím chính

Trang 104

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam X T phím A n phím Z.

____________________________________________________________________________________ 65-90 41-5A Không

B ng 4.5 Mô t các phím ch và s trên bàn phím chính

Mã phím o trong b ng trên b ng v i mã ASCII c a kí t mà phím th hi n. Trong các ng d ng Windows thư ng không dùng mã phím o này mà thay vào ó ng d ng ch x lý thông i p kí t dành cho kí t có mã ASCII. Cu i cùng là mã phím o c a bàn phím m r ng Num Pad (bên ph i c a bàn phím) và các phím ch c năng (F1, F2, F3...).
Th p phân Th p l c phân H ng phím nh nghĩa trong WINUSER.H Windows dùng Bàn phím IBM tương thích

96-105 106 107 108 109 110 111 112121 122135 144 145

60-69 6A 6B 6C 6D 6E 6F 70-79 7A-87 90 91

VK_NUMPAD0 n VK_NUMPAD9 VK_MULTIPLY VK_ADD VK_SEPARATOR VK_SUBTRACT VK_DECIMAL VK_DIVIDE VK_F1 VK_F11 n VK_F10 n VK_F24 X

Phím 0 – 9 khi èn Num Lock ư c b t Phím * Phím +

Phím Phím . Phím / Phím F1 Phím F11 n F10 n F24

VK_NUMLOCK VK_SCROLL
B ng 4.6 Mô t các phím b sung

Num Lock Scroll Lock

M t s các phím o như F13- F24 thì ư c Windows t o ra phòng h cho các bàn phím sau này. Thư ng thì ng d ng Windows ch dùng phím F1 – F10 mà thôi. 4.2.4.4. Các tham s wParam và lPram trong thông i p phát sinh t bàn phím Trang 105

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ Trong thông i p phím gõ (WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, và WM_SYSKEYUP) thì tham s wParam s nh n giá tr mã phím o. Còn tham s lParam s ch a thông tin chi ti t v phím ư c gõ vào. B ng sau mô t các thông tin ch a trong 32 bit c a tham s lParam.
Bit nh n d ng N i dung

0-15

Ch a s l n c a phím ư c nh n xu ng. N u chúng ta ch nh n r i nh ra thì giá tr này b ng 1, n u chúng ta gi luôn phím thì s l p này s tăng theo. Ch a mã quét OEM (Original Equipment Manufacturer) ư c phát sinh t ph n c ng, ta h u như không quan tâm n thông tin này C này có giá tr 1 khi phím ư c nh n là phím thu c nhóm phím m r ng trên bàn phím IBM tương thích hay phím Alt, Ctrl bên ph i bàn phím ư c nh n. Windows ít quan tâm n giá tr c a c này Mã ng c nh c a phím (Context code), n u c này có giá tr b ng 1 thì phím Alt ư c nh n, i u này tương ng v i thông i p WM_SYSKEYDOWN hay WM_SYSKEYUP ư c phát sinh Tr ng thái c a phím trư c ó, trư ng này b ng 0 cho bi t phím trư c ó tr ng thái nh , và 1 n u phím trư c ó tr ng thái nh n. Tr ng thái d ch chuy n c a phím, c này b ng 0 n u phím ang ư c nh n, và b ng 1 n u phím ư c nh n.
B ng 4.7 Mô t thông tin ch a trong tham s lParam

16-23

24

29

30

31

4.2.5. o n chương trình minh h a o n chương trình dư i ây minh h a m t chương trình nh nh p các kí t t bàn phím và xu t ra màn hình.
#define BUFSIZE 65535; #define SHIFTED 0x8000;

Trang 106

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) { HDC hdc; // Thi t b ng c nh TEXTMETRIC tm; // C u trúc metric c a văn b n static DWORD dwCharX; // B ngang c a kí t static DWORD dwCharY; // Chi u dài c a kí t static DWORD dwClientX; // B ngang c a vùng làm vi c static DWORD dwClientY; // Chi u dài c a vùng làm vi c static DWORD dwLineLen; // Chi u dài c a m t dòng static DWORD dwLines; // S dòng văn b n trong vùng làm vi c static int nCaretPosX = 0; // T a static int nCaretPosY = 0; // T a x c a caret y c a caret

static int nCharWidth = 0; // B dày c a kí t static int cch = 0; // S kí t trong buffer static int nCurChar = 0; // Ch n kí t hi n th i trong buffer

static PTCHAR pchInputBuf; // Kí t t m ưa vào buffer int i, j; // Bi n l p int cCR = 0; // S kí t xu ng dòng int nCRIndex = 0; // Ch n kí t xu ng dòng cu i cùng

int nVirtKey; // Mã phím o TCHAR szBuf [128]; // Buffer t m TCHAR ch; // Kí t PAINTSTRUCT ps; // Dùng cho hàm BeginPaint RECT rc; // Hình ch nh t trong hàm DrawText

Trang 107

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
SIZE sz; // Kích thư c c a chu i COLORREF crPrevText; // Màu c a văn b n COLORREF crPrevBk; // Màu n n switch ( message ) { case WM_CREATE: /* L y thông tin font hi n th i */ hdc = GetDC ( hWnd ); GetTextMetrics ( hdc, &tm ); ReleaseDC ( hWnd, hdc ); dwCharX = tm.tmAveCharWidth; dwCharY = tm.tmHeight; /* C p phát b nh m lưu kí t nh p vào */

pchInputBuf = (LPTSTR)GlobalAlloc( GPTR,BUFSIZE * sizeof ( TCHAR ) ); return 0; case WM_SIZE: /* Lưu gi kích thư c c a vùng làm vi c */ dwClientX = LOWORD ( lParam ); dwClientY = HIWORD ( lParam ); /* Tính kích thư c t i a c a m t dòng và s dòng t i a trong vùng làm vi c */ dwLineLen = dwClientX - dwCharX; dwLines = dwClientY / dwCharY; break; case WM_SETFOCUS:

Trang 108

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
/* T o và hi n th caret khi c a s nh n ư c s quan tâm */ CreateCaret ( hWnd, ( HBITMAP ) 1, 0, dwCharY ); SetCaretPos ( nCaretPosX, nCaretPosY * dwCharY ); ShowCaret ( hWnd ); break; case WM_KILLFOCUS: /* n caret và h y khi c a s không còn nh n ư c s quan tâm */ HideCaret ( hWnd ); DestroyCaret ( ); break; case WM_CHAR: switch ( wParam ) { case 0x08: // Backspace case 0x0A: // Linefeed case 0x1B: // Escape MessageBeep( ( UINT ) –1 ); return 0; case 0x09: // tab /* Chuy n phím tab thành 4 kí t tr ng liên t c nhau */ for ( i = 0; i < 4; i ++ ) SendMessage (hWnd, WM_CHAR, 0x20, 0); return 0; case 0x0D: // Xu ng dòng /* Lưu kí t xu ng dòng và t o dòng m i ưa caret

Trang 109

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
xu ng v trí m i */ pchInputBuf [ cch++ ] = 0x0D; nCaretPosX = 0; nCaretPosY += 1; break; default: // X lý nh ng kí t có th hi n th ch = ( TCHAR ) wParam; HideCaret ( hWnd ); /* L y b dày c a kí t và xu t ra */ hdc = GetDC ( hWnd ); GetCharWidth32 ( hdc, (UINT) wParam, (UINT)wParam, &nCharWidth ); TextOut(hdc, nCaretPosX, nCaretPosY*dwCharY, &ch, 1); ReleaseDC ( hWnd, hdc ); /* Lưu kí t vào buffer */ pchInputBuf [ cch++ ] = ch; /* Tính l i v trí ngang c a caret. N u v trí này t i cu i dòng thì chèn thêm kí t xu ng dòng và di chuy n n dòng m i */ nCaretPosX += nCharWidth; if ( ( DWORD ) nCaretPosX > dwLineLen ) { nCaretPosX = 0; pchInputBuf [ cch++ ] = 0x0D; ++nCaretPosY; } ư c

caret

Trang 110

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
nCurChar = cch; ShowCaret ( hWnd ); break; } SetCaretPos ( nCaretPosX, nCaretPosY * dwCharY ); break; case WM_KEYDOWN: switch ( wParam ) { case VK_LEFT: // LEFT arrow /* Caret di chuy n qua trái và ch if ( nCaretPosX > 0 ) { HideCaret ( hWnd ); /* Tính toán l i v trí c a caret khi qua trái */ ch = pchInputBuf [--nCurChar ]; hdc = GetDC ( hWnd ); GetCharWidth32 ( hdc, ch, ch, &nCharWidth ); ReleaseDC ( hWnd, hdc ); nCaretPosX=max(nCaretPosX-nCharWidth,0 ); ShowCaret ( hWnd ); } break; case VK_RIGHT: // RIGHT arrow /* Di chuy n caret sang ph i */ n u dòng */

Trang 111

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
if (nCurChar < cch) { HideCaret ( hWnd ); /* Tính toán l i v trí c a caret khi sang ph i */ ch = pchInputBuf [ nCurChar ]; if ( ch == 0x0D ) { nCaretPosX = 0; nCaretPosY++; } /* N u kí t không ph i là enter thì ki m tra xem phím shift có ư c nh n hay không. N u có nh n thì màu và xu t ra màn hình. */ else { hdc = GetDC ( hWnd ); nVirtKey = GetKeyState ( VK_SHIFT ); if ( nVirtKey & SHIFTED ) { crPrevText=SetTextColor( hdc,RGB (255, 255, 255) ); crPrevBk= SetBkColor(hdc,RGB(0,0,0)); TextOut(hdc,nCaretPosX,nCaretPosY*dwCharY, &ch,1 ); SetTextColor ( hdc, crPrevText ); SetBkColor ( hdc, crPrevBk ); } i

Trang 112

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
GetCharWidth32(hdc,ch,ch,&nCharWidth); ReleaseDC ( hWnd, hdc ); nCaretPosX = nCaretPosX + nCharWidth; } nCurChar++; ShowCaret ( hWnd ); break; } break; case VK_UP: // Phím mũi tên lên case VK_DOWN: // Phím mũi tên xu ng MessageBeep ( (UINT) –1 ); return 0; case VK_HOME: // Phím home /* Thi t l p v trí c a caret dòng u tiên */

nCaretPosX = nCaretPosY = 0; nCurChar = 0; break; case VK_END: // Phím end /* Di chuy n v cu i văn b n và lưu v trí c a kí t xu ng dòng cu i */ for ( i=0; i < cch; i++ ) { if ( pchInputBuf [ i ] == 0x0D ) { cCR++;

Trang 113

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
nCRIndex = i + 1; } } nCaretPosY = cCR; /* Chép t t c các kí t t kí t xu ng dòng cu i */ for ( i = nCRIndex, j = 0; i < cch; i++, j++ ) szBuf [ j ] = pchInputBuf [ i ]; szBuf [ j ] = TEXT ( '\0' ); /* Tính v trí d c c a caret */ hdc = GetDC ( hWnd ); GetTextExtentPoint32(hdc,szBuf, lstrlen(szBuf), &sz ); nCaretPosX = sz.cx; ReleaseDC ( hWnd, hdc ); nCurChar = cch; break; default: break; } SetCaretPos( nCaretPosX, nCaretPosY*dwCharY ); break; case WM_PAINT: if ( cch == 0 ) break; hdc = BeginPaint ( hWnd, &ps ); n kí t hi n th i v a nh p t bàn phím vào b nh m.

Trang 114

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
HideCaret ( hWnd ); SetRect ( &rc, 0, 0, dwLineLen, dwClientY ); DrawText ( hdc, pchInputBuf, -1, &rc, DT_LEFT ); ShowCaret ( hWnd ); EndPaint ( hWnd, &ps ); break; case WM_DESTROY: PostQuitMessage ( 0 ); /* Gi i phóng buffer */ GlobalFree ( ( HGLOBAL) pchInputBuf ); UnregisterHotKey ( hWnd, 0xAAAA ); break; default: return DefWindowProc ( hWnd, message, wParam, lParam ); } return NULL; }

4.3. THI T B CHU T
Trong m t môi trư ng giao ti p h a, vi c s d ng thi t b nh v chu t là h t s c c n thi t. Nh thi t b chu t ta có th di chuy n n m t i m b t kì trên khung màn hình và th c hi n thao tác kích các nút chu t. i v i m t s ng d ng h a không quá ph c t p thì công c th c hi n ch y u là chu t, riêng i v i các ng d ng òi h i s ph c t p khi v thì ngư i ta dùng bút v . V i Windows thì thi t b chu t là m t thành ph n quan tr ng, n u chúng ta b thi t b chu t thì v n kh i ng bình thư ng và các chương trình v n có th ch y ư c. Tuy nhiên khi ó ta s lúng túng nhi u khi x lý các ng d ng tr c quan tương tác v i ngư i dùng theo t a hay nh v .

Trang 115

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ Cũng tương t như bàn phím, thi t b chu t cũng ư c dùng nh p d li u t ngư i dùng vào ng d ng nhưng d li u ây không ph i là văn b n như khi nh p t bàn phím mà là các thao tác v hay x lý các i tư ng h a.

4.3.1. Cơ b n v thi t b chu t trong Windows
V cơ b n Windows h tr các lo i thi t b chu t có m t nút, hai và ba nút, ngoài ra Windows còn có th dùng thi t b khác như joystick hay bút v b t chư c thi t b chu t. Các ng d ng trong Windows thư ng né vi c dùng các nút th hai và nút th ba, có th s d ng t t trên các thi t b chu t ch có m t nút. Thông thư ng nút th hai c a thi t b chu t ph i ư c dùng cho ch c năng g i th c ơn ng c nh (context menu). Theo nguyên t c, ta có th ki m tra xem có t n t i thi t b chu t hay không b ng cách dùng hàm GetSystemMetrics. fMouse = GetSystemMetrics( SM_MOUSEPRESENT ); Giá tr tr v fMouse là TRUE (1) n u có thi t b chu t ư c cài FALSE (0) n u thi t b chu t không ư c cài t vào máy. sau: nButton = GetSystemMetrics( SM_CMOUSEBUTTONS ); Giá tr tr v là 0 n u không cài v là 2 n u chưa cài t thi t b chu t. t thi t b chu t, tuy nhiên dư i Windows 98 giá tr tr t, và ngư c l i b ng

Ta cũng có th ki m tra s nút c a thi t b chu t b ng cách dùng hàm trên theo câu l nh

Khi ngư i dùng di chuy n thi t b chu t thì Windows cũng di chuy n m t nh bitmap nh trên màn hình, nh này ư c g i là con tr chu t (mouse cursor). Con tr chu t này có m t i m g i là i m nóng (hot spot) , i m nóng này n m trong hình bitmap, và do ngư i t o con tr chu t quy t nh. Khi chúng ta tham chi u t i m t v trí c a con tr chu t thì chính là chúng ta ang dùng t a c a i m nóng này. Windows h tr m t s các con tr chu t chu n, mà ngư i l p trình ch c n g i ra và dùng ch không c n ph i t o các t p tin *.cur. tr ng thái bình thư ng thì m t ng d ng trong Windows thư ng dùng con tr chu t IDC_ARROW ư c nh nghĩa trong WINUSER.H, i m nóng chính là i m trên cùng c a mũi tên. Ngoài ra con tr chu t còn cho bi t tr ng thái c a ng d ng, ví d m t ng d ng ang x lý c n m t kho ng th i gian thì con tr chu t xu t hi n hình ng h cát (IDC_WAIT). Khi ó h u như các ch c năng giao ti p v i ngư i dùng i u ph i hoãn n khi x lý hoàn thành. Trong l p c a s ta có trư ng nh nghĩa con tr chu t cho ng d ng như sau

wndclass.hCursor = LoadCursor ( NULL, IDC_ARROR); Trang 116

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ V i thi t b chu t ta có th có các hành ng như sau: • • • Kích chu t : nh n và th m t nút chu t. Kích úp chu t : nh n và th chu t nhanh (nh n 2 l n nhanh). Kéo : di chuy n chu t trong khi v n n m gi m t nút.

4.3.2. X lý các thông i p t thi t b chu t
Các thông i p ư c t o t chu t r t khác v i thông i p c a bàn phím, m t th t c c a s s nh n thông i p chu t b t c khi nào thi t b chu t di chuy n qua c a s hay kích vào trong c a s , th m chí c trong trư ng h p c a s không ư c kích ho t hay không nh n ư c s quan tâm. Windows nh nghĩa 21 thông i p ư c phát sinh t thi t b chu t. Trong s ó có n 11 thông i p không liên quan n vùng làm vi c (client area). Nh ng thông i p không ph i vùng làm vi c (nonclient-area messages) thư ng ư c các ng d ng b qua không x lý. 4.3.2.1. Thông i p chu t trong vùng làm vi c Khi con tr chu t di chuy n vào vùng làm vi c c a m t c a s , th t c c a s c a nó s nh n ư c thông i p WM_MOUSEMOVE. B ng sau mô t các thao tác làm vi c v i thi t b chu t và các thông i p phát sinh t nó. Nút Trái Gi a Ph i Nh n WM_LBUTTONDOWN Th WM_LBUTTONUP Nh n úp WM_LBUTTONDBLCLK WM_MBUTTONDBLCLK WM_RBUTTONDBLCLK

WM_MBUTTONDOWN WM_MBUTTONUP WM_RBUTTONDOWN WM_MBUTTONUP

B ng 4.8 Mô t thông i p kích thi t b chu t

Th t c c a s c a ng d ng s nh n ư c thông i p c a nút chu t gi a n u máy tính cài thi t b chu t có 3 nút. Tương t như v y v i thông i p thi t b chu t ph i, chúng ta c n có thi t b chu t dùng 2 nút. nh n ư c thông i p kích úp thi t b chu t th t c c a s ph i khai báo nh n thông i p này. Wndclass.style = CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS; Trong thông i p phát sinh t thi t b chu t thì tham s lParam s ch a v trí c a thi t b chu t, 16 byte th p s ch a giá tr t a x, còn 16 byte cao s ch a giá tr t a c a y. l y ra hai giá tr này ta có th dùng macro là LOWORD và HIWORD.

Trang 117

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ Giá tr wParam s cho bi t tr ng thái c a nút nh n, phím Shift, và phím Ctrl. Chúng ta có th ki m tra các tr ng thái này b ng cách dùng bit m t n ư c nh nghĩa trư c trong WINUSER.H. Các m t n này ư c b t u b ng ti n t MK_xxx (Mouse Key)

MK_LBUTTON MK_MBUTTON MK_RBUTTON MK_SHIFT MK_CONTROL

Nút chu t trái nh n Nút chu t gi a nh n Nút chu t ph i nh n Phím Shift ư c nh n Phím Ctrl ư c nh n

B ng 4.9 Mô t tr ng thái c a chu t và phím nh n

Ví d khi nh n ư c thông i p WM_LBUTTONDOWN chúng ta mu n ki m tra xem phím Ctrl có ư c nh n hay không b ng cách so giá tr wParam v i m t n MK_CONTROL.
... if (wParam & MK_CONTROL) { /* Có gi phím control */ } else { /* Không gi phím control */ }

Như chúng ta ã bi t khi di chuy n thi t b chu t qua vùng làm vi c thì thông i p WM_MOUSEMOVE s ư c g i n cho th t c c a s ó. Nhưng Windows không phát sinh thông i p này cho t ng pixel trên màn hình mà tuỳ thu c vào thông s ph n c ng c a thi t b chu t ư c cài t và t c làm vi c c a nó. Khi chúng ta kích nút chu t trái vào vùng làm vi c c a m t c a s không kích ho t (inactive window) thì Windows s kích ho t c a s này t c là c a s v a ư c kích sau ó Trang 118

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ truy n thông i p WM_LBUTTONDOWN vào th t c WndProc c a c a s . Khi m t c a s nh n ư c thông i p WM_XXXDOWN thì không nh t thi t ph i nh n ư c thông i p WM_XXXUP hay ngư c l i. i u này ư c gi i thích như sau, khi ngư i dùng kích trái vào m t c a s và gi luôn nút chu t v a kích r i kéo thi t b chu t n m t vùng thu c ph m vi c a c a s khác m i th . Khi ó c a s u tiên s nh n ư c thông i p nh n chu t WM_LBUTTONDOWN và c a s th hai s nh n ư c thông i p nh thi t b chu t WM_LBUTTONUP. Tuy nhiên tình hu ng trên s không xu t hi n v i hai trư ng h p ngo i l sau : • Th t c WndProc c a m t c a s ang th c hi n vi c b t gi thi t b chu t (mouse capture), i v i tình tr ng này thì c a s ti p t c nh n ư c thông i p chu t cho dù con tr chu t có di chuy n ra ngoài vùng làm vi c c a c a s . Ki u này thư ng xu t hi n trong các ng d ng v hay thao tác i tư ng h a, ví d khi ta v m t ư ng th ng dài và kéo ra ngoài vùng làm vi c c a c a s , thì khi ó c a s v s b t gi to c a thi t b chu t t o ư ng th ng và có th cho thanh cu n cu n theo. • N u xu t hi n h p thông tin tr ng thái (model) c a h th ng, thì không có chương trình nào khác nh n ư c thông i p c a thi t b chu t. H p tho i tr ng thái h th ng và h p tho i tr ng thái c a ng d ng ngăn c n vi c chuy n qua c a s khác trong m t ng khi nó chưa gi i quy t xong hay v n còn tr ng thái kích ho t (active). 4.3.2.2. Thông i p c a thi t b chu t ngoài vùng làm vi c V i các thông i p c a thi t b chu t v a tìm hi u trong ph n trư c u ư c phát sinh khi thi t b chu t n m trong vùng làm vi c c a c a s . Khi di chuy n con tr chu t ra kh i vùng làm vi c c a c a s nhưng v n trong ph m vi c a c a s thì khi ó các thông i p c a thi t b chu t s ư c phát sinh d ng thông i p c a thi t b chu t ngoài vùng làm vi c (nonclient-area). Ngoài vùng làm vi c c a m t c a s là c a s thanh tiêu , th c ơn, và thanh cu n c a c a s . Nói chung v i các thông i p c a thi t b chu t phát sinh t ngoài vùng làm vi c thì chúng ta không quan tâm l m, thay vào ó ta giao phó cho hàm m c nh x lý là DefWindowProc th c hi n. i u này cũng gi ng như là thông i p bàn phím h th ng mà ta ã tìm hi u trong các ph n trư c. Cũng tương t như thông i p xu t phát t vùng làm vi c, các thông i p ngoài vùng làm vi c ư c nh nghĩa v i t NC vào sau d u "_", ta có b ng mô t các thông i p phát sinh t ngoài vùng làm vi c như sau.
Nút Trái Gi a Ph i Nh n
WM_NCLBUTTONDOWN WM_NCMBUTTONDOWN WM_RBUTTONDOWN

Th
WM_NCLBUTTONUP WM_NCMBUTTONUP WM_NCRBUTTONDOWN

Nh n úp
WM_NCLBUTTONDBLCLK WM_NCMBUTTONDBLCLK WM_NCRBUTTONDBLCLK

Trang 119

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
B ng 4.10 Mô t các thông i p chu t ngoài vùng làm vi c

Các tham s lParam và wParam cũng hơi khác so v i các thông i p thi t b chu t phát sinh trong vùng làm vi c. V i tham s lParam c a thông i p phát sinh t ngoài vùng làm vi c s ch ra v trí ngoài vùng làm vi c nơi mà thi t b chu t di chuy n hay kéo t i. V trí này ư c nh danh b i các giá tr nh nghĩa trong WINUSER.H ư c b t u v i HT (vi t t t cho hittest).

Hình 4.2 Minh h a t a

màn hình và t a

vùng làm vi c

Tham s lParam s ch a t a x 16 byte th p và t a y 16 byte cao. Tuy nhiên, ây là t a màn hình, không ph i là t a vùng làm vi c gi ng như thông i p phát sinh t vùng làm vi c. Do ó chúng ta ph i chuy n v t a vùng làm vi c x lý ti p n u c n. t a chuy n t t a màn hình sang t a làm vi c hay ngư c l i t t a màn hình ta dùng hai hàm tương ng ư c Windows cung c p như sau : ScreenToClient( hwnd, &pt ); ClientToScreen( hwnd, &pt ); pt là bi t c u trúc POINT, hai hàm trên s nh n tham chi u hàm ta s ư c giá tr pt tương ng t a m i. n bi n pt do ó sau khi g i làm vi c sang

4.3.3 Ví d minh ho thi t b chu t

Trang 120

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ o n chương trình th c hi n ch c năng v t do b ng các thao tác: Nh n chu t trái v m t ư ng th ng t v trí con tr c a bút v n v trí chu t trái kích, ngoài ra ta cũng có th v b ng cách nh n phím trái và gi luôn sau ó ta kéo chu t n v trí b t kì r i th . N u ta nh n chu t ph i thì s i màu c a bút v .
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hdc; static POINT oldPoint; static int iC; int WIDTH_PEN = 2; HPEN oPen,pen; COLORREF Col [ ] ={ RGB (0, 0, 0) , RGB (255 ,0 ,0), RGB (0, 255, 0), RGB (0, 0, 255), RGB (255, 255, 0)}; POINT point; TCHAR str [255]; switch ( message ) // X lý thông i p { case WM_LBUTTONDOWN: /* V ư ng th ng t v trí trư c ó n v trí chu t hi n t i*/

hdc = GetDC ( hWnd ); pen = CreatePen ( PS_SOLID,WIDTH_PEN,Col [ iC] ); oPen = ( HPEN ) SelectObject ( hdc,pen ); point.x = LOWORD ( lParam );

Trang 121

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
point.y = HIWORD ( lParam ); MoveToEx ( hdc, oldPoint.x, oldPoint.y, NULL ); LineTo ( hdc, point.x, point.y ); oldPoint = point; /* Ch n l i bút v trư c ó và h y bút v v a t o*/ SelectObject ( hdc, oPen ); DeleteObject ( pen ); ReleaseDC ( hWnd, hdc ); break; case WM_RBUTTONDOWN: /* Chuy n index c a b ng màu sang v trí ti p theo, n u cu i b ng màu thì quay l i màu iC = ( iC+1 ) % ( sizeof ( Col ) / sizeof ( COLORREF ) ); break; case WM_MOUSEMOVE: /* Xu t to chu t hi n th i lên thanh tiêu */ u tiên*/

sprintf ( str,"Toa do chuot x = %d, To do y = %d", LOWORD(lParam), HIWORD(lParam)); SetWindowText ( hWnd, str ); /* Ki m tra xem có gi phím chu t trái hay không*/ if ( wParam & MK_LBUTTON ) { hdc = GetDC ( hWnd ); pen = CreatePen ( PS_SOLID,WIDTH_PEN,Col [ iC ] ); oPen = ( HPEN ) SelectObject ( hdc, pen ); point.x = LOWORD ( lParam ); point.y = HIWORD ( lParam );

Trang 122

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
MoveToEx ( hdc, oldPoint.x, oldPoint.y, NULL ); LineTo ( hdc, point.x, point.y ); oldPoint = point; SelectObject ( hdc, oPen ); DeleteObject ( pen ); ReleaseDC ( hWnd, hdc ); } break; case WM_DESTROY: PostQuitMessage ( 0 ); break; default: return DefWindowProc ( hWnd, message, wParam, lParam ); } return 0; }

4.4. B

NH TH I GIAN

Như chúng ta ã bi t Windows cung c p cho ta các thông tin thông qua d ng thông i p như là thông i p bàn phím, thông i p phát sinh t thi t b chu t . Và ngoài ra thì m t thông i p cũng r t h u d ng là thông i p th i gian. Khi vi t m t chương trình chúng ta có th yêu c u h i u hành g i m t thông i p c nh báo theo t ng kho ng th i gian nh t nh chúng ta có th làm m t s x lý c n thi t. Thông i p này ư c g i t h i u hành n chương trình thông qua m t b nh th i gian (Timer) và thông i p ư c phát sinh là WM_TIMER. Vi c dùng ch c năng này r t ơn gi n, ta khai báo m t b nh th i gian và thi t l p thông s kho ng th i gian Windows phát sinh thông i p Timer cho ng d ng. Khi ó ng d ng ch c n x lý thông i p WM_TIMER trong hàm x lý c a s WinProc.

4.4.1. B

nh th i gian và v n

ng b

Trang 123

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ Theo lý thuy t thông i p th i gian do Windows cung c p là chính xác n mili giây nhưng th c t không hoàn toàn như v y. S chính xác còn ph thu c vào ng h c a h th ng và các ho t ng hi n th i c a chương trình. Nguyên nhân c a v n là thông i p th i gian WM_TIMER có ưu tiên th p, như thông i p tô v l i màn hình WM_PAINT, thông thư ng chúng ph i ch cho x lý xong các thông i p khác.

4.4.2. Kh i t o b

nh th i gian

Không như thông i p xu t phát t bàn phím và chu t, ư c Windows g i t ng vào hàng i thông i p c a ng d ng. i v i thông i p th i gian ph i ư c khai báo trư c b ng hàm SetTimer, sau khi khai báo hàm này thì Windows s g i thông i p WM_TIMER i u n vào hàng i c a ng d ng. Hàm SetTimer ư c khai báo như sau : UINT_PTR SetTimer( HWND hWnd, UINT_PTR nIDEvent, UINT uElapse, TIMERPROC lpTimerFunc ); Trong ó ý nghĩa các tham s ư c mô t :

nh th i gian. • hWnd : nh danh c a c a s khai báo dùng b • nIDEvent : nh danh c a b nh th i gian. • nElapse : Là kho ng th i gian ngh gi a hai l n g i thông i p • lpTimerFunc : Hàm s x lý khi thông i p WM_TIMER phát sinh, n u chúng ta khai báo là NULL thì Windows s g i thông i p WM_TIMER vào hàng i thông i p c a c a s tương ng. Khi không còn dùng b hàm này ư c khai báo : nh th i gian n a hay k t thúc ng d ng ta g i hàm KillTimer,

BOOL KillTimer( HWND hWnd, UINT_PTR uIDEvent ); • • hWnd : nh danh c a c a s dùng b nh th i gian uIDEvent : nh danh c a b nh th i gian.

4.4.3. Ví d v b

nh th i gian

4.4.3.1. Dùng thông i p WM_TIMER o n chương trình minh h a vi c s d ng b nh th i gian trong chương trình. C m i 0.5 giây thì chương trình phát sinh t ng ng u nhiên m t vòng tròn trên màn hình.
#include <time.h>

Trang 124

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
#include "stdio.h" #define MAX_POINT 10000 #define IDT_TIMER1 1 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; static int NumCir = 0; static POINT point [ MAX_POINT ]; int r = 5, i; HPEN pen, oldPen; RECT rc; TCHAR str [255]; /* X lý thông i p*/ switch ( message ) { case WM_CREATE: /* Khai báo dùng b nh th i gian trong ng d ng*/

SetTimer(hWnd, IDT_TIMER1, 500, ( TIMERPROC )NULL); /* Kh i ng hàm ng u nhiên*/

srand ( (unsigned) time( NULL ) ); break; case WM_PAINT: hdc = BeginPaint ( hWnd, &ps );

Trang 125

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
pen = CreatePen ( PS_SOLID, 2, RGB (255,0,0) ); oldPen = (HPEN) SelectObject ( hdc, pen ); /* V các vòng tròn v i tâm là các i m lưu trong point và bán kính là r */ for( i=0; i < NumCir; i++ ) Arc ( hdc, point[i].x-r, point[i].y-r, point[i].x+r, point[i].y+r, point[i].x+r, point[i].y,point[i].x+r,point[i].y); /* L y l i bút v trư c ó và hũy bút v v a t o*/ SelectObject ( hdc, oldPen ); DeleteObject ( pen ); EndPaint ( hWnd, &ps ); break; case WM_TIMER: /* L y thông tin c a vùng làm vi c*/ GetClientRect ( hWnd, &rc ); /*Phát sinh ng u nhiên m t vòng tròn*/ point [NumCir].x = rand( ) % (rc.right - rc.left); point [NumCir].y = rand( ) % (rc.bottom - rc.top); NumCir++; /*Hi n th s vòng tròn ã sinh ra trên thanh tiêu sprintf ( str,"So vong tron : %d", NumCir); SetWindowText ( hWnd, str ); /* Làm b t h p l vùng làm vi c & yêu c u v l i */ InvalidateRect ( hWnd, &rc, FALSE); break; case WM_DESTROY: /* H y b s d ng b nh th i gian*/ */

Trang 126

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
KillTimer ( hWnd, IDT_TIMER1 ); PostQuitMessage ( 0 ); break; default: return DefWindowProc ( hWnd, message, wParam, lParam ); } return 0; }

4.4.3.2. Dùng hàm x lý o n chương trình sau cũng khai báo s d ng m t b nh th i gian, nhưng khai báo tr c ti p, t c là khi h t th i gian ch thay vì truy n thông i p WM_TIMER thì Windows g i hàm TimerProc th c hi n. Chương trình khi th c thi s xu t ra m t d ng :giây.
#include <time.h> #include "stdio.h" #define IDT_TIMER1 1 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; /* Khai báo bi n lưu các giá tr không gian*/ struct tm *newtime; time_t CurTime; TCHAR str [255];

ng h

i n t theo d ng : gi : phút

Trang 127

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
RECT rc; /* Bi n LOGFONT LOGFONT lf; HFONT oldFont, font; COLORREF color = RGB (255, 0, 0), oldColor; switch ( message ) { case WM_CREATE: /* kh i t o b nh th i gian, và khai báo hàm x lý Timer*/ t o font m i*/

SetTimer ( hWnd, IDT_TIMER1, 1000, ( TIMERPROC ) TimerProc ); break; case WM_PAINT: hdc = BeginPaint ( hWnd, &ps ); /* L y gi ng h h th ng*/

time( &CurTime ); newtime = localtime ( &CurTime ); GetClientRect ( hWnd, &rc ); /* T o chu i xu t ra màn hình*/ sprintf(str,"Gio hien tai : %d gio: %d phut: %d giay", newtime->tm_hour,newtime->tm_min, newtime>tm_sec); /* Thi t l p màu kí t xu t*/ oldColor = SetTextColor ( hdc, color ); /* T o font riêng dùng*/

memset ( &lf, 0, sizeof ( LOGFONT ) ); lf.lfHeight = 50;

Trang 128

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
strcpy ( lf.lfFaceName, "Tahoma" ); font = CreateFontIndirect ( &lf ); oldFont = ( HFONT ) SelectObject ( hdc,font ); /* Xu t ra màn hình*/ DrawText ( hdc, str, strlen(str), &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE ); /* L y l i các giá tr m c nh*/

SetTextColor ( hdc,oldColor ); SelectObject ( hdc,oldFont ); DeleteObject ( font ); EndPaint ( hWnd, &ps ); break; case WM_DESTROY: PostQuitMessage ( 0 ); break; default: return DefWindowProc ( hWnd, message, wParam, lParam ); } return 0; } /* Hàm x lý c a Timer*/ VOID CALLBACK TimerProc( HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) { /* Hàm này ơn gi n yêu c u tô l i vùng làm vi c*/ RECT rc; GetClientRect ( hwnd, &rc );

Trang 129

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
InvalidateRect ( hwnd, &rc, TRUE ); }

Chương 5 X
5.1. M U

LÝ VĂN B N VÀ FONT CH

M t trong các c tính n i b t nh t c a Windows là giao di n giao ti p v i ngư i dùng. Nh c tính này, nhi u d ng d li u thông tin khác nhau ư c máy tính h tr khi xu t ra màn hình, máy in, … Trong ó, xu t văn b n ra vùng làm vi c c a các ng d ng Win32 là hình th c ph bi n nh t trong giao di n h a.

Trang 130

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ các chương trư c, các thao tác xu t thông tin ch ư c th c hi n thông qua các c a s thông báo, h p tho i và các ph n t i u khi n. Chương này s trình bày cách th hi n n i dung văn b n trên vùng làm vi c c a c a s thông qua các hàm Win32® API. Ph n cu i chương s trình bày cách kh i t o, ch n và x lý các d ng font ch khác nhau. Nh kh năng này, vi c th hi n các o n văn b n s tr nên sinh ng và tr c quan hơn.

5.2. X

LÝ VĂN B N

X lý văn b n là công vi c ph bi n nh t trong các thao tác h a. Chúng ư c s d ng theo các nh d ng và cách th c khác nhau trong các ng d ng x lý tài li u, b ng bi u, cơ s d li u và h tr thi t k b ng máy tính (CAD - Computer Aided Design). T p h p các hàm Win32® API x lý văn b n ư c phân thành hai nhóm chính: Nhóm các hàm nh d ng – chu n b cho thao tác xu t d li u, và nhóm các hàm th c hi n thao tác hi n th . Chúng ta s b t u v i vi c tìm hi u các hàm hi n th .

5.2.1. Hi n th văn b n
hi n th n i dung văn b n trên các thi t b xu t, d a vào t ng trư ng h p th hi n khác nhau, ta dùng các hàm Win32 API khác nhau. Các hàm này ph thu c vào font ch , thu c tính c a thi t b ng c nh DC (Device Context ) và kho ng cách ký t th hi n. Hàm ph bi n nh t th c hi n thao tác xu t m t chu i ký t văn b n, s d ng font ch , màu ch và màu n n hi n hành là : BOOL TextOut(HDC hDC, int nXStart, int nYStart, LPCTSTR lpString, int cbString); Hàm này th c hi n thao tác xu t chu i ký t xác nh b i con tr lpString ra DC, v i chi u dài ư c xác nh b i cbString (không ph thu c vào ký t NULL ánh d u k t thúc chu i). Hai trư ng nXStart và nYStart là v trí g c c a chu i hi n th , xác nh theo t a logic c a vùng làm vi c c a s , và thư ng là i m g c trên bên trái c a vùng hi n th chu i. Chúng ta s bàn k hơn khi tìm hi u v canh l văn b n trong ph n 5.2.2. N u thao tác xu t chu i th c hi n thành công, hàm tr v giá tr khác 0. Ngư c l i, giá tr tr v b ng 0. Khi c n trình bày văn b n theo tu n t t ng c t, ta dùng hàm TabbedTextOut sau : LONG TabbedTextOut(HDC hDC, int nX, int nY, LPCTSTR lpString, int nCount, int nNumTabs, LPINT lpnTabStopPositions, int nTabOrigin);

Trang 131

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ N u trong chu i ký t có các ký t tab (‘\t’ ho c 0x09), hàm TabbedTextOut s chuy n các ký t tab vào dãy các v trí "d ng" tương ng. S lư ng các tab d ng ư c xác nh b i nNumTabs, và lpnTabStopPositions là dãy v trí các tab d ng theo ơn v tính pixels. Ví d , n u r ng trung bình c a m i ký t là 8 pixels, và m i tab d ng c n t cách nhau 5 ký t , dãy các tab d ng s ph i l n lư t có giá tr 40, 80, 120, … . Tuy nhiên, các giá tr này không nh t thi t ph i là b i s c a nhau. N u bi n nNumTabs ho c lpnTabStopPositions có giá tr là 0 và NULL, các tab d ng ư c t cách nhau t ng 8 ký t . N u nNumTabs b ng 1, lpnTabStopPositions tr n giá tr xác nh m t dãy tăng tu n hoàn là b i s c a dãy này. Ví d , n u nNumTabs b ng 1, và lpnTabStopPositions b ng 30, ta s có dãy tab d ng t i v trí 30, 60, 90, … pixels. Trư ng nTabOrigin xác nh t a theo tr c x c a i m b t u tính kho ng cách t i các tab. Giá tr này không nh t thi t ph i là v trí u tiên c a chu i, có th ch n trùng ho c không. Hàm tr v kích thư c chu i hi n th , theo ơn v logic, n u thành công. Ngư c l i, hàm tr v 0. Trong ó, chi u cao chu i là WORD cao c a bi n ki u LONG, chi u r ng là WORD th p. M t hàm xu t văn b n khác tương t hàm TextOut là hàm ExtTextOut : BOOL ExtTextOut(HDC hDC, int X, int Y, UINT fuOptions, CONST RECT *lprc, LPCTSTR lpString, UINT cbCount, CONST INT *lpDx); Bi n lprc là m t con tr n c u trúc RECT, trong ó n i dung văn b n hi n th s b c t vào vùng hình ch nh t tương ng n u fuOptions ư c thi t l p là ETO_CLIPPED, ho c là vùng n n hình ch nh t s ư c tô b i màu n n n u fuOptions là ETO_OPAQUE. Trư ng lpDx là m t dãy s nguyên xác nh kho ng cách gi a các ký t liên ti p trong chu i. Nó cho phép m t chương trình t o kho ng cách r ng ho c h p gi a các ký t , i u mà ôi lúc c n thi t trong vi c i u ch nh các t trong văn b n theo r ng c t. Giá tr lpDx có th là NULL tương ng v i ch m c nh cho kho ng cách này. Tương t hàm TextOut, hàm ExtTextOut tr v giá tr khác 0 n u thành công. Ngư c l i, giá tr tr v b ng 0. M t hàm m c m c cao hơn xu t văn b n là hàm DrawText :

int DrawText(HDC hDC, LPCTSTR lpString, int nCount, LPRECT lpRect, UINT uFormat); Cũng như các hàm xu t văn b n khác, hàm DrawText xu t chu i xác nh b i con tr lpString có dài nCount. Tuy nhiên, v i chu i có ký t k t thúc là NULL, n u nCount b ng -1, hàm s t ng tính toán chi u dài c a chu i.

Trang 132

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ Bi n lpRect tr n c u trúc RECT c a hình ch nh t (theo to logic) mà trong ó văn b n th hi n theo nh d ng ư c thi t l p trong uFormat. N u uFormat b ng 0, n i dung văn b n s ư c hi n th theo t ng dòng t trên xu ng dư i. M i dòng m i ư c xác nh thông qua ký t v u dòng CR (carriage return, b ng ‘\r’ ho c 0x0D) ho c ký t xu ng dòng LF (linefeed, b ng ‘\n’ ho c 0x0A) có trong văn b n. Ph n văn b n bên ngoài hình ch nh t lpRect s b c t b . Giá tr uFormat b ng 0 cũng chính là giá tr c canh l trái (DT_LEFT). Ngoài ra, ta có th thi t l p các c canh l ph i (DT_RIGHT), và canh l gi a (DT_CENTER) cho văn b n. lo i b ch c năng i u khi n c a các ký t CR và LF, c n thêm vào c DT_SINGLELINE. N u thi t l p DT_SINGLELINE, ta cũng có th ch nh v trí c a dòng hi n th phía trên (DT_TOP), phía dư i (DT_BOTTOM), ho c chính gi a (DT_VCENTER) trong vùng hình ch nh t. Trong trư ng h p hi n th nhi u dòng văn b n, Windows ch ng t dòng khi g p ký t CR và LF. ng t dòng dài hơn kích thư c hình ch nh t hi n th , c n thi t l p c DT_WORDBREAK. N u không mu n Windows c t b các ph n dư ra khi v ch vư t quá ph m vi khung ch nh t, ta thêm c DT_NOCLIP. N u mu n ký t tab (‘\t’ ho c 0x09) ư c di n d ch thành ký t phân c t, c n thêm c DT_EXPANDTABS. Giá tr m c nh c a tab là 8 kho ng tr ng. C DT_TABSTOP ư c dùng t l i giá tr tab. Trong trư ng h p này, byte cao c a word th p (bits 15-8) c a uFormat s ch a giá tr tab c n thay th .

5.2.2.
D a vào nhóm liên quan

nh d ng văn b n
c trưng các thành ph n hi n th , các hàm nh d ng văn b n phân làm ba n thu c tính c a DC, r ng ký t và kích thư c chu i ký t hi n th .

Vi c thi t l p thu c tính nh d ng văn b n cho DC ư c th c hi n thông qua các hàm canh l văn b n, thi t l p kho ng cách ký t , xác nh màu n n và màu văn b n. Cùng v i các hàm này, Windows cũng cung c p các hàm cho bi t thu c tính hi n hành tương ng cho DC. Trong các hàm v thu c tính DC, bi n hàm thi t l p màu ch và màu n n : u tiên luôn là handle c a DC hi n hành. Xét

COLORREF SetTextColor(HDC hDC, COLOREF crColor); COLORREF SetBkColor(HDC hDC, COLORREF crColor); Bi n crColor xác nh màu c n thi t l p. N u thành công, hàm tr v màu ch (màu n n) trư c khi ư c thi t l p. N u không, hàm tr v giá tr c CLR_INVALID. Ngoài ra, xác nh màu ch và màu n n hi n hành, ta dùng hai hàm sau : COLORREF GetTextColor(HDC hDC); Trang 133

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ COLORREF GetBkColor(HDC hDC); N u hàm th c hi n thành công, ta xác là CLR_INVALID. nh ư c màu hi n hành. N u không, giá tr tr v

Khi v ch , Windows s d ng hai ch : ch trong su t (TRANSPARENT) và ch m (OPAQUE). ch trong su t, màu n n s không ư c s d ng n, ch v ra è lên n n hi n hành. ch m , trư c khi v ch , n n s ư c xoá i v i màu n n ư c thi t l p b i hàm SetBkColor: int SetBkColor(HDC hDC, int iBkMode); n n TRANSPARENT ho c OPAQUE (ch m c nh c a V i iBkMode là ch Windows là OPAQUE). N u thành công, hàm tr v ch n n trư c khi ư c thi t l p. Ngư c l i, giá tr tr v là zero. bi t ch n n hi n t i, ta dùng hàm : int GetBkMode(HDC hDC); Hàm tr v giá tr TRANSPARENT ho c OPAQUE, n u thành công. Ngư c l i, giá tr tr v là zero. xác l p v trí chu i văn b n hi n th d a trên i m g c nXStart, nYStart (xem ph n 5.2.1) ta dùng hàm SetTextAlign : UINT SetTextAlign(HDC hDC, UINT fMode); Khi ó, i m g c nXStart c nh bên trái khung ch nh t n u fMode là TA_LEFT. Ký t u chu i s hi n th t i m g c này. ây cũng là giá tr m c nh c a Windows. N u fMode b ng TA_RIGHT, v trí chu i ư c tính t bên ph i, t c ký t cu i chu i hi n th t i i m g c, và ngư c l i cho n ký t u tiên. N u fMode b ng TA_CENTER, v trí gi a chu i chính là i m g c. Tương t , thi t l p v trí hi n th chu i theo phương ng, các c TA_TOP, TA_BOTTOM, và TA_BASELINE ư c dùng tương ng i m g c nYStart trên, gi a và dư i dòng văn b n hi n th . i v i Windows thì giá tr m c nh theo phương ng là TA_TOP. N u g i hàm SetTextAlign v i c TA_UPDATE, Windows s không s d ng i m g c nXStart, nYStart trong hàm xu t văn b n TextOut, thay vào ó là v trí ư c thi t l p trư c ó b i hàm MoveToEx ho c LineTo, ho c m t hàm thay i v trí khác. C TA_UPDATE cũng c p nh t i m g c v u chu i (n u dùng TA_LEFT) và v cu i chu i (n u dùng TA_RIGHT) cho l n g i k ti p. i u này c n thi t cho vi c hi n th nhi u dòng văn b n v i hàm TextOut. N u c TA_CENTER ư c thi t l p, v trí c a nXStart v n như cũ sau khi hàm TextOut ư c g i. bi t ch canh l văn b n hi n t i, ta dùng hàm : Trang 134

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ UINT GetTextAlign(HDC hDC); N u thành công, hàm tr v c tương ng c a canh l văn b n hi n hành. Ngư c l i, giá tr tr v là GDI_ERROR. Ví d sau ây trình bày cách th c xác nh các d ng canh l theo phương ngang:

switch ( (TA_LEFT | TA_RIGHT | TA_CENTER) & GetTextAlign(hDC) ) { case TA_LEFT: . . . case TA_RIGHT: . . . case TA_CENTER: . . . }

Ví d ti p theo s d ng hàm SetTextAlign c p nh t v trí hi n th hi n th i khi hàm TextOut ư c g i. Trong ví d này, bi n cArial là m t s nguyên cho bi t s font Arial.
UINT uAlignPrev; char szCount[8]; uAlignPrev = SetTextAlign(hdc, TA_UPDATECP); MoveToEx(hdc, 10, 50, (LPPOINT) NULL);

Trang 135

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
TextOut(hdc, 0, 0, "Number of Arial fonts: ", 23); itoa(cArial, szCount, 10); TextOut(hdc, 0, 0, (LPSTR) szCount, strlen(szCount)); SetTextAlign(hdc, uAlignPrev);

M t thu c tính khác c a DC nh hư ng n cách v chu i là kho ng cách gi a các ký t trong chu i hi n th . Kho ng cách m c nh c a Windows là 0, khi ó các ký t ư c hi n th liên ti p nhau. thay i kho ng cách gi a các ký t , ta dùng hàm : int SetTextCharacterExtra(HDC hDC, int nCharExtra); Trong ó, nCharExtra là kho ng cách theo ơn v logic thi t l p gi a các ký t . N u thành công, hàm tr v kho ng cách trư c khi ư c thi t l p. Ngư c l i, giá tr tr v là 0x80000000. bi t kho ng cách hi n t i, ta dùng hàm : int GetTextCharacterExtra(HDC hDC); N u thành công, giá tr tr v cho bi t kho ng cách hi n t i. Ngư c l i, giá tr tr v là 0x80000000. Ngoài ra, Windows còn h tr các hàm cho bi t r ng ký t và kích thư c chu i hi n th . ây là các hàm c p cao, s d ng trong vi c trình bày văn b n v i các ki u font khá ph c t p. Trong chương này, chúng ta ch c p n m t s hàm như GetTextMetrics (ph n 5.3.2) và GetTextExtentPoint32 (ph n 5.3.5).

5.3. FONT CH
Trong Windows, khi trình bày văn b n, các ký t ư c th hi n theo nhi u d ng khác nhau. ây là m t trong nh ng c trưng cơ b n c a giao di n h a - ngư i dùng (GUI – Graphical User Interface). th c hi n i u này, Windows h tr nhi u d ng font ch khác nhau. Trong ph n này, chúng ta tìm hi u các v n chính v các font ch , cũng như cách s d ng chúng trình bày văn b n.

5.3.1. Khái ni m font trong Windows
M t font ch là m t t p h p các ký t và ký hi u cùng d ng, th hi n qua ki u ch , lo i ch và kích c ch . Ki u ch xác nh các c trưng v ký t và ký hi u trong font ch , ví d r ng, nét ch dày ho c m nh, có chân (có g ch ngang ho c các nét cong m nh u các ký t ) hay không.

Trang 136

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ Lo i ch xác nh m nh t (tr ng lư ng) và nghiêng c a d ng font th hi n. Chia làm ba lo i sau : roman, opaque, và italic. Font roman là d ng font ch có tr ng lư ng trung bình, thư ng dùng trong in n. Font opaque là d ng ư c bi n i ngiêng c a font roman. Font italic là d ng font ư c thi t k theo d ng nghiêng chuyên bi t. Kích thư c font ch ư c tính như là kho ng cách t ch n dư i c a m t ký t có chân n ch n trên c a m t ký t hoa, và ư c tính theo ơn v i m (kho ng 0,013817 c a 1 inch). M t t p các font v i m t s kích c và tr ng lư ng khác nhau nhưng cùng m t ki u lo i ư c xem là m t h font ch . Các font ch trong Windows ư c chia thành hai nhóm, g i là font GDI và font thi t b . Font GDI ư c lưu tr dư i d ng t p tin trên ĩa, trong khi font thi t b ư c thi t k s n trong thi t b xu t tương ng, ví d máy in. Không như font GDI, khi in b ng font thi t b , Windows không c n nh d ng font, mà ch c n g i n i dung d li u tr c ti p n thi t b . Ngư i dùng ch n tr c ti p font t máy in in. i v i font GDI, Windows chuy n văn b n thành nh bitmap sau ó chuy n n máy in in. Như v y, l i i m c a font GDI là c l p v i thi t b xu t, tuy nhiên t c x lý in ch m hơn. Các font GDI thông thư ng g m có : font bitmap, font vector và font TrueType. Font bitmap ư c c u thành t ma tr n pixel, có l i i m là hi n th nhanh, nhưng h n ch trong vi c th hi n v i các kích thư c khác nhau (do ch phóng to – thu nh , và khi phóng trông r t thô). Font vector th hi n các ký t như là t p h p các nét v (s d ng các hàm GDI), do ó linh ng và co gi n hơn font bitmap, tuy nhiên ư c v khá ch m và ư ng nét cũng không ư c m m m i cho l m. Font TrueType là d ng font ư c s d ng ph bi n nh t hi n nay, ư c lưu tr dư i d ng m t t p các i m nh, k t h p m t s thu t toán bi n i. Do ó th hi n s c x o các ư ng nét trên màn hình và máy in. Chúng ta s kh o sát các hàm x lý cho các font ch d ng này trong ph n 5.3.3. Còn bây gi chúng ta tìm hi u cách s d ng các font có s n c a h th ng.

5.3.2. S d ng font

nh nghĩa s n

Khi ta g i các hàm v ch TextOut, TabbedTextOut, ExtTextOut ho c DrawText, Windows s s d ng font ch ang ư c ch n trong DC hi n th n i dung văn b n. Ta có th dùng m t s font ư c Windows nh nghĩa s n, thư ng g i là font h th ng (phân bi t các font do ngư i dùng t o trong quá trình x lý văn b n – xem ph n 5.3.3). Tên macro c a các font này th hi n trong b ng sau : MACRO
ANSI_FIXED_FONT

FONT Font v i kích thư c c nh c a ký t d a trên Windows. Font Courier là m t ví d i n hình c a d ng font này. Trang 137

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
ANSI_VAR_FONT

Font v i r ng ký t thay i d a trên các ký t chu n c a Windows. Font MS San Serif là m t ví d i n hình. Font v i thi t b ã cho ư c ch n m c nhiên. D ng font này thư ng co s n trong h th ng i u khi n vi c trình bày trên thi t b . Tuy nhiên, i v i m t s thi t b , font ư c cài t ngay trên thi t b . Ví d , i v i máy in, các font thi t b cài s n th c hi n thao tác in nhanh hơn so v i vi c load bitmap nh v t máy tính. Font c a giao di n nh. h a ư c thi t l p m c

DEVICE_DEFAULT_FONT

DEFAULT_GUI_FONT

OEM_FIXED_FONT

Font ch c nh, d a trên b ký t OEM. Ví d , i v i máy IBM®, font OEM d a trên b ký t IBM PC. Font h th ng c a Windows. ư c h i u hành dùng trình bày các thành ph n giao di n như thanh tiêu , menu, n i dung văn b n trong các h p tho i thông i p. Các font h th ng này luôn có s n khi cài h i u hành, trong khi các font khác c n ph i cài thêm tùy theo ng d ng sau này. Font Windows ư c s d ng như font h th ng trong các phiên b n trư c 3.0.
B ng 5.1 Macro các font nh nghĩa s n.

SYSTEM_FONT

SYSTEM_FIXED_FONT

Vi c ch n và s d ng font h th ng trong Windows khá ơn gi n. làm i u này, tiên chương trình t o ra handle c a font - ki u bi n HFONT, sau ó ch n font dùng hàm GetStockObject. HGDIOBJ GetStockObject(int fnObject);

u

Trong ó, ki u HGDIOBJ là HFONT, bi n fnObject là m t trong các macro b ng trên. N u thành công, hàm này tr v handle c a font h th ng hi n hành. Ngư c l i, giá tr tr v là NULL. thay i font, ta g i hàm SelectObject. HGDIOBJ SelectObject(HDC hDC, HGDIOBJ hGDIObj); Ho c g n hơn, ta có th g i :

Trang 138

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ SelectObject(hDC.GetStockObject(fnObject)); Khi ó, font hi n hành trong DC là font v a ư c g i. Hàm tr v macro font trư c ó. N u không thành công, l i tr v là GDI_ERROR. Thư ng khi g i font nh s n, n u các font không có s n, h th ng s tr v font h th ng (SYSTEM_FONT). Lưu ý, ch nên dùng các font có s n n u ch hi n th c a DC ng d ng hi n th i là MM_TEXT. xem các thu c tính c a font h th ng, ví d kích thư c c a b font khi xu t văn b n, ta dùng hàm GetTextMetrics. BOOL GetTextMetrics(HDC hDC, LPTEXTMETRIC lpTM); Bi n lpTM là con tr n c u trúc TEXTMETRIC mà n u hàm th c hi n thành công (tr v giá tr nonzero) s ch a các tham s c a font. o n chương trình sau minh h a vi c ch n font chu i ký t s d ng font này. HFONT hfnt, hOldFont; hfnt = GetStockObject(ANSI_VAR_FONT); if (hOldFont = SelectObject(hdc, hfnt)) { TextOut(hdc, 10, 50, "Sample ANSI_VAR_FONT text.", 26); SelectObject(hdc, hOldFont); } Tuy nhiên, font ch h th ng khá nghèo nàn, không áp ng nhu c u trình bày văn b n. Vì th , Windows h tr các hàm s d ng các font ch t t o. Ph n ti p theo s bàn k hơn v các hàm x lý các font này. nh s n vào m t DC, sau ó vi t m t tính toán v trí

5.3.3. S d ng font t t o
Font logic là m t i tư ng GDI có handle ki u HFONT. M t font logic là m t mô t c a m t font ch th c t . Tương t như vi t v logic và ch i sơn logic, font logic là m t i tư ng tr u tư ng, và tr thành font th c t trong DC khi ng d ng g i hàm SelectObject. u tiên, ta c n cách sau : nh nghĩa các trư ng trong c u trúc LOGFONT theo m t trong hai

Trang 139

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ • Thi t l p các trư ng trong c u trúc LOGFONT d a trên các c tính c a font b n quan tâm. Trong trư ng h p này, khi g i hàm SelectObject, Windows s s d ng m t thu t toán "ánh x font" ch n m t font tương thích nh t hi n có trên thi t b. • Ch n font trong h p tho i Font, hàm ChooseFont s kh i gán các giá tr trong c u trúc LOGFONT theo thu c tính font ư c ch n. s d ng font này trong các thao tác xu t văn b n, trư c h t ng d ng c n kh i t o font logic, r i chuy n cho DC. Vi c t o font logic ư c th c hi n b ng cách g i hàm CreateFont ho c hàm CreateFontIndirect. Tuy nhiên, hàm CreateFont ít ư c s d ng hơn do hàm c n g i các bi n trong c u trúc LOGFONT, trong khi hàm CreateFontIndirect ch c n bi n con tr LOGFONT. C hai hàm u tr v handle c a font logic HFONT. Trư c khi ng d ng có th xu t văn b n, font logic c n ư c ánh x tương ng v i m t font v t lý trong thi t b xu t, ho c font n p vào h i u hành. Ti n trình này ư c th c hi n khi ng d ng g i hàm SelectObject. Khi ó, ta có th dùng hàm GetTextMetrics (ho c các hàm tương ương) xác nh kích thư c và c trưng c a font th c tính v trí và xu t văn b n ra thi t b xu t. Sau khi dùng font, ta c n lo i b font dùng hàm DeleteObject. Chú ý không ư c xoá font trong DC ang th c thi, ho c font h th ng.

5.3.4. C u trúc LOGFONT và TEXTMETRIC
t o font logic, ta có th g i hàm CreateFont và CreateFontIndirect. Hàm CreateFontIndirect nh n con tr c u trúc LOGFONT. Hàm CreateFont có bi n là 14 trư ng c a LOGFONT. Xét nh nghĩa c a c u trúc LOGFONT : typedef struct tagLOGFONT // lf { LONG lfHeight; LONG lfWidth; LONG lfEscapement; LONG lfOrientation; LONG lfWeight; BYTE lfItalic; BYTE lfUnderline; Trang 140

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ BYTE lfStrikeOut; BYTE lfCharSet; BYTE lfOutPrecision; BYTE lfClipPrecision; BYTE lfQuality; BYTE lfPitchAndFamily; TCHAR lfFaceName[LF_FACESIZE]; } LOGFONT; Hai trư ng u trong c u trúc LOGFONT tính theo ơn v logic, do ó ph thu c vào hi n th . Trư ng lfHeight là chi u cao c a ký t , nh n giá tr m c nh c a font n u b ng ch 0. N u lfHeight âm, Windows xác nh kích c font qua giá tr tuy t i g n nh t. Giá tr dương c a lfHeight x p x b ng giá tr tmHeight tương ng trong c u trúc TEXTMETRICS. Trư ng lfWidth xác nh r ng ký t . Trong trư ng h p lfWidth b ng 0, Windows s ch n font tương ng d a vào chi u cao lfHeight. Giá tr lfWidth khác 0 thư ng ư c s d ng cho các font TrueType (không tương thích cho các font vector). Trư ng này tương ương trư ng tmAveCharWidth trong c u trúc TEXTMETRICS. Hai trư ng ti p theo xác nh hư ng hi n th c a các ký t trong chu i. Trư ng lfEscapement xác nh góc l ch gi a ư ng cơ s (base line) và tr c x c a thi t b . Giá tr nh p vào là m t b i s c a 10. Chu i xu t theo hư ng m c nh (trái sang ph i), hư ng lên, t ph i sang trái, và hư ng xu ng n u giá tr l n lư t là 0, 900, 1800, và 2700. Trư ng lfOrientation xác nh hư ng ư ng cơ s c a t ng ký t so v i tr c x. Giá tr ư c xác nh tương t lfEscapement. N u ng d ng g i hàm trong Windows NT, v i ch h a là GM_ADVANCED, giá tr lfEscapement ư c xác nh c l p v i lfOrientation. Trong các trư ng h p khác, hai giá tr này ph i ư c thi t l p như nhau. Ví d sau th hi n vi c xu t m t chu i quanh tâm vùng làm vi c c a c a s b ng cách thay i giá tr c a trư ng lfEscapement và lfOrientation t ng 10 .
RECT rc; int angle; HFONT hfnt, hfntPrev; LPSTR lpszRotate = "String to be rotated."; // C p phát vùng nh cho c u trúc LOGFONT.

ng d ng

Trang 141

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
PLOGFONT plf=(PLOGFONT)LocalAlloc(LPTR, sizeof(LOGFONT)); // Xác nh tên và m nh t c a font.

lstrcpy(plf->lfFaceName, "Arial"); plf->lfWeight = FW_NORMAL; // Thu nh n kích thư c c a vùng làm vi c c a s GetClientRect(hwnd, &rc); // Thi t l p ch n n TRANSPARENT cho thao tác xu t văn b n. ng d ng .

SetBkMode(hdc, TRANSPARENT); // V chu i quay quanh tâm vùng làm vi c t ng 10 for (angle = 0; angle < 3600; angle += 100) { plf->lfEscapement = angle; hfnt = CreateFontIndirect(plf); hfntPrev = SelectObject(hdc, hfnt); TextOut(hdc, rc.right/2, rc.bottom/2, lpszRotate, lstrlen(lpszRotate)); SelectObject(hdc, hfntPrev); DeleteObject(hfnt); } // Chuy n ch hi n th v l i d ng OPAQUE. (36 l n).

SetBkMode(hdc, OPAQUE); // Gi i phóng vùng nh ã c p phát cho c u trúc LOGFONT.

LocalFree((LOCALHANDLE) plf);

Trư ng ti p theo là lfWeight xác nh m nh t c a ký t , có giá tr t 0 n 1000. Trong trư ng h p b ng 0, Windows s d ng giá tr m c nh. ti n dùng, ta dùng m t s macro sau :

Trang 142

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam Giá tr
0 100 200 200 300 400 400 500 600 600 700 800 800 900 900

____________________________________________________________________________________ Tên
FW_DONTCARE FW_THIN FW_EXTRALIGHT FW_ULTRALIGHT FW_LIGHT FW_NORMAL FW_REGULAR FW_MEDIUM FW_SEMIBOLD FW_DEMIBOLD FW_BOLD FW_EXTRABOLD FW_ULTRABOLD FW_HEAVY FW_BLACK

B ng 5.2 Macro xác

nh

m nh t lfWeight.

Các trư ng lfItalic, lfUnderline, lfStrikeOut xác ngang n u ư c thi t l p b ng TRUE.

nh font nghiêng, có g ch dư i, g ch

Trư ng lfCharSet xác nh t p ký t s d ng. Giá tr OEM_CHARSET xác nh t p ký t ph thu c h i u hành. Thông thư ng, ta s d ng DAFAULT_CHARSET (t p ký t m c nh). Vi c ch n t p ký t là r t quan tr ng, n u ng d ng s d ng font có t p ký t không xác nh, h th ng không th thông d ch chúng. Các trư ng còn l i khá ph c t p. Chúng ta không phân tích các giá tr c a chúng ây. Trư ng lfOutPrecision nh nghĩa chính xác (có th có) c a font th c t so v i font yêu c u. Trư ng lfClipPrecision xác nh cách th c các ký t b c t b khi n m ngoài vùng clipping. Trư ng lfQuality dùng cho font vector, xác nh cách th c GDI nh nghĩa chính xác c a font logic so v i font v t lý. Trư ng lfPitchAndFamily xác nh h font ch . Trư ng lfFaceName xác nh tên ki u font. Sau khi ã ch n font cho DC, ta c n bi t các c trưng c a font hi n t i dùng cho vi c xu t văn b n b ng hàm GetTextMetrics. Ta có c u trúc TEXTMETRIC :

Trang 143

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ typedef struct tagTEXTMETRIC // tm { LONG tmHeight; LONG tmAscent; LONG tmDescent; LONG tmInternalLeading; LONG tmExternalLeading; LONG tmAveCharWidth; LONG tmMaxCharWidth; LONG tmWeight; LONG tmOverhang; LONG tmDigitizedAspectX; LONG tmDigitizedAspectY; BCHAR tmFirstChar; BCHAR tmLastChar; BCHAR tmDefaultChar; BCHAR tmBreakChar; BYTE tmItalic; BYTE tmUnderlined; BYTE tmStruckOut; BYTE tmPitchAndFamily; BYTE tmCharSet; } TEXTMETRIC; Trang 144

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ Các trư ng v kích thư c ư c tính theo ơn v logic, ph thu c vào ch hi n th . Trư ng tmHeight cho bi t chi u cao c a ký t , b ng t ng hai trư ng tmAscent (ph n trên ư ng cơ s ) và tmDescent (ph n dư i ư ng cơ s ). Trư ng tmInternalLeading xác nh kho ng cách bên trong ư ng biên xác nh b i tmHeight. Ngư i thi t k có th cho giá tr này b ng 0. Trư ng tmExternalLeading là kho ng cách Windows thêm vào gi a các dòng. Ngư i dùng cũng có th gán giá tr này b ng 0. Trư ng tmAveCharWidth cho bi t r ng trung bình c a các ký t ch thư ng. Trư ng tmMaxCharWidth cho bi t r ng ký t l n nh t tính theo ơn v logic. i v i b font fixed-pitch ( r ng không i), giá tr này b ng tmAveCharWidth. Trư ng tmOverhang cho bi t ph n m r ng (theo ơn v logic) mà Windows thêm vào font vector khi font nghiêng ho c tô m. Khi font nghiêng, giá tr tmAveCharWidth không thay i, b i vì chu i các ký t nghiêng v n có r ng b ng chu i ch thông thư ng. Trong trư ng h p ch m, Windows s m r ng t ng ký t . Khi ó, tmAveCharWidth c a ký t bình thư ng b ng tmAveCharWidth tr i l n tmOverhang c a ký t m. Trư ng tmDigitizedAspectX và tmDigitizedAspectY xác nh t l co c a font. Chúng ta cũng có th xác nh chúng b ng hàm GetDeviceCaps (xác nh các thông tin thi t b ) v i các thông s c a nIndex là LOGPIXELSX và LOGPIXELSY. int GetDeviceCaps(HDC hDC, int nIndex); Trư ng tmFirstChar xác nh giá tr ký t u tiên trong font, tmLastChar xác nh giá tr ký t cu i cùng. N u g i hàm GetTextMetricsW, giá tr này s l n hơn 255. Trư ng tmDefaultChar ch a giá tr Windows dùng hi n th các ký t không t n t i trong b font, thư ng là hình ch nh t. Trư ng tmBreakChar ư c dùng ng t t khi canh ch nh văn b n. N u không dùng các font c bi t, ví d font EBCDIC, giá tr này chính là giá tr ký t kho ng tr ng (mã b ng 32). Các trư ng tmWeight, tmItalic, tmUnderlined, tmStruckOut, tmCharSet và tmPitchAndFamily gi ng các trư ng lfWeight, lfItalic, lfUnderline, lfStrikeOut, lfCharSet và lfPitchAndFamily trong c u trúc LOGFONT.

5.3.5. S d ng h p tho i ch n font
ch n font, ta có th s d ng h p tho i font. u tiên, ng d ng kh i t o các giá tr trong c u trúc CHOOSEFONT, sau ó g i hàm ChooseFont hi n th h p tho i li t kê danh sách các font. Sau khi ngư i dùng ch n m t font có s n và ch n OK, hàm ChooseFont s kh i gán các giá tr tương ng vào c u trúc LOGFONT. ng d ng có th g i hàm CreateFontIndirect t o m t font logic d a trên các yêu c u c a ngư i dùng. Xét c u trúc CHOOSEFONT. typedef struct tagCHOOSEFONT // cf { Trang 145

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ DWORD lStructSize; HWND hwndOwner; HDC hDC; LPLOGFONT lpLogFont; INT iPointSize; DWORD Flags; DWORD rgbColors; LPARAM lCustData; LPCFHOOKPROC lpfnHook; LPCTSTR lpTemplateName; HINSTANCE hInstance; LPTSTR lpszStyle; WORD nFontType; WORD ___MISSING_ALIGNMENT__; INT nSizeMin; INT nSizeMax; } CHOOSEFONT; Trư ng lStructureSize xác nh s byte kích thư c c u trúc. Trư ng hwndOwner xác nh c a s ch a h p tho i ch n font. Trư ng này có th là m t handle c a s xác nh, ho c cũng có th b ng NULL n u h p tho i không xác nh c a s cha. Trư ng hDC là DC c a máy in có các font ư c li t kê trong h p tho i. Ch dùng trư ng hDC n u thi t l p trư ng Flags v i c CF_PRINTERFONTS ho c CF_BOTH; trong các trư ng h p khác, giá tr trư ng này b b qua. Trư ng lpLogFont tr n c u trúc LOGFONT. N u ta thi t l p trong trư ng Flags giá tr CF_INITTOLOGFONTSTRUCT, và kh i gán các giá tr cho nó, hàm ChooseFont s kh i t o h p tho i v i font g n gi ng nh t. Sau khi ta ch n OK óng h p tho i, hàm ChooseFont s thi t l p các giá tr c a c u trúc này d a trên các ch n l a tương ng. Trang 146

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ Trư ng iPointSize xác nh kích thư c font ư c ch n theo ơn v 1/10 i m. Giá tr này s ư c thi t l p sau khi ta óng h p tho i. Trư ng Flags là t p các bit c k t h p các giá tr sau :
CF_APPLY

ư c dùng

kh i t o h p tho i Font. Trư ng này có th

H p tho i có thêm button Apply. Ta ph i cung c p hàm hook x lý thông i p WM_COMMAND cho button này. H p tho i li t kê danh sách các font máy in và font màn hình. Trư ng hDC s xác nh DC liên quan n máy in. C này c n k t h p v i c CF_SCREENFONTS và CF_PRINTERFONTS. Xác nh hàm ChooseFont ch qu n lý và ch n l a trên font d ng TrueType. h p tho i th hi n các control cho phép ngư i dùng thi t l p ch g ch ngang, g ch dư i và ch n màu. N u c này ư c thi t l p, ta có th s d ng trư ng rgbColors xác nh màu font ban u. Ta cũng có th s d ng trư ng lfStrikeOut và lfUnderline c a c u trúc n trư ng lpLogFont xác nh LOGFONT tr các thi t l p ban u c a checkbox g ch ngang và g ch dư i ký t . Hàm ChooseFont s s d ng các trư ng này tr v giá tr ch n l a c a ngư i dùng. Cho phép th t c hook thi t l p trong trư ng lpfnHook. Ch ra trư ng hInstance và lpTemplateName xác nh h p tho i m u s d ng m c nh. Ch ra trư ng hInstance xác nh kh i d li u ch a h p ho i m u trư c khi n p. H th ng s b qua giá tr c a trư ng lpTemplateName. Xác nh hàm ChooseFont s ch ra l i n u ngư i dùng c ch n font ho c ki u không Trang 147

CF_BOTH

CF_TTONLY

CF_EFFECT

CF_ENABLEHOOK

CF_ENABLETEMPLATE

CF_ENABLETEMPLATEHANDLE

CF_FORCEFONTEXIST

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam t n t i.

____________________________________________________________________________________

CF_INITTOLOGFONTSTRUCT

Xác nh hàm ChooseFont ph i s d ng c u trúc LOGFONT qua trư ng lpLogFont kh i t o h p tho i. Xác nh hàm ChooseFont ch ch n font có kích thư c trong gi i h n t nSizeMin n nSizeMax. Gi ng c CF_NOVECTORFONTS. Khi s d ng c u trúc LOGFONT kh i t o các control c a h p tho i, trong ó combo box tên font không th hi n m t font nào ang ư c ch n c . Không cho phép ch n combo box Scrip. Khi c này ư c thi t l p, trư ng lfCharSet c a c u trúc LOGFONT ư c thi t l p v i giá tr DEFAULT_CHARSET khi hàm ChooseFont tr v . C này ch dùng khi kh i t o h p tho i. Khi s d ng c u trúc LOGFONT kh i t o các control c a h p tho i, ta không dùng ki u font nào c (combo box style). Khi s d ng c u trúc LOGFONT kh i t o các control c a h p tho i, ta không hi n th ch n l a ban u cho combo box kích thư c. Hàm ChooseFont không cho phép ch n l a font vector. H p tho i font ch li t kê các font vi t hư ng ngang. H p tho i ch li t kê các font h tr máy in liên quan n DC xác nh qua handle hDC. Ch nh hàm ChooseFont ch cho phép ch n l a các font có th co giãn (font vector, TrueType, …).

CF_LIMITSIZE

CF_NOOEMFONTS CF_NOFACESEL

CF_NOSCRIPTSEL

CF_NOSTYLESEL

CF_NOSIZESEL

CF_NOVECTORFONTS

CF_NOVERTFONTS

CF_PRINTERFONTS

CF_SCALABLEONLY

Trang 148

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam H p tho i ch li t kê các font màn hình ư c h th ng h tr . H p tho i s hi n th nút Help. Trư ng hwndOwner ph i xác nh window nh n thông i p HELPMSGSTRING mà h p tho i ưa ra khi ngư i dùng nh n button Help. Xác nh trư ng lpszStyle tr n vùng m ch a d li u ki u mà hàm ChooseFont dùng kh i t o combo box Font Style. Sau khi ngư i dùng óng h p tho i, hàm ChooseFont chép d li u ki u vào vùng m. Xác nh hàm ChooseFont cho phép ch n l a các font có s n cho máy in và màn hình. N u c này ư c thi t l p, c c CF_BOTH và CF_SCALABLEONLY cũng c n ư c thi t l p.
B ng 5.3 Các macro c Flags kh i t o h p tho i Font.

____________________________________________________________________________________
CF_SCREENFONTS

CF_SHOWHELP

CF_USESTYLE

CF_WYSIWYG

N u c CF_EFFECT ư c thi t l p, trư ng rgbColors s xác nh màu ch kh i t o. N u hàm ChooseFont th c hi n thành công, trư ng này s ch a giá tr RGB c a màu ch mà ngư i dùng ã ch n. Trư ng lCustData xác nh d li u ư c ng d ng nh nghĩa chuy n cho hàm hook gán b i giá tr lpfnHook. N u h th ng g i thông i p WM_INITDIALOG, giá tr lParam c a thông i p là con tr tr n c u trúc CHOOSEFONT xác nh khi h p tho i ư c t o. Trư ng lpfnHook tr n th t c hook CFHookProc x lý các thông i p c a h p tho i. s d ng giá tr này, c n ph i thi t l p c v i CF_ENABLEHOOK. Trư ng lpTemplateName tr n chu i (k t thúc b ng ký t NULL) xác nh tên tài nguyên h p tho i m u, liên quan v i trư ng hInstance. N u thi t l p c CF_ENABLETEMPLATEHANDLE, hInstance là handle c a i tư ng vùng nh ch a h p tho i m u. N u thi t l p c CF_ENABLETEMPLATE, hInstance xác nh module ch a h p tho i m u có tên trư ng lpTemplateName. Trư ng lpszStyle tr n vùng m ch a d li u ki u. N u thi t l p c CF_USESTYLE, hàm ChooseFont s s d ng d li u trong vùng m kh i t o combo box ki u font. Khi ngư i dùng óng h p tho i, hàm ChooseFont chép chu i trong combo box ki u font vào vùng m này. Trư ng nFontType xác nh d ng font tr v . Có th k t h p các giá tr sau : Trang 149

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam Font ch m. Giá tr này ư c l p l i trong trư ng lfWeight c a c u trúc LOGFONT, và b ng FW_BOLD. Font ch nghiêng. Giá tr này ư c l p l i trong trư ng lfItalic c a c u trúc LOGFONT. Font ch là font máy in. Font ch bình thư ng. Giá tr này ư c l p l i trong trư ng lfWeight c a c u trúc LOGFONT, và b ng FW_REGULAR . Font ch là font màn hình. Font d a theo giao di n GUI.
nh d ng font tr v .

____________________________________________________________________________________
BOLD_FONTTYPE

ITALIC_FONTTYPE

PRINTER_FONTTYPE REGULAR_FONTTYPE

SCREEN_FONTTYPE SIMULATED_FONTTYPE

B ng 5.4 Các macro xác

Trư ng nSizeMin và nSizeMax xác nh kích c ch nh nh t và l n nh t mà ngư i dùng có th ch n. Hàm ChooseFont ch nh n ra các giá tr này khi c CF_LIMITSIZE ư c thi t l p. Như ã trình bày trên, t o h p tho i font cho phép ngư i dùng ch n các thu c tính c a m t font logic, ta dùng hàm ChooseFont. BOOL ChooseFont(LPCHOOSEFONT lpcf); V i lpcf tr n c u trúc CHOOSEFONT ch a các thông tin dùng Khi hàm tr v , c u trúc này ch a các thông tin mà ngư i dùng ch n. kh i t o h p tho i.

N u ngư i dùng nh n nút OK trên h p tho i, hàm tr v giá tr khác 0. Ngư c l i, n u ch n Cancel ho c óng (close) h p tho i, giá tr tr v b ng 0. Ví d sau minh h a vi c ch n font logic s d ng h p tho i font.
HFONT FAR PASCAL MyCreateFont( void ) { CHOOSEFONT cf; LOGFONT lf;

Trang 150

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
HFONT hfont; // Kh i t o các trư ng trong c u trúc CHOOSEFONT. cf.lStructSize = sizeof(CHOOSEFONT); cf.hwndOwner = (HWND)NULL; cf.hDC = (HDC)NULL; cf.lpLogFont = &lf; cf.iPointSize = 0; cf.Flags = CF_SCREENFONTS; cf.rgbColors = RGB(0,0,0); cf.lCustData = 0L; cf.lpfnHook = (LPCFHOOKPROC)NULL; cf.lpTemplateName = (LPSTR)NULL; cf.hInstance = (HINSTANCE) NULL; cf.lpszStyle = (LPSTR)NULL; cf.nFontType = SCREEN_FONTTYPE; cf.nSizeMin = 0; cf.nSizeMax = 0; // Hi n th h p tho i font. ChooseFont(&cf); /* T o font logic d a trên các ch n l a c a ngư i dùng và tr v handle c a font logic */ hfont = CreateFontIndirect(cf.lpLogFont); return (hfont); }

5.3.6. Ví d v hi n th văn b n b ng các font khác nhau

Trang 151

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ Sau khi tìm hi u v vi c xu t n i dung văn b n và s d ng font ch b ng các hàm Win32® API, ta có th trình bày văn b n m t cách linh ng hơn. Ph n này ưa ra ví d xu t m t chu i văn b n theo các font khác nhau trên cùng m t dòng. M t trong các cách trình bày m t dòng văn b n v i nhi u font ch khác nhau là s d ng hàm GetTextExtentPoint32 sau m i l n g i hàm TextOut và c ng chi u dài nh n ư c vào v trí hi n th hi n t i. Ví d sau xu t câu "This is a sample string", s d ng ch m vi t "This is a", ch nghiêng vi t "sample", và tr l i ch m vi t “string.". Sau khi xu t xong, chương trình ph c h i l i d ng font m c nh.
int XIncrement; int YStart; TEXTMETRIC tm; HFONT hfntDefault, hfntItalic, hfntBold; SIZE sz; LPSTR lpszString1 = "This is a "; LPSTR lpszString2 = "sample "; LPSTR lpszString3 = "string."; /* T o font ch m và nghiêng (hàm này không vi t ây) */

hfntItalic = MyCreateFont(); hfntBold = MyCreateFont(); /* Ch n font ch XIncrement = 10; YStart = 50; hfntDefault = SelectObject(hdc, hfntBold); TextOut(hdc, XIncrement, YStart, lpszString1, lstrlen(lpszString1)); /* Tính dài c a chu i chu i ti p theo */ u tiên và c ng giá tr này vào giá tr XIncrement th c hi n thao tác xu t m và vi t chu i t i v trí xác nh b i c p tham s (XIncrement, YStart) */

GetTextExtentPoint32(hdc, lpszString1, lstrlen(lpszString1), &sz); XIncrement += sz.cx;

Trang 152

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
/* Xác nh l n ph n m r ng ký t qua c u trúc TEXTMETRIC và tr b t XIncrement. ( i u này ch c n thi t cho font vector) */ GetTextMetrics(hdc, &tm); XIncrement -= tm.tmOverhang; /* Ch n font nghiêng và vi t chu i th hai b t hfntBold = SelectObject(hdc, hfntItalic); GetTextMetrics(hdc, &tm); XIncrement -= tm.tmOverhang; TextOut(hdc, XIncrement, YStart, lpszString2, lstrlen(lpszString2)); /* Tính dài c a chu i chu i ti p theo */ u tiên và c ng giá tr này vào giá tr XIncrement th c hi n thao tác xu t u t i v trí (XIncrement, YStart) */

GetTextExtentPoint32(hdc, lpszString2, lstrlen(lpszString2), &sz); XIncrement += sz.cx; /* Ch n l i font ch m và vi t chu i th ba b t u t i v trí (XIncrement, YStart) */

SelectObject(hdc, hfntBold); TextOut(hdc, XIncrement-tm.tmOverhang, YStart, lpszString3, lstrlen(lpszString3)); /* Ch n l i font ban u */

SelectObject(hdc, hfntDefault); /* Xoá các i tư ng font ch */

DeleteObject(hfntItalic); DeleteObject(hfntBold);

Trong ví d trên, ta s d ng hàm GetTextExtentPoint32 c a chu i văn b n.

nh n chi u dài và chi u cao

BOOL GetTextExtentPoint32(HDC hDC, LPCTSTR lpString, int cbString, LPSIZE lpSize); Trong ó hDC là handle c a DC, lpString tr n chu i văn b n có chi u dài xác nh b i cbString. Và lpSize tr n c u trúc SIZE ch a kích thư c c a chu i ký t c n xác nh. Trang 153

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ typedef struct tagSIZE { LONG cx; LONG cy; } SIZE; C u trúc trên xác bi n cx và cy. nh chi u r ng và chi u cao c a m t hình ch nh t l n lư t qua hai

N u th c hi n thành công, hàm tr v giá tr khác 0. Ngư c l i, giá tr tr v b ng 0.

Chương 6 H A VÀ CÁC
Trang 154

I TƯ NG GDI

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________

6.1. M

U

Windows cung c p m t tính năng r t c s c, ó là kh năng h a c l p thi t b ư c xây d ng trên k thu t GDI (giao di n giao ti p v i các thi t b h a khác nhau). GDI là thư vi n h a c a Windows, cung c p t t c hàm ph c v cho các thao tác k t xu t hình nh và văn b n ra thi t b . GDI có th v ra nhi u lo i thi t b khác nhau: • • • Màn hình Máy in Máy v

GDI có trách nhi m giao ti p và k t xu t các yêu c u mà ngư i dùng chuy n cho nó n úng thi t b ích. V cơ b n, nó giao ti p v i các trình i u khi n thi t b (các t p tin .drv), th t ra các trình i u khi n thi t b cũng là m t giao di n do Windows ưa ra, do ó trách nhi m n ng n không th t s thu c v GDI c a Windows mà là c a các nhà s n xu t thi t b ph n c ng, h bu c ph i cung c p trình i u khi n theo giao di n này n u mu n bán ư c s n ph m cho ngư i dùng Windows. Như v y, ngư i l p trình không c n quan tâm n vi c i u khi n tr c ti p thi t b xu t mà ch c n quan tâm n thư vi n hàm GDI. Chương này s trình bày các khái ni m cơ s v GDI như device context, các hàm GDI cơ s v và tô, các hàm n p và zoom nh bitmap. Ph n cu i chương s trình bày cách l y v handle device context c a máy in và m t s hàm cơ s s d ng cho vi c i u khi n in n. Tóm l i, Windows cung c p kh năng s d ng cùng m t hàm khác nhau. i u này làm cho chương trình c l p v i thi t b . k t xu t ra nhi u thi t b

6.2. DEVICE CONTEXT
Device context là m t thi t b xu t logic, liên k t v i m t thi t b xu t v t lý c th . Windows không cho phép chúng ta k t xu t tr c ti p ra thi t b v t lý mà ph i thông qua handle c a device context. Handle device context là m t s nguyên không d u ư c Windows c p như m t nh danh c a device context. Ví d 1 : Xu t dòng ch "Hello Windows 2000" ra màn hình
HDC hDC; /* L y device context c a c a s */ hDC=GetDC(hWnd); /* Xu t dòng ch "Hello Windows 2000" ra c a s t i v trí (20,20) */

Trang 155

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
TextOut(hDC, 20, 20, "Hello Windows 2000", 18); /*Gi i phóng Device Context */ RealeaseDC(hWnd, hDC);

Ví d 2 : V hình ch nh t
HDC hDC; HPEN hPen, oldHPen; /* L y v device context c a c a s */ hDC=GetDC(hWnd); /* T o bút v m i v i nét li n, dày 5, màu xanh */

hPen=CreatePen(PS_SOLID, 5, RGB(0, 0, 255)); /* Ch n bút v hi n hành là bút v m i và lưu l i bút v cũ */ oldHPen=(HPEN)SelectObject(hDC, hPen); /* V hình ch nh t */ Rectangle(hDC, 20, 20, 100, 100); /* Restore l i bút v cũ */ SelectObject(hDC, oldHPen); /* Gi i phóng bút v DeleteObject(hPen); /* Gi i phóng device context */ ReleaseDC(hWnd, hDC); ã t o ra */

6.2.1. Thao tác l y v và gi i phóng Device Context
Có 3 cách nh n v và gi i phóng m t Device Context :

S d ng hàm BeginPaint và EndPaint khi x lý thông i p WM_PAINT:
hDC = BeginPaint(hWnd, &ps);

Trang 156

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
// X lý ………… EndPaint(hWnd, &ps);

Bi n ps là m t c u trúc ki u PAINTSTRUCT. Dùng hàm GetDC và ReleaseDC khi x lý các thông i p khác WM_PAINT:
hDC = GetDC(hWnd); //X lý ………… ReleaseDC(hWnd, hDC);

Dùng hàm GetWindowDC và ReleaseDC :
hDC = GetWindowDC(hWnd); // X lý ………… ReleaseDC(hWnd, hDC);

Lưu ý : Các hàm GetDC và BeginPaint tr v device context cho vùng client c a c a s , riêng hàm GetWindowDC tr v device context c a toàn b c a s k c thanh tiêu , menu, thanh cu n… và t t nhiên là c vùng client. v ra ngoài vùng làm vi c (client area), ph i ch n thông i p WM_NCPAINT( NC: None Client). Ngoài ra, còn có th nh n v device context c a toàn màn hình b ng hàm: hDC = CreateDC( "DISPLAY", NULL, NULL, NULL);

6.2.2. T o l p và gi i phóng memory device context
Memory device context(MDC)là m t device context o không g n v i m t thi t b xu t c th nào. Mu n k t qu k t xu t ra thi t b v t lý ta ph i chép MDC lên m t device context th t s (device context có liên k t v i thi t b v t lý). MDC thư ng ư c dùng như m t device context trung gian v trư c khi th c s xu t ra thi t b , nh m gi m s ch p gi t n u thi t b xu t là window hay màn hình. t o MDC tương thích v i m t hDC c th , s d ng hàm CreateCompatibleDC: HDC hMemDC; hMemDC = CreateCompatibleDC(hDC); ơn gi n hơn, có th tương thích v i màn hình. t NULL vào v trí hDC, Windows s t o m t device context

Trang 157

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ H y MDC b ng hàm DeleteDC. MDC có b m t hi n th như m t thi t b th t. Tuy nhiên, b m t hi n th này lúc u r t nh , ch là m t pixel ơn s c. Không th làm gì v i m t b m t hi n th ch g m 1 bit như v y. Do ó c n làm cho b m t hi n th này r ng hơn b ng cách ch n m t i tư ng bitmap GDI vào MDC: SelectObject(hMemDC, hBitmap); th Ch có th ch n ư c. Sau khi ch n m t th t s . Sau khi ư c hoàn t t trong MDC, nh ư c ưa ra device context th t s b ng hàm BitBlt: BitBlt(hDC, xDest, yDest, nWidth, nHeight, hMemDC, xSource, ySource); Ví d : Chu n b nh trư c khi ưa ra màn hình, tránh gây ch p màn hình trong thông i p WM_PAINT.
case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // L y v kích thư c vùng client c a c a s hi n hành RECT rect; GetClientRect(hWnd, &rect); // T o MDC tương thích v i DC c a c a s HDC hMemDC; hMemDC = CreateCompatibleDC(hdc); // Ch n m t i tư ng bitmap m r ng vùng hi n th cho MDC

i tư ng bitmap vào MDC, không th ch n vào m t device context c i tư ng bitmap cho MDC, có th dùng MDC như m t device context

HBITMAP bitmap,oBitmap; bitmap = CreateCompatibleBitmap(hdc,rect.right,rect.bottom); oBitmap = (HBITMAP)SelectObject(hMemDC,bitmap);

Trang 158

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
// V l i n n MDC FillRect(hMemDC, &rect, HBRUSH (GetBkColor(hMemDC))); // Xu t hình nh, text ra MDC SetPixel(hMemDC, 0, 0, RGB(255,0,0)); MoveToEx(hMemDC, 50, 50, NULL); LineTo(hMemDC, 100, 100); Rectangle(hMemDC, 10, 10, 100, 100); TextOut(hMemDC, 15 ,15, "Testing MDC", 11); If (!BitBlt(hdc, 0, 0, rect.right, rect.bottom, hMemDC, 0, 0, SRCCOPY)) MessageBox(hWnd, "Failed to transfer bit block", "Error",MB_OK); // Ph c h i l i bitmap cũ cho MDC SelectObject(hMemDC, oBitmap); // Gi i phóng MDC, bitmap ã t o DeleteDC(hMemDC); DeleteObject(bitmap); EndPaint(hWnd, &ps); break;

6.3. M T S

HÀM

H A CƠ S

S d ng các hàm h a cơ s , ta có th trình bày các i tư ng văn b n, hình nh … trên ng d ng. G m các nhóm hàm v văn b n (text), bút v , mi n tô, và nh bitmap. Các hàm v văn b n ã ư c trình bày trong chương trư c. hàm còn l i. ây s trình bày các nhóm

6.3.1. Nhóm hàm v
COLORREF GetPixel(HDC hDC, int nXPos, int nYPos);

Trang 159

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ L y v giá tr màu t i v trí (nXPos, nYPos) c a hDC, tr v -1 n u i m này n m ngoài vùng hi n th . COLORREF SetPixel(HDC hDC, int nXPos, int nYPos, COLORREF clrRef); V m t i m màu clrRef t i v trí (nXPos, nYPos) lên hDC. Giá tr tr v là màu c a i m (nXPos, nYPos) ho c -1 n u i m này n m ngoài vùng hi n th . DWORD MoveToEx(HDC hDC, int x, int y); nt a Di chuy n bút v LOWORD, y = HIWORD. (x, y) trên hDC. Giá tr tr v là t a cũ c a bút v , x =

BOOL LineTo(HDC hDC, int xEnd, int yEnd); V o n th ng t v trí hi n hành n u thành công, FALSE n u th t b i. n v trí (xEnd, yEnd) trên hDC. Hàm tr v TRUE

BOOL Polyline(HDC hDC, const POINT FAR *lpPoints, int nPoints); các V ư ng g p khúc lên hDC b ng các o n th ng liên ti p, s nh là nPoints v i t a nh ư c xác nh trong lpPoints. Hàm tr v TRUE n u thành công, FALSE n u th t b i. BOOL Polygon(HDC hDC, const POINT FAR *lpPoints, int nPoints); V a giác có nPoints nh, t a các TRUE n u thành công, FALSE n u th t b i. nh ư c xác nh b i lpPoints. Hàm tr v

BOOL Rectangle(HDC hDC, int left, int top, int right, int bottom); V hình ch nh t có t a là left, top, right, bottom lên hDC.

HPEN CreatePen(int penStyle, int penWidth, COLORREF penColor); T o bút v có ki u penStyle, dày nét v là penWidth, màu penColor. Hàm tr v handle c a bút v n u thành công và tr v NULL n u th t b i. Các giá tr c a penStyle như sau :
Giá tr PS_SOLID PS_DASH PS_DOT Gi i thích

Trang 160

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
PS_DASHDOT PS_DASHDOTDOT PS_NULL PS_INSIDEFRAME B ng 6.1 Các ki u bút v penStyle Không hi n th

Ví d : T o bút v m i và dùng bút v này v m t s
HDC hDC; POINT PointArr[3]; HPEN hPen, hOldPen; hDC = GetDC(hWnd); PointArr[0].x = 50; PointArr[0].y = 10; PointArr[1].x = 250; PointArr[1].y = 50; PointArr[2].x = 125; PointArr[2].y = 130; // V m t ư ng g p khúc b ng Pen hi n hành Polyline(hDC, PointArr, 3); //T o Pen m i có nét li n, dày 1, màu xanh

ư ng cơ s .

hPen = (HPEN)CreatePen(PS_SOLID, 1, RGB(0, 0, 255)); //Ch n bút v m i cho hDC c a window hOldPen = SelectObject(hDC, hPen); //V ư ng th ng v i bút v m i

MoveToEx(hDC, 100, 100, NULL);

Trang 161

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
LineTo(hDC, 200, 150); //Tr l i bút v cũ cho hDC SelectObject(hDC, hOldPen); //Xoá bút v m i t o và gi i phóng hDC DeleteObject(hPen); ReleaseDC(hWnd, hDC);

6.3.2. Nhóm hàm mi n
HBRUSH CreateSolidBrush(COLORREF cRef); T o m u tô c v i màu cRef.

HBRUSH CreateHatchBrush(int bStyle, COLORREF cRef); T o m u tô d ng lư i ki u bStyle v i màu cRef. Các ki u bStyle : HS_HORIZONTAL HS_VERTICAL HS_FDIAGONAL HS_BDIAGONAL HS_CROSS HS_DIAGCROSS BOOL FloodFill(HDC hDC, int xStart, int yStart, COLORREF cRef); Tô màu m t vùng kín, màu ư ng biên là cRef. BOOL ExtFloodFill(HDC hDC, int xStart, int yStart, COLORREF cRef, UINT fillStyle); Tô màu m t vùng kín, fillStyle quy t nh cách tô :

o FLOODFILLBORDER : Tô màu vùng có màu ư ng biên là cRef. Trang 162

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ o FLOODFILLSURFACE : Tô vùng có màu cRef. Ví d : S d ng các m u có s n và t o các m u tô m i
HDC hDC; HPEN hPen; HBRUSH hBrush, hOldBrush; hDC = GetDC(hWnd); //V hai hình ch nh t v i bút v Black hPen = (HPEN)GetStockObject(BLACK_PEN); SelectObject(hDC, hPen); Rectangle(hDC, 10, 10, 50, 50); Rectangle(hDC, 100, 100, 200, 200); // Dùng m t trong các m u tô có s n tô hình

tô.

hBrush = (HBRUSH)GetStockObject(GRAY_BRUSH); SelectObject(hDC, hBrush); FloodFill(hDC, 30, 30, RGB(0,0,255)); // T o m u tô m i tô hình th hai

hBrush = (HBRUSH)CreateHatchBrush(HS_DIAGCROSS, RGB(0, 255, 255)); hOldBrush = (HBRUSH)SelectObject(hDC, hBrush); FloodFill(hDC, 150, 150, RGB(0, 0, 0)); SelectObject(hDC, hOldBrush); //Xóa m u tô và gi i phóng hDC DeleteObject(hBrush); ReleaseDC(hWnd, hDC);

6.3.3. Nhóm hàm bitmap

Trang 163

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ 6.3.3.1. N p nh Có hai cách n p nh bitmap : N p t bitmap resource trong chương trình : HBITMAP LoadBitmap(HINSTANCE hInstance, LPCTSTR lpBitmapName); is u tiên hInstance là handle th hi n c a module ch a bitmap resource, có th là NULL n u bitmap mu n n p là m t bitmap h th ng. ó là các bitmap nh s d ng cho các thành ph n giao di n chương trình như close box và các d u check, các nh danh b t u v i ti p u ng OBM. i s th hai có th s d ng macro MAKEINTRESOURCE n u bitmap k t h p v i m t nh danh ki u nguyên, ho c là chu i tên bitmap resource. Sau khi s d ng, dùng hàm DeleteObject gi i phóng handle ang tham chi u n bitmap ó. Ví d : N p bitmap resource, có s d ng MDC
// L y v kích thư c vùng client c a c a s RECT rect; GetClientRect(hWnd, &rect); // L y v handle device context c a c a s HDC hdc; hdc = GetDC(hWnd); //T o MDC tương thích v i hDC c a c a s HDC hMemDC; hMemDC = CreateCompatibleDC(hdc); HBITMAP hNewBmp,hOldBmp; // N p bitmap resource có ID là IDB_CUB hNewBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_CUB)); if(hNewBmp) { //Gán bitmap m i cho MDC hOldBmp = (HBITMAP)SelectObject(hMemDC,hNewBmp);

tránh gây ch p màn hình.

Trang 164

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
//Copy bitmap t MDC sang DC BitBlt(hdc, 0, 0, rect.right, rect.bottom, hMemDC, 0, 0, SRCCOPY); } //Ph c h i l i bitmap cũ cho MDC SelectObject(hMemDC, hOldBmp); //Gi i phóng bitmap v a t o và MDC, hdc DeleteObject(hNewBmp); DeleteDC(hMemDC); ReleaseDC(hdc);

N p t file bitmap c a Windows(*.bmp) : *B ng màu(Color Palette): B ng màu trong Windows GDI là m t khái ni m gi ng như b ng màu th t s c a h a sĩ, nó g m các ô màu(palette entry) v i thông tin c th v m t s c . qu n lý vi c th hi n màu trên các c a s , Windows s d ng các b ng màu. Thông thư ng các c a s dùng b ng màu h th ng th hi n thông tin. Tuy nhiên, trong nhi u trư ng h p b ng màu h th ng không phù h p v i nhu c u, khi ó ta c n thay m t s màu trong b ng màu h th ng b ng các màu phù h p hơn.

Trong th c t , Windows cho phép m i c a s dùng m t b ng màu khác nhau v i i u ki n s lư ng màu trong b ng màu ó không ư c vư t quá s màu t i a cho phép c a thi t b hi n th . Khi m t c a s nh n s quan tâm (focus), Windows s th hi n d li u trong c a s ó v i s màu t i a cho phép c a b ng màu tương ng, nh ng màu còn l i trong palette s ư c th hi n b ng nh ng màu g n gi ng nh t. i v i nh ng c a s không active, d li u s ư c th hi n b ng nh ng màu g n gi ng nh t trong b ng màu h th ng.

Hình 6.2 Cách th hi n màu s d ng palette.

Ví d v cách th hi n màu s d ng palette: o B ng màu h th ng có 12 giá tr màu. Trang 165

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ o B ng màu 1 dùng cho c a s 1. C a s 1 ang active nên các màu c a b ng màu 1 ư c ánh x tr c ti p vào b ng màu h th ng. o B ng màu 2 dùng cho c a s 2. C a s 2 không active nên các màu 0,2,4,5,6 ư c ánh x vào các v trí còn tr ng trên b ng màu h th ng; các màu còn l i ư c ánh x vào nh ng màu g n gi ng nh t c a b ng màu h th ng. *C u trúc file bitmap : File bitmap g m 2 ph n: ph n header và ph n d li u nh.

Hình 6.3 C u trúc file bitmap.

o C u trúc BITMAPFILEHEADER
Tên trư ng Kích thư c Ý nghĩa

bfType bfSize bfReserved1 bfReserved2 bfOffBits

2 bytes(WORD) 4 bytes(DWORD) 2 bytes(WORD) 2 bytes(WORD) 4 bytes(DWORD)

Lo i file(=BM) Kích thư c file(bytes) Không dùng(=0) Không dùng(=0) Kích thư c c a ph n BitmapHeader (byte)

o C u trúc BITMAPINFO
Tên trư ng Ki u Ý nghĩa

bmiHeader bmiColors

BITMAPINFOHEADER RGBQUAD*

Các thông s

nh bitmap

B ng màu c a nh.

o C u trúc BITMAPINFOHEADER
Tên trư ng Ki u Ý nghĩa

biSize

DWORD

Kích thư c ph n BITMAPINFO(=40 bytes)

Trang 166

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam Chi u r ng bitmap(theo ơn v pixel) Chi u cao bitmap(theo ơn v pixel) S plane. Luôn = 1. S bit dùng lưu giá tr 1 i m nh.

____________________________________________________________________________________ biWidth biHeight biPlanes biBitCount LONG LONG WORD WORD

= 1: nh tr ng en = 4: nh 16 màu = 8: nh 256 màu =16: nh 16 bits =24: nh 24 bits Giá tr này cho bi t s màu có trong b ng màu bmiColors. biCompression DWORD Hình th c nén c a d li u nh: - BI_RGB: nh không nén - BI_RLE8: nén theo hình th c RLE cho nh 8 bits/pixel - BI_RLE4: nén theo hình th c RLE cho nh 4 bits/pixel biSizeImage biXPelsPerMeter biYPelsPerMeter biClrUsed biClrImportant DWORD LONG LONG DWORD DWORD Kích thư c c a nh( ơn v byte). Trư ng h p biCompression=BI_RGB thì giá tr này có th = 0. phân gi i (DPI/m) theo phương ngang. Dùng trong trư ng h p nh quét t scanner. phân gi i (DPI/m) theo phương d c. Dùng trong trư ng h p nh quét t scanner. S màu th c s ư c dùng. N u = 0 thì có nghĩa là dùng t t c màu trong b ng màu. S lư ng màu quan tr ng dùng trong vi c hi n th nh. N u = 0 htì dùng t t c màu trong b ng màu.

Trang 167

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ o C u trúc RGBQUAD bmiColors là m t m ng ki u RGBQUAD, ch a các giá tr màu dùng cho nh, ây chính là b ng màu c a nh. S lư ng ph n t c a bmiColors b ng s màu c a nh. bmiColors ch dùng cho nh en tr ng, 16 màu và 256 màu; khi ó ph n d li u nh cho m i pixel ch là các index n 1 v trí trong b ng màu này. i v i nh 16 bits và 24 bits màu, giá tr bmiColors=NULL, b ng màu không ư c s d ng n a. Trong trư ng h p này, n u nh là 16 bits thì m i pixel s ư c bi u di n b ng 1 WORD trong ph n d li u nh, 5 bits th p nh t s lưu giá tr màu Blue, 5 bits k s lưu giá tr màu Green, và 5 bits sau cùng lưu giá tr màu Red, bit cao nh t không ư c s d ng (Lý do là nh dùng 16 bits bi u di n RGB, ta chia u cho 3 s c nên m i s c R, G, B s có 5 bits bi u di n và dư ra 1 bit). nh 24 bits thì dùng 3 bytes bi u di n cho 3 s c RGB cho m i pixel trong ph n d li u nh.
Tên trư ng Ki u Ý nghĩa

rgbRed rgbGreen rgbBlue rgbReserved

BYTE BYTE BYTE BYTE

Giá tr thành ph n RED Giá tr thành ph n GREEN Giá tr thành ph n BLUE Không dùng

o C u trúc ph n d li u nh (BITMAPDATA): Như ã trình bày trên, ph n d li u t p tin bitmap dùng lưu giá tr index c a màu tương ng v i i m nh trong b ng màu i v i nh có s màu <=256. Các i m nh ư c lưu tu n t t trái sang ph i theo t ng dòng quét(scanline) theo th t t dư i lên. i v i nh <=256 màu, công th c sau: bi t giá tr màu (R,G,B) ng v i 1 i m nh (x,y), s d ng

(R,G,B) c a i m nh i = bmiColors[i] i v i nh 16 và 24 bits màu, ta không dùng palette và cách bi u di n c a ph n d li u ã ư c trình bày trên. Ph n d li u c a file bitmap có th ư c nén theo phương pháp RLE, tài li u này không trình bày chi ti t vào m i lo i nh nén, n u c n các b n có th tham kh o trong các giáo trình v x lý nh. *Cách t o bitmap t file *.bmp: o c header c a file, l y các thông tin v nh: r ng, cao, b ng màu…

Trang 168

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ o c d li u nh và gi i mã(n u c n thi t) vào b nh m. o T o palette màu t b ng màu l y ư c t file b ng hàm CreatePalette. o i palette màu cho thi t b xu t, s d ng các hàm SelectPalette, RealizePalette.

o T o l p bitmap handle b ng hàm CreateDIBitmap.
Hình 6.4 Sơ t ng quát quy trình n p nh bitmap

Ví d : N p nh bitmap t file.
void LoadBmp(char *bmpFN, HDC hdc, RECT rect) { try { int FHandle; BITMAPFILEHEADER bmpfh; HANDLE hBmp, hBuff; BITMAPINFO *BmpInfo; unsigned char *Buff; int Count,NumColor; long n, BytesPerLine; Count=0; SetCursor(LoadCursor(NULL, IDC_WAIT)); // M file bitmap c

if ((FHandle=open(bmpFN, O_BINARY|O_RDONLY))==-1) throw "Cannot open the file."; // c header file bitmap

read(FHandle, &bmpfh, sizeof(BITMAPFILEHEADER));

Trang 169

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
hBmp=GlobalAlloc(LMEM_MOVEABLE, bmpfh.bfOffBits-sizeof(BITMAPFILEHEADER)); BmpInfo=(BITMAPINFO*)GlobalLock(hBmp); // c ph n bitmap info và palette màu

read(FHandle, BmpInfo, bmpfh.bfOffBits-sizeof(BITMAPFILEHEADER)); if (BmpInfo->bmiHeader.biCompression != BI_RGB) throw "Program don't support compressed bitmap file."; // Xác nh s màu c a palette

NumColor=(int)pow(2,BmpInfo->bmiHeader.biBitCount); if(NumColor>256) throw "The program supports 256 colors bitmap file only."; // Xác nh s byte cho 1 scanline

BytesPerLine=(bmpfh.bfSize-bmpfh.bfOffBits)/ BmpInfo->bmiHeader.biHeight; /* C p nh t thông tin kích thư c nh trên BITMAPINFO (hi n t i = 0 n u nh không nén) */ BmpInfo->bmiHeader.biSizeImage=bmpfh.bfSize-bmpfh.bfOffBits; // c n i dung file bitmap

hBuff=GlobalAlloc(GMEM_MOVEABLE, BmpInfo->bmiHeader.biSizeImage); Buff=(unsigned char *)GlobalLock(hBuff); If (!Buff) throw "Cannot read the bitmap data."; // do { n = read(FHandle,Buff,BytesPerLine); Buff+=n; c t ng dòng trên file

Trang 170

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
Count++; }while (Count<BmpInfo->bmiHeader.biHeight); close(FHandle); GlobalUnlock(hBuff); GlobalUnlock(hBmp); SetCursor(LoadCursor(NULL, IDC_ARROW)); /*-----------------T o palette màu cho nh Bitmap---------------------*/ HANDLE hMemPal; LOGPALETTE far *logPal; HPALETTE hPal; int i; hMemPal=GlobalAlloc(LMEM_MOVEABLE, sizeof(LOGPALETTE)+NumColor*sizeof(PALETTEENTRY)); logPal=(LOGPALETTE far *)GlobalLock(hMemPal); // S m c trong Palette logPal->palNumEntries=NumColor; logPal->palVersion=0x300; //Gán các giá tr màu RGB cho nh ng Entry trong Palette for (i=0;i<NumColor;i++) //Error here { logPal->palPalEntry[i].peRed=BmpInfo->bmiColors[i].rgbRed; logPal->palPalEntry[i].peGreen = BmpInfo->bmiColors[i].rgbGreen; logPal->palPalEntry[i].peBlue = BmpInfo->bmiColors[i].rgbBlue;

Trang 171

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
logPal->palPalEntry[i].peFlags = PC_RESERVED; } // T o handle cho Palette hPal=CreatePalette(logPal); GlobalUnlock(hMemPal); GlobalFree(hMemPal); If (!hPal) throw "Cannot create palette."; /*------------------------Tao handle bmp file ------------------------------*/ SetCursor(LoadCursor(NULL, IDC_WAIT)); // Map palette vào hdc SelectPalette(hdc,hPal,FALSE); RealizePalette(hdc); BmpInfo=(BITMAPINFO *)LocalLock(hBmp); Buff=(unsigned char *)GlobalLock(hBuff); //T o bitmap hBmp=CreateDIBitmap(hdc,(BITMAPINFOHEADER *)BmpInfo, CBM_INIT, Buff, (BITMAPINFO *)BmpInfo,DIB_RGB_COLORS); GlobalUnlock(hBuff); GlobalUnlock(hBmp); GlobalFree(hBuff); GlobalFree(hBmp); SetCursor(LoadCursor(NULL, IDC_ARROW)); if(!hBmp) throw "Cannot create bitmap."; /*-----------------------Hi n th bitmap lên c a s ---------------------------*/ HDC hMemDC;

Trang 172

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
HANDLE OldBmp; // T o MDC hMemDC=CreateCompatibleDC(hdc); SelectPalette(hMemDC, hPal, FALSE); // Tr v palette h th ng UnrealizeObject(hPal); // Map l i palette RealizePalette(hdc); SelectPalette(hMemDC, hPal, FALSE); // Liên k t hMemDC v i nh bitmap OldBmp=SelectObject(hMemDC, hBmp); // Copy bitmap lên window BitBlt(hdc, 0, 0, rect.right, rect.bottom, hMemDC, 0, 0,SRCCOPY); // H y MDC SelectObject(hMemDC,OldBmp); DeleteDC(hMemDC); } catch(char *e) { MessageBox(NULL, e, "Error", MB_OK|MB_ICONERROR); } }

6.3.3.2. Zoom nh Thao tác zoom nh òi h i ph i có hai MDC, m t MDC ngu n MDC ích lưu nh ã ư c zoom t MDC ngu n. Trang 173 copy nh vào, m t

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam
t ng quát quy trình zoom nh bitmap

____________________________________________________________________________________
Hình 6.4 Sơ

Ví d : zoom nh bitmap l y t bitmap resource.
// L y v kích thư c vùng client c a c a s RECT rect; GetClientRect(hWnd, &rect); //L y v handle device context c a c a s HDC hdc; hdc = GetDC(hWnd); // T o 2 MDC tương thích v i DC c a c a s HDC hSourceMemDC, hDestMemDC; hSourceMemDC = CreateCompatibleDC(hdc); hDestMemDC = CreateCompatibleDC(hdc); //N p bitmap c n load va t o m t bitmap r ng tương thích hdc HBITMAP hBmp,hOldBmp,hBlankBmp,hOldBlankBmp; hBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_CUB)); hBlankBmp = CreateCompatibleBitmap(hdc,rect.right,rect.bottom); if(hBmp && hBlankBmp && hSourceMemDC && hDestMemDC) { // Ch n bitmap c n load cho MDC ngu n hOldBmp = (HBITMAP)SelectObject(hSourceMemDC, hBmp); // Ch n blank bitmap cho MDC ích hOldBlankBmp =(HBITMAP)SelectObject(hDestMemDC,hBlankBmp); // L y v thông tin c a nh BITMAP bmpInfo; GetObject(hBmp, sizeof(BITMAP),(BITMAP *)&bmpInfo);

Trang 174

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
// Zoom nh t MDC ngu n sang MDC ích StretchBlt(hDestMemDC, 0, 0, rect.right, rect.bottom,hSourceMemDC, 0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight, SRCCOPY); // Copy nh ã zoom t MDC ích lên hdc BitBlt(hdc, 0, 0, rect.right, rect.bottom, hDestMemDC, 0,0,SRCCOPY); } // Gi i phóng các bitmap handle, MDC handle SelectObject(hSourceMemDC, hOldBmp); DeleteObject(hBmp); SelectObject(hDestMemDC, hOldBlankBmp); DeleteObject(hBlankBmp); DeleteDC(hSourceMemDC); DeleteDC(hDestMemDC); ReleaseDC(hdc);

6.4. IN N
Trên Windows, các ng d ng không truy xu t tr c ti p máy in mà s dùng các hàm GDI v ra device context c a máy in. Do ó vi c in n trên Windows tr nên ơn gi n, tương t vi c v ra các h p tho i trên màn hình. V i cơ ch này, ngư i l p trình không c n quan tâm n vi c máy in ang s d ng là máy in hi u gì, lo i nào… Các Windows printer device driver s m nh n vi c chuy n d li u c n in sang d ng phù h p v i máy in hi n hành. Ti n trình in n trên Windows bao g m các bư c sau: L y v device context c a máy in c n in. G i yêu c u b t u vi c in n (STARTDOC). K t xu t d li u ra máy in(có th sang trang _ NEWFRAME n u c n). G i yêu c u k t thúc vi c in n(ENDDOC). Gi i phóng device context máy in.

6.4.1. L y v handle device context máy in

Trang 175

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ 6.4.1.1. S d ng file win.ini D a vào thông tin v máy in m c nh trong file win.ini. File win.ini lưu thông tin v máy in trong section [windows], entry DEVICE. Ví d : m t o n c a file win.ini ch a thông tin v máy in m c [windows] device = EpsonFX1050, Epson9, LPT1 ó là các thông tin v tên máy in, driver, và c ng giao ti p v i máy tính. M t s hàm chu n c ghi file win.ini c a Windows : nh.

DWORD GetProfileString(LPCTSTR lpAppName, LPCTSTR lpKeyName, LPCTSTR lpDefault, LPTSTR lpReturnedString, DWORD nSize); BOOL WriteProfileString(LPCTSTR lpAppName, LPCTSTR lpKeyName, LPCTSTR lpString); Ví d : In dòng ch ra máy in m c
void PrintStrWinInit(char *msg) { char prnInfo[200]; GetProfileString("windows", "device", "NoPrinter", prnInfo, 200); If ( strcmp(prnInfo, "NoPrinter") ) { char prnName[100], prnDriver[100], prnPort[100]; char seps[10]; char *token; strcpy(seps,","); token = strtok(prnInfo, seps); strcpy(prnName, token);

nh.

Trang 176

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
token=strtok(NULL, seps); strcpy(prnDriver, token); token=strtok(NULL, seps); strcpy(prnPort, token); HDC prnDC; prnDC=CreateDC(prnDriver, prnName, prnPort, NULL); if(prnDC) { StartDoc(prnDC, NULL); StartPage(prnDC); TextOut(prnDC, 100, 100, "Your message here:", 18); TextOut(prnDC, 100, 200, msg, strlen(msg)); TextOut(prnDC, 100, 300, "End of printing", 15); EndPage(prnDC); EndDoc(prnDC); DeleteDC(prnDC); } } }

6.4.1.2. S d ng h p tho i Print M t cách khác ơn gi n hơn l y v handle device context c a m t máy in b t kỳ thay vì máy in m c nh là s d ng h p tho i in chu n c a Windows. H p tho i in chu n ư c kích ho t b ng hàm PrintDlg (hàm này ư c nh nghĩa trong module COMMDLG.DLL), h p tho i này cho phép ngư i dùng thi t l p các thông s in n.

Trang 177

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________

Hình 6.4 H p tho i in

K t qu tr v c a hàm PrintDlg là m t handle device context c a máy in ã ch n. Ví d : In dòng ch ra máy in ư c ch n t h p tho i in chu n.
void PrintStrPrintDlg(char *msg) { PRINTDLG pd; ZeroMemory(&pd, sizeof(PRINTDLG)); pd.lStructSize = sizeof(PRINTDLG); pd.hwndOwner = GetFocus(); pd.Flags = PD_RETURNDC|PD_NOSELECTION; if(PrintDlg(&pd)) { StartDoc(pd.hDC, NULL); StartPage(pd.hDC); TextOut(pd.hDC, 100, 100, "Your message here:", 18);

Trang 178

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
TextOut(pd.hDC, 100, 200, msg, strlen(msg)); TextOut(pd.hDC, 100, 300, "End of printing", 15); EndPage(pd.hDC); EndDoc(pd.hDC); DeleteDC(pd.hDC); } }

6.4.2. Các hàm i u khi n in n
Hàm int StartDoc(hDC, lpDocInfo) Ý nghĩa

B t u tác v in n 1 tài li u trong file có tên lpDocInfo, hDC là handle printer device context. K t thúc tác v in n. H y tác v in hi n hành. B t u trang m i.

int EndDoc(hDC) int AbortDoc(hDC) int StartPage(hDC) int EndPage(hDC) int SetAbortDoc( hDC, MyAProc )

K t thúc 1 trang. Ch nh hàm (MyAProc) x lý trư ng h p ngư i dùng mu n ng t ngang tác v in.

B ng 6.2 Các hàm i u khi n in n

6.4.3. X lý l i khi in
Trong quá trình in b ng vi c s d ng các hàm i u khi n in n, n u các thao tác thành công thì luôn tr v giá tr l n hơn 0. N u có l i, dùng hàm DWORD GetLastError(VOID) Win2000 m i h tr hàm này). l y v mã l i (ch WinNT và

Trang 179

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________

Chương 7 QU N LÝ B
7.1. M U

NH

VÀ T P TIN

M t ti n trình thông thư ng ư c hi u là m t chương trình máy tính ang ư c thi hành. Quá trình th c thi các ti n trình g n li n v i vi c qu n lý và s d ng các tài nguyên trong máy tính, trong ó áng k nh t là qu n lý b nh chính và x lý h th ng lưu tr ph . Trong các h th ng máy tính hi n i, b nh chính là trung tâm c a các thao tác, x lý. B nh chính có th xem như m t m ng các ph n t ki u BYTE ho c WORD, ư c xác nh thông qua a ch c a chúng. M i chương trình ư c ánh x vào b nh chính trư c khi ư c thi hành và ư c h i u hành qu n lý thông qua t p l nh xác nh. Trong su t quá trình thi hành, các chương trình v i d li u truy xu t c a chúng luôn ư c t trong b nh chính. Nhưng b nh chính thì khá nh có th lưu gi m i d li u và chương trình, ngoài ra d li u s m t khi không còn ư c cung c p năng lư ng. Do ó, c n ph i s d ng h th ng lưu tr ph . Chương này trình bày các v n trên qua hai ph n sau : ph n 7.2 - Qu n lý b nh - trình bày cách th c Microsoft® Win32® API qu n lý các vùng nh thông qua các hàm c p phát, s d ng, và gi i phóng chúng; cách th c thao tác trên a ch vùng nh o và các trang nh . Ph n 7.3 - X lý t p tin - trình bày các hàm th c hi n các thao tác t o, x lý và h y t p tin, cũng như tìm hi u m t s v n liên quan n t p tin.

7.2. QU N LÝ B

NH

M i ti n trình trong Win32 u có m t vùng a ch o 32-bit cho phép nh v vùng nh n 4 GB. a ch o này không ph i là vùng nh v t lý th c t . Windows s d ng m t c u trúc d li u ánh x chuy n i a ch o thành vùng nh v t lý. Vùng a ch o c a m i ti n trình thư ng l n hơn r t nhi u so v i vùng nh v t lý th c s trên máy tính. Do ó, tăng vùng nh cho các ti n trình ang th c hi n, h th ng s d ng vùng nh tr ng trên ĩa. Vùng nh v t lý và vùng a ch o c a m i ti n trình ư c t ch c thành các trang, ph thu c vào h máy tính. Ví d , i v i máy tính h x86, m i trang có kích thư c là 4 KB.

Trang 180

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ tăng kh năng linh ng trong vi c qu n lý b nh , h th ng có th di chuy n các trang t b nh chính vào ĩa và ngư c l i. Các thao tác này ư c th c hi n ch b i h th ng, các ng d ng ch vi c g i các hàm c p phát và s d ng vùng a ch o. Thư vi n C chu n h tr các hàm c p phát và gi i phóng vùng nh như malloc, free, …, ho c trong C++ là new, delete, …. Th nhưng trong Windows 16 bits, các hàm này có th gây l i h th ng. Trong Win32, ta có th s d ng chúng an toàn do h th ng ch qu n lý b nh qua các trang v t lý mà không nh hư ng n a ch o. Hơn n a, Win32 cũng không phân bi t gi a con tr g n và con tr xa. M c dù v y, các hàm trên không th hi n các kh năng h tr c a vi c qu n lý b nh trong Win32. Chúng ta s làm quen v i các hàm Global và Local - s d ng t Windows 16 bits, và các hàm qu n lý vùng nh o khác.

7.2.1. Các hàm Global và Local
Các hàm toàn c c (global) và a phương (local) là các hàm heap Windows 16 bits. Tuy nhiên, qu n lý b nh trong Win32 cũng h tr các hàm này có th s d ng các chương trình, ho c source code c a các chương trình vi t cho Windows 16 bits. Các hàm toàn c c và a phương x lý ch m và ít ch c năng hơn các hàm qu n lý b nh m i thi t k cho Win32. Chúng ta s làm quen các hàm m i ph n sau. c p phát vùng nh cho m t ti n trình, ta có th s d ng hàm GlobalAlloc ho c LocalAlloc. Vi c qu n lý vùng nh trong Win32 không phân bi t hàm toàn c c hay c c b như trong Windows 16 bits. Do ó, không có s phân bi t gi a các i tư ng vùng nh ư c c p phát b i hai hàm trên. Thêm vào ó, vi c chuy n mô hình o n vùng nh 16 bits sang vùng a ch o 32 bits th c hi n m t s hàm toàn c c và a phương v i các ch n l a (options) không c n thi t ho c vô nghĩa. Ví d , vì c c p phát toàn c c và a phương u tr v a ch o 32 bits, do ó không xác nh d ng con tr g n ho c xa trong các hàm trên. Hai hàm này c p phát m t vùng nh theo kích thư c nBytes trong heap. Có prototype như sau : HGLOBAL GlobalAlloc(UINT uFlags, DWORD nBytes); HLOCAL LocalAlloc(UINT uFlags, UINT nBytes); Trong ó uFlags xác
Toàn c c GMEM_FIXED

nh cách th c c p phát vùng nh . Ta có b ng sau :
a phương LMEM_FIXED Ý nghĩa

C p phát vùng nh c nh. Giá tr tr v là m t con tr . C p phát vùng nh

GMEM_MOVEABLE

LMEM_MOVEABLE

Trang 181

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam không c nh. Trong Win32, kh i nh không bao gi di chuy n trong vùng nh v t lý, nhưng trong heap m c nh. Hàm tr v handle c a m t i tư ng b nh . Ta dùng hàm GlobalLock ho c LocalLock chuy n handle sang con tr vùng nh .

____________________________________________________________________________________

GMEM_ZEROINIT

LMEM_ZEROINIT

Kh i t o n i dung vùng nh v i giá tr 0.
GMEM_FIXED | GMEM_ZEROINIT GMEM_MOVEABLE | GMEM_ZEROINIT

GPTR GHND LPTR LHND

LMEM_FIXED | LMEM_ZEROINIT LMEM_MOVEABLE | LMEM_ZEROINIT

B ng 7.1 Các c s d ng trong các hàm GlobalAlloc và LocalAlloc

Chú ý : Không th s d ng giá tr GMEM_FIXED ng th i v i GMEM_MOVEABLE, ho c LMEM_FIXED ng th i v i LMEM_MOVEABLE. N u thành công, hàm tr v handle cho tr tr v là NULL. i tư ng vùng nh ư c c p phát. Ngư c l i, giá

Các i tư ng vùng nh ư c c p phát b ng hàm GlobalAlloc và LocalAlloc là các trang riêng, truy c p c-ghi b i chính ti n trình t o nó. Các ti n trình khác không th truy c p các i tư ng vùng nh này. Khi dùng cách th c c p phát GMEM_MOVEABLE ho c LMEM_MOVEABLE, ta nh n ư c handle vùng nh . s d ng vùng nh , ta dùng hàm GlobalLock ho c LocalLock : LPVOID GlobalLock(HGLOBAL hMem); LPVOID LocalLock(HLOCAL hMem); N u thành công hàm tr v con tr tr tr v là NULL. n byte u tiên trong kh i nh . Ngư c l i, giá tr

Trang 182

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ Khi khoá (lock) vùng nh , các kh i nh không th d ch chuy n trong b nh máy tính. Sau khi s d ng con tr vùng nh , c n m khoá (unlock) chúng, h th ng có th di chuy n và s d ng các vùng nh linh ng cho các ti n trình khác. Ta dùng hai hàm tương ng là GlobalUnlock và LocalUnlock. BOOL GlobalUnlock(HGLOBAL hMem); BOOL LocalUnlock(HLOCAL hMem); M i l n khoá vùng nh , bi n m tương ng tăng m t ơn v . M i l n m khoá, bi n m gi m m t. N u vùng nh còn khoá, hàm tr v giá tr khác 0, ngư c l i giá tr tr v là 0. Kích thư c th t s c a vùng nh ư c c p phát có th l n hơn kích thư c yêu c u (nBytes). xác nh s byte th t s ư c c p phát, ta dùng hàm GlobalSize và LocalSize. DWORD GlobalSize(HGLOBAL hMem); UINT LocalSize(HLOCAL hMem); N u thành công, hàm tr v s byte kích thư c vùng nh xác giá tr tr v là 0. nh b i hMem. Ngư c l i, c p phát thay i

Ngoài ra, ta có th s d ng hàm GlobalReAlloc và LocalReAlloc kích thư c ho c thu c tính vùng nh .

HGLOBAL GlobalReAlloc(HGLOBAL hMem, DWORD nBytes, UINT uFlags); HLOCAL LocalReAlloc(HLOCAL hMem, UINT nBytes, UINT nFlags); Trư ng nBytes xác nh kích thư c c p phát l i cho vùng nh hMem. Tuy nhiên, khi nFlags ch a GMEM_MODIFY (ho c LMEM_MODIFY), h th ng b qua giá tr này. Khi ó, hàm thay i các thu c tính c a vùng nh . xác nh handle c a vùng nh khi bi t con tr vùng nh , ta dùng hàm GlobalHandle và LocalHandle như sau : HGLOBAL GlobalHandle(LPCVOID pMem); HLOCAL LocalHandle(LPCVOID pMem); V i pMem là con tr tr n byte u tiên trong vùng nh . N u thành công, hàm tr v handle c n tìm. Ngư c l i, giá tr tr v là NULL. nh Sau khi s d ng xong, ta dùng hàm GlobalFree và LocalFree ã ư c c p phát. Trang 183 gi i phóng các vùng

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ HGLOBAL GlobalFree(HGLOBAL hMem); HLOCAL LocalFree(HLOCAL hMem); N u thành công, giá tr tr v là NULL. Ngư c l i, hàm tr v giá tr handle c a tư ng ban u. i

o n chương trình sau minh h a cách h th ng c p phát m t vùng nh v i kích thư c yêu c u là 3500 bytes. Sau ó gán các giá tr vùng nh b ng 0x3C.
HANDLE hMem; LPBYTE lpAddress; int i, nSizeMem; hMem = GlobalAlloc(GMEM_MOVEABLE, 3500); if(hMem != NULL) { /* Vùng nh có th l n hơn 3500 */ nSizeMem = GlobalSize(hMem); lpAddress = (LPBYTE)GlobalLock(hMem); if(Address != NULL) { for(i=0; i<nSizeMem; i++) lpAddress[i] = 0x3C; GlobalUnlock(hMem); /* … */ } /* N u không dùng n a thì g i hàm GlobalFree(hMem); */ }

Trang 184

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ o n chương trình ti p theo c p phát l i vùng nh trên v i kích thư c là 5000 bytes, kh i gán các giá tr là 0x00 :
… HANDLE hMemTmp; hMemTmp = GlobalReAlloc(hMem, 5000, GMEM_MOVEABLE|GMEM_ZEROINIT); if(hMemTmp != NULL) { hMem = hMemTmp; nSizeMem = GlobalSize(hMem); /* … */ } … /* Khi k t thúc s d ng, c n g i hàm GlobalFree(hMem); */

7.2.2 Các hàm Heap
Các hàm heap cho phép các ti n trình t o m t vùng heap riêng cho m t ho c m t s trang trong vùng a ch c a ti n trình ang th c hi n. Sau ó ti n trình có th s d ng m t t p các hàm khác nhau qu n lý vùng nh trong heap này. ây không có s phân bi t gi a vùng nh ư c c p phát b i hàm heap riêng hay dùng các hàm c p phát khác. u tiên hàm HeapCreate t o i tư ng heap cho m t ti n trình. Vùng nh heap này ch ư c dùng cho ti n trình này mà thôi, và không chia s cho các ti n trình khác, ngay c các ti n trình trong thư vi n liên k t ng DLL (dynamic-link library). HANDLE HeapCreate(DWORD flOptions, DWORD dwInitialSize, DWORD dwMaximumSize); Trư ng flOptions xác nh các thu c tính ư c ch n cho vùng heap m i ư c kh i t o. Có th là HEAP_GENERATE_ EXCEPTIONS và HEAP_NO_SERIALIZE. Trư ng dwInitialSize xác nh kích thư c kh i t o c a heap, ư c làm tròn cho các trang vùng nh . Trư ng dwMaximumSize xác nh vùng nh t i a có th c p phát cho ti n trình b ng hàm Trang 185

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ HeapAlloc ho c HeapReAlloc. Hàm tr v handle c a i tư ng heap n u thành công, ngư c l i tr v NULL. c p phát vùng nh l n HeapReAlloc. u, ta g i hàm HeapAlloc. N u mu n c p phát l i, dùng hàm

LPVOID HeapAlloc(HANDLE hHeap, DWORD dwFlags, DWORD dwBytes); Trư ng dwFlags có th là HEAP_GENERATE_ EXCEPTIONS, HEAP_NO_SERIALIZE, và HEAP_ZERO_ MEMORY. Trư ng dwBytes xác nh s bytes vùng heap ư c c p phát. N u thành công, hàm tr v con tr n vùng nh . N u th t b i, hàm tr v NULL n u dwFlags không thi t l p HEAP_ GENERATE_EXCEPTIONS. N u có thi t l p, giá tr tr v là STATUS_NO_MEMORY (không có s n vùng nh ho c l i vùng heap), ho c STATUS_ACCESS_VIOLATION (Do l i vùng heap ho c bi n không chính xác). LPVOID HeapReAlloc(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem, DWORD dwBytes); Trư ng lpMem tr n vùng nh c n c p phát l i. Vùng nh này ã ư c t o b ng hàm HeapAlloc ho c HeapReAlloc. Trư ng dwBytes xác 0x7FFF8. nh kích thư c vùng nh c n c p phát. Giá tr này ph i nh hơn

khoá và m khoá vùng nh heap, ta dùng hàm HeapLock và HeapUnlock. BOOL HeapLock(HANDLE hHeap); BOOL HeapUnlock(HANDLE hHeap); N u thành công, giá tr tr v khác 0. Ngư c l i, hàm tr v 0. xác nh kích thư c vùng heap, ta dùng hàm HeapSize.

DWORD HeapSize(HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem); Trong hàm này, dwFlags ch dùng v i HEAP_NO_ SERIALIZE. Các trư ng khác tương t các hàm khác. N u thành công, hàm tr v kích thư c vùng nh . N u th t b i, hàm tr v giá tr là 0xFFFFFFFF. Sau khi s d ng, ta gi i phóng vùng nh và h y HeapDestroy. i tư ng heap b ng hàm HeapFree và

BOOL HeapFree(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem);

Trang 186

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ BOOL HeapDestroy(HANDLE hHeap); Trong ó, trư ng dwFlags ư c nh nghĩa ch v i giá tr HEAP_NO_SERIALIZE. N u thành công, hai hàm này u tr v giá tr khác 0. Ngư c l i, giá tr tr v là 0. Chúng ta không minh h a các hàm s d ng b nh heap trong tài li u này.

7.2.3 Các hàm Virtual
Microsoft® Win32® API cung c p m t t p các hàm qu n lý b nh o cho phép m t ti n trình thao tác và xác nh các trang trong vùng a ch không gian o, g m các ch c năng sau : dành vùng không gian a ch o cho m t ti n trình. Vùng không gian dành không c p phát vùng lưu tr v t lý th t s , nhưng ngăn không cho các thao tác c p phát khác s d ng vùng nh này. Nó không nh hư ng n các ti n trình khác. Khi c n s d ng, ti n trình s c p phát vùng lưu tr v t lý cho không gian này. C p phát xác nh n chu i các trang dành trong không gian a ch o c a ti n trình có th s d ng vùng lưu tr v t lý (trong RAM ho c ĩa). Thi t l p các thu c tính c-ghi, ch c, ho c không ư c truy c p cho các trang ã xác nh n. i u này khác v i các hàm c p phát chu n luôn c p phát c p phát các trang v i thu c tính là c-ghi. Gi i phóng chu i các trang dành, s n vùng a ch o cho các thao tác c p phát c a ti n trình ang g i. Kh xác nh n các trang ã xác nh n b ng cách gi i phóng vùng lưu tr v t lý, s n cho các thao tác c p phát c a các ti n trình khác. Khoá m t ho c m t vài trang vùng nh ã xác nh n vào vùng nh v t lý (RAM) h th ng có th hoán chuy n các trang vào t p tin trang. Nh n thông tin v chu i các trang trong vùng a ch o c a ti n trình ang g i ho c c a m t ti n trình xác nh khác. Thay i các ch c năng b o v truy c p cho chu i xác nh các trang xác nh n trong vùng a ch o c a ti n trình ang g i ho c ti n trình xác nh khác. 7.2.3.1 C p phát vùng nh o c p phát

Các hàm qu n lý b nh o th c hi n các thao tác trên các trang vùng nh . các trang vùng nh o, ta dùng hàm VirtualAlloc, v i các ch c năng sau ây : dành m t hay nhi u trang tr ng. C p phát xác nh n m t hay nhi u trang dành. dành và c p phát xác nh n m t hay nhi u trang tr ng.

Chúng ta có th ch nh a ch u c a các trang dành hay c p phát, ho c cho h th ng t xác nh n a ch . Hàm s làm tròn a ch ch nh v i biên trang thích h p. Vùng nh ư c c p phát ư c kh i gán b ng 0, n u ta không thi t l p c MEM_RESET.

Trang 187

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ LPVOID VirtualAlloc(LPVOID lpAddress, DWORD dwSize, DWORD flAllocationType, DWORD flProtect); Trư ng lpAddress xác nh a ch b t u c a vùng c p phát. N u vùng nh ang dành, a ch ch nh ư c làm tròn n biên 64 KB k ti p. N u vùng nh ã dành và ang ư c xác nh n, a ch s ư c làm tròn n biên trang k . xác nh kích thư c c a trang, ta s d ng hàm GetSystemInfo. N u bi n này b ng NULL, h th ng t xác nh n a ch vùng nh c p phát. Trư ng dwSize xác nh s byte kích thư c vùng nh . N u lpAddress b ng NULL, giá tr này s ư c làm tròn n biên trang k . N u không, các trang c p phát là các trang ch a m t hay nhi u byte n m trong kho ng t lpAddress n lpAddress+dwSize. Nghĩa là, n u hai byte n m hai trang thì c hai trang ó u n m trong vùng c p phát. Trư ng flAllocationType xác
C MEM_COMMIT

nh d ng c p phát, có th k t h p t các c :
Ý nghĩa

C p phát vùng lưu tr v t lý trong b nh ho c ĩa. Các trang ã ư c c p phát xác nh n ho c kh c p phát u có th ư c c p phát l i mà không gây ra l i. dành vùng không gian a ch o c a ti n trình. Không th c p phát vùng dành b ng các hàm c p phát b nh khác (malloc, GlobalAlloc, …) cho n khi chúng ư c gi i phóng. Chúng ch ư c c p phát b ng hàm VirtualAlloc. Áp d ng cho Windows NT. Khi thi t l p v i giá tr này, d li u ư c xem như không quan tr ng, có th b vi t ch ng lên. ng d ng không hoán chuy n d li u t b nh chính vào (ra) t p tin trang. M t khác, khi thi t l p giá tr này, h th ng s b qua các giá tr c a flProtect. C p phát vùng nh t i th . a ch cao nh t có

MEM_RESERVE

MEM_RESET

MEM_TOPDOWN

B ng 7.2 Các c xác

nh d ng c p phát flAllocationType.

Trư ng flProtect xác nh cách th c b o v truy c p vùng nh . N u các trang ã ư c c p phát xác nh n, m t trong các c sau có th ư c thi t l p, k t h p v i các c PAGE_GUARD và PAGE_NOCACHE : Trang 188

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam
Ý nghĩa

____________________________________________________________________________________
C PAGE_READONLY PAGE_READWRITE PAGE_EXECUTE

Ch cho phép

c các trang c p phát (không ư c ghi). c và ghi các trang vùng nh . c và

Cho phép truy c p

Cho phép th c thi các ti n trình, nhưng không ghi. Cho phép th c thi và

PAGE_EXECUTE_READ PAGE_EXECUTE_READWRITE PAGE_GUARD

c, nhưng không ư c ghi. c và ghi.

Cho phép th c thi,

Các trang trong vùng tr thành các trang "lính canh". N u ghi ho c c các trang này, h th ng s phát sinh l i ngo i l STATUS_PAGE_GUARD và t t tình tr ng ó c a trang “lính canh”. Xem thêm ví d trong ph n 7.2.3.4. C m truy c p ( c, ghi, th c thi) các trang. N u truy c p, ta có l i b o v chung. m. Thích h p v i các ch Không dùng b nh v trang hơn là NO_ACCESS.
nh d ng b o v truy c p flProtect.

PAGE_NOACCESS

PAGE_NOCACHE

b o

B ng 7.3 Các c xác

N u thành công, hàm tr v tr v là NULL. 7.2.3.2 Gi i phóng vùng nh

a ch cơ s c a các trang vùng c p phát. Ngư c l i giá tr o

gi i phóng vùng nh o, ta dùng hàm VirtualFree. Hàm gi i phóng ho c kh c p phát (ho c c hai) các trang trong không gian a ch o c a ti n trình ang g i. BOOL VirtualFree(LPVOID lpAddress, DWORD dwSize, DWORD dwType); Trư ng lpAddress là con tr tr n vùng các trang c n gi i phóng. N u dwType ch a c MEM_RELEASE, ây ph i là con tr tr v t hàm VirtualAlloc. Trư ng dwSize xác nh s byte kích vùng nh c n gi i phóng. N u dwType ch a c MEM_RELEASE, giá tr này c n thi t l p b ng 0. Trong các trư ng h p khác, vùng nh hư ng s là các trang có ít nh t m t byte n m trong o n lpAddress n lpAddress + dwSize. Nghĩa là, n u có 2 byte n m biên hai trang khác nhau, thì c hai trang u ư c gi i phóng.

Trang 189

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ Trư ng dwType xác nh cách gi i phóng, s d ng giá tr MEM_DECOMMIT, ho c MEM_RELEASE. V i giá tr u, hàm gi i phóng các trang ch nh ( ã ư c xác nh n c p phát). N u các trang chưa ư c c p phát, ta v n có th kh c p phát (decommit) mà không gây ra l i. V i giá tr sau, hàm gi i phóng vùng nh dành. Trong trư ng h p này, dwSize ph i b ng 0, n u không hàm th c hi n th t b i. N u thành công, hàm tr v giá tr khác 0. Ngư c l i, giá tr tr v là 0. Lưu ý gi i phóng các trang, các trang ph i cùng tình tr ng (c p phát hay dành), và t t c các trang dành b ng hàm c p phát VirtualAlloc c n gi i phóng ng th i. N u m t s trang dành ban u ã ư c xác nh n c p phát, chúng c n ư c kh c p phát trư c khi g i hàm VirtualFree gi i phóng. 7.2.3.3 Thao tác trên các trang vùng nh xác nh kích thư c các trang trên máy tính, ta s d ng hàm GetSystemInfo.

VOID GetSystemInfo(LPSYSTEM_INFO lpSystemInfo); Trư ng lpSystemInfo tr n c u trúc SYSTEM_INFO ch a các thông tin h th ng.

typedef struct _SYSTEM_INFO // sinf { union { DWORD dwOemId; struct { WORD wProcessorArchitecture; WORD wReserved; } }; DWORD dwPageSize; LPVOID lpMinimumApplicationAddress;

Trang 190

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
LPVOID lpMaximumApplicationAddress; DWORD dwActiveProcessorMask; DWORD dwNumberOfProcessors; DWORD dwProcessorType; DWORD dwAllocationGranularity; WORD wProcessorLevel; WORD wProcessorRevision; }SYSTEM_INFO;

xác nh thông tin v b nh , ta ch kh o sát m t s trư ng liên quan. Trư ng dwPageSize các nh kích thư c các trang theo d ng ã ư c c p phát b ng hàm VirtualAlloc. Trư ng lpMinimumApplicationAddress tr n a ch vùng nh th p nh t, và trư ng lpMaximumApplicationAddress tr n a ch vùng nh cao nh t có th truy c p b i các ng phân nh mà vùng d ng và thư vi n liên k t ng. Trư ng dwAllocationGranularity xác nh nh o c p phát. C th , hàm VirtualAlloc yêu c u c p phát m t byte s dành m t vùng không gian b nh có kích thư c là dwAllocationGranularity byte. Ti n trình có th khoá m t hay nhi u trang ã ư c c p phát (xác nh n) vào vùng nh v t lý (RAM), ngăn ch n vi c h th ng hoán chuy n các trang vào (ra) t p tin trang b ng cách dùng hàm VirtualLock. BOOL VirtualLock(LPVOID lpAddress, DWORD dwSize); m khoá các trang ã b khoá, ta dùng hàm VirtualUnlock, cho phép các trang có th ư c hoán chuy n vào (ra) t p tin trang trên ĩa. BOOL VirtualUnlock(LPVOID lpAddress, DWORD dwSize); n a ch cơ s c a vùng các trang c n ư c khoá. Trư ng Trư ng lpAddress tr dwSize xác nh s byte vùng nh c n khoá, g m các trang ch a t t c các a ch t lpAddress n lpAddress + dwSize. N u thành công, giá tr tr v khác 0. Ngư c l i, các hàm tr v 0. S trang m c nh ư c c p phát t i a là 30 trang. Tuy nhiên, chúng ta có cũng th thay i s trang t i a này. Các trang c n m khoá không nh t thi t ph i là các trang c a l n g i khoá b ng hàm VirtualLock trư c ó, nhưng u ph i là các trang ang b khoá. Trang 191

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ Khác v i các hàm GlobalLock và LocalLock có dùng m t bi n m m chu i các l n khoá vùng nh , hàm VirtualLock thì không. Do ó m khóa, ta ch c n g i hàm VirtualUnlock m t l n mà thôi. 7.2.3.4 S d ng các hàm qu n lý b nh o dành và xác nh n

Trong ph n này, chúng ta minh h a b ng ví d th c hi n thao tác vùng nh , và ví d t o trang "lính canh".

u tiên, ta s d ng hàm VirtualAlloc và VirtualFree c p phát dành Trong ví d và xác nh n vùng nh o. u tiên, hàm VirtualAlloc ư c g i c p phát dành m t kh i các trang. Ta s d ng giá tr NULL cho a ch cơ s , ng nghĩa v i vi c cho h th ng t xác nh v trí vùng c p phát. Sau ó s d ng l i hàm VirtualAlloc c p phát xác nh n các trang trong vùng dành. Khi ó, ta c n ch nh a ch cơ s cho các trang này. Trong ví d này, ta s d ng c u trúc try-except xác nh n các trang trong vùng dành. M i khi có l i trang xu t hi n trong quá trình th c hi n kh i try, hàm l c trư c kh i except s ư c th c hi n. N u hàm l c có th c p phát m t trang khác, ph n th c thi s ti p t c trong kh i try t i c i i m xu t hi n l i ngo i l . Ngư c l i, các handler ngo i l trong kh i except ư c th c thi. Như m t thay th cho c p phát ng, ti n trình có th ơn gi n c p phát xác nh n vùng còn l i thay vì ch dành chúng. Tuy nhiên vi c c p phát xác nh n như v y l i t o nên các kh i nh không c n thi t áng ra ư c s d ng cho các ti n trình khác. Trong ví d này, ta s d ng hàm VirtualFree gi i phóng vùng nh ã xác nh n l n vùng nh dành sau khi hoàn t t công vi c. Hàm này ư c g i hai l n : l n u kh c p phát các trang ã ư c c p phát xác nh n, và l n sau gi i phóng toàn b các trang dư i d ng dành.
#define PAGELIMIT 80 #define PAGESIZE 0x1000 INT PageFaultExceptionFilter(DWORD); VOID MyErrorExit(LPTSTR); LPTSTR lpNxtPage; DWORD dwPages = 0; VOID UseDynamicVirtualAlloc(VOID) {

Trang 192

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
LPVOID lpvBase; LPTSTR lpPtr; BOOL bSuccess; DWORD i; /* dành các trang trong không gian a ch o c a ti n trình */

lpvBase = VirtualAlloc( NULL, // h th ng t xác nh a ch

PAGELIMIT*PAGESIZE,// kích thư c vùng c p phát MEM_RESERVE, // c p phát dư i d ng dành

PAGE_NOACCESS); // cách th c b o v = không truy c p if (lpvBase == NULL ) MyErrorExit("VirtualAlloc reserve"); lpPtr = lpNxtPage = (LPTSTR) lpvBase; /* S d ng c u trúc x lý ngo i l try-exception truy c p các trang. N u l i trang xu t hi n, b l c ngo i l s th c thi c p phát xác nh n các trang k ti p trong kh i dành */ for (i=0; i < PAGELIMIT*PAGESIZE; i++) { try { lpPtr[i] = 'a'; // Ghi vào b nh } /* N u xu t hi n l i trang, c g ng c p phát xác nh n trang khác */ except ( PageFaultExceptionFilter(GetExceptionCode() ) ) { /* o n này ch th c hi n khi hàm l c không th xác nh n trang k ti p */

Trang 193

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
ExitProcess( GetLastError() ); } } /* Gi i phóng các trang sau khi s d ng. bSuccess = VirtualFree( lpvBase, // a ch cơ s c a kh i nh u tiên là các trang ã ư c c p phát xác nh n */

dwPages*PAGESIZE, // s byte các trang ã c p phát MEM_DECOMMIT); // hình th c là kh xác nh n /* Cu i cùng, gi i phóng toàn vùng nh ( if (bSuccess) { bSuccess = VirtualFree( lpvBase, // a ch cơ s c a kh i nh dành) */

0, // gi i phóng toàn kh i nh MEM_RELEASE); // gi i phóng (hoàn toàn) } } INT PageFaultExceptionFilter(DWORD dwCode) { LPVOID lpvResult; /* N u xu t hi n l i ngo i l , thoát chương trình */ if (dwCode != EXCEPTION_ACCESS_VIOLATION) { printf("exception code = %d\n", dwCode); return EXCEPTION_EXECUTE_HANDLER;

Trang 194

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
} printf("page fault\n"); /* N u các trang dành ã ư c dùng thì thoát */

if (dwPages >= PAGELIMIT) { printf("out of pages\n"); return EXCEPTION_EXECUTE_HANDLER; } /* Ngư c l i, c p phát xác nh n m t trang khác */ lpvResult = VirtualAlloc( (LPVOID) lpNxtPage, // c p phát trang ti p theo PAGESIZE, // s byte kích thu c trang MEM_COMMIT, // c p phát xác nh n các trang PAGE_READWRITE); // truy c p if (lpvResult == NULL ) { printf("VirtualAlloc failed\n"); return EXCEPTION_EXECUTE_HANDLER; } /* Tăng trang dwPages++; lpNxtPage += PAGESIZE; /* Ti p t c th c hi n nơi l i trang xu t hi n */ return EXCEPTION_CONTINUE_EXECUTION; } m, và chuy n lpNxtPage n trang ti p */ c-ghi

Trang 195

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ o n chương trình ti p theo th c hi n thao tác t o trang "lính canh". Trang này cung c p c nh báo khi truy c p các trang vùng nh . i u này r t h u ích cho các ng d ng c n qu n lý s m r ng c a c u trúc d li u ng. t o trang “lính canh”, ta thi t l p c PAGE_GUARD trong hàm VirtualAlloc. C này có th dùng k t h p v i t t c các c khác, tr c PAGE_NOACCESS. N u chương trình truy c p trang "lính canh", h th ng s phát sinh l i ngo i l STATUS_GUARD_PAGE (0x80000001). H th ng cũng xoá c PAGE_GUARD, lo i b tình tr ng "lính canh" c a trang vùng nh . H th ng s không ng ng truy c p trang vùng nh v i l i ngo i l STATUS_GUARD_PAGE. N u m t l i ngo i l xu t hi n trong su t d ch v h th ng, d ch v s tr v giá tr xác nh l i. N u sau ó ta truy c p l i trang này (mà chưa thi t l p l i tình tr ng "lính canh"), thì s không x y ra l i ngo i l n a. Chương trình sau minh h a cách th c hi n c a m t trang lính canh, và hi n tư ng xu t hi n l i d ch v h th ng :
#include <windows.h> #include <stdio.h> #include <stdlib.h> int main() { LPVOID lpvAddr; DWORD cbSize; BOOL vLock; LPVOID commit; cbSize = 512; // Vùng nh c n c p phát. /* G i hàm c p phát */ lpvAddr=VirtualAlloc(NULL,cbSize,MEM_RESERVE, PAGE_NOACCESS); if(lpvAddr == NULL) {

Trang 196

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
fprintf(stdout,"VirtualAlloc failed on RESERVE with %ld\n", GetLastError()); } /* C p phát xác nh n vùng nh */ commit = VirtualAlloc(NULL,cbSize,MEM_COMMIT, PAGE_READONLY|PAGE_GUARD); if(commit == NULL) { fprintf(stderr,"VirtualAlloc failed on COMMIT with %ld\n", GetLastError()); } else { fprintf(stderr,"Committed %lu bytes at address %lp\n", cbSize,commit); } /* Khoá vùng nh ã xác nh n */

vLock = VirtualLock(commit,cbSize); if(!vLock) { fprintf(stderr,"Cannot lock at %lp, error = %lu\n", commit, GetLastError()); } else fprintf(stderr,"Lock Achieved at %lp\n",commit); /* Khoá vùng nh l n n a */

Trang 197

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
vLock = VirtualLock(commit,cbSize); if(!vLock) { fprintf(stderr,"Cannot get 2nd lock at %lp, error = %lu\n", commit, GetLastError()); } else fprintf(stderr,"2nd Lock Achieved at %lp\n",commit); }

Chương trình trên cho k t qu tương t k t qu sau : Committed 512 bytes at address 003F0000 Cannot lock at 003F0000, error = 0x80000001 2nd Lock Achieved at 003F0000 Chú ý : L n khoá th nh t th t b i, t o l i ngo i l STATUS_GUARD_PAGE. Tuy nhiên, trong l n khoá th hai, hàm th c hi n thành công, do h th ng ã lo i b tình tr ng "lính canh" c a trang.

7.3 X

LÝ T P TIN

T p tin là m t ơn v lưu tr cơ b n máy tính phân bi t các kh i thông tin khác nhau, ư c lưu tr trên các thi t b lưu tr ph như là ĩa, băng t , và ư c t ch c theo các nhóm g i là thư m c. x lý t p tin, ta có th dùng các hàm trong C chu n như fopen, fclose, fread, fwrite, fseek, … trong môi trư ng Windows. Các hàm này ư c h tr trong thư vi n stdio.h. Chúng ta s không bàn v các hàm này ây. Trong ph n này, chúng ta s tìm hi u các hàm thao tác trên t p tin c a Win32® cho phép các ng d ng t o, m , c p nh t và xoá các t p tin, cũng như tìm hi u các thông s h th ng v t p tin.

7.3.1 T o và m t p tin
Win32® API cung c p hàm CreateFile s n. Trang 198 t o m t t p tin m i ho c m m t t p tin ã có

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ HANDLE CreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); n chu i ký t zero xác nh tên t p tin c n m ho c t o. Trư ng lpFileName tr Trư ng dwDesiredAccess xác nh cách th c truy c p i tư ng. M t ng d ng có th th c hi n truy c p c, ghi, c-ghi, s d ng m t hay k t h p các giá tr sau :
Giá tr 0 Ý nghĩa

Xác nh truy v n thi t b n m t i tư ng. M t ng d ng có th truy v n thu c tính thi t b mà không c n ph i truy c p thi t b . Xác l p hình th c truy c p c. D li u có th c t t p tin, ng th i d ch chuy n con tr t p tin. truy c p c-ghi, ta k t h p v i c GENERIC_WRITE. Xác l p hình th c truy c p ghi. D li u có th ư c ghi vào t p tin, ng th i d ch chuy n con tr . có th truy c p c-ghi, ta k t h p v i c GENERIC_READ.
nh cách truy c p i tư ng

GENERIC_READ

GENERIC_WRITE

B ng 7.4 Trư ng dwDesiredAccess xác

Trư ng dwShareMode thi t l p các bit c xác nh cách chia s i tư ng (t p tin). N u dwShareMode b ng 0, i tư ng không th chia s . Khi ó, ta không th thao tác trên i tư ng chia s i tư ng, ta k t h p m t trong các c sau : cho n khi óng handle.
FILE_SHARE_DELETE

S d ng trong Windows NT : Thao tác trên i tư ng ch th c hi n n u yêu c u truy c p xoá. Thao tác trên i tư ng ch th c hi n n u yêu c u truy c p c. Thao tác trên i tư ng ch th c hi n n u yêu c u truy c p ghi.
nh cách chia s i tư ng

FILE_SHARE_READ

FILE_SHARE_WRITE

B ng 7.5 Trư ng dwShareMode xác

Trang 199

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ Trư ng lpSecurityAttributes tr n c u trúc SECURITY_ATTRIBUTES xác nh handle i tư ng có ư c chuy n cho các ti n trình con hay không. ây chúng ta không dùng, và thi t l p giá tr là NULL. Trư ng dwCreationDisposition xác l p thao tác t o t p tin m i hay m t p tin ã có. Dùng m t trong các giá tr sau :
CREATE_NEW

T o m i m t t p tin. Hàm này th t b i n u t p tin ã có. T o m i m t t p tin. N u t p tin ã t n t i, hàm s t o ch ng lên, ng th i xoá các thu c tính hi n hành c a t p tin. M m t t p tin. Hàm th t b i n u t p tin chưa có s n. M m t t p tin n u có s n. N u t p tin chưa t n t i, hàm s t o t p tin như s d ng c CREATE_NEW. M m t t p tin. Khi m , h th ng kh i t o kích thư c t p tin l i v 0 byte. Ti n trình g i c n m t p tin ít nh t v i d ng truy c p GENERIC_WRITE. Hàm th t b i n u không t n t i t p tin.

CREATE_ALWAYS

OPEN_EXISTING

OPEN_ALWAYS

TRUNCATE_EXISTING

B ng 7.6 Trư ng dwCreationDisposition xác l p thao tác t p tin

Trư ng dwFlagsAndAttributes xác h p các thu c tính sau :
FILE_ATTRIBUTE_ARCHIVE

nh các thu c tính và c cho t p tin. Ta có th k t

T p tin archive. ng d ng dùng thu c tính này ánh d u t p tin có th sao lưu ho c lo i b . T p tin n. Không hi n th trong danh sách các t p tin thông thư ng trong các thư m c. T p tin không có thu c tính nào khác. Thu c tính này thư ng ư c dùng duy nh t. D li u t p tin không có s n. D li u ư c ch di chuy n v t lý vào vùng lưu tr offline. T p tin ch c. nh

FILE_ATTRIBUTE_HIDDEN

FILE_ATTRIBUTE_NORMAL

FILE_ATTRIBUTE_OFFLINE

FILE_ATTRIBUTE_READONLY

ng d ng không th ghi ho c xoá

Trang 200

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam d li u trong t p tin.

____________________________________________________________________________________

FILE_ATTRIBUTE_SYSTEM

T p tin là m t ph n c a h i u hành, ho c ư c s d ng c bi t trong h th ng. T p tin ư c dùng cho vùng lưu tr t m. Sau khi ng d ng k t thúc, t p tin s ư c xóa.
nh các thu c tính và c cho t p tin.

FILE_ATTRIBUTE_TEMPORARY

B ng 7.7 Trư ng dwFlagsAndAttributes xác

Các c xác nh t p tin khá ph c t p, chúng ta không bàn k ây. Trư ng cu i cùng là hTemplateFile xác nh handle truy c p GENERAL_READ n t p tin t m. T p tin t m có vai trò h tr các thu c tính t p tin và thu c tính m r ng cho t p tin ư c t o. Trong Windows 95, giá tr hTemplateFile c n ư c gán b ng NULL. N u thành công hàm tr v handle c a t p tin xác INVALID_HANDLE_VALUE. nh. Ngư c l i, giá tr tr v là

Lưu ý, vi c thi t l p giá tr dwDesiredAccess cho phép ng d ng có th truy v n các thu c tính thi t b mà không th c s truy c p thi t b . i u này r t h u d ng, ví d trong trư ng h p ng d ng mu n xác nh kích thư c cùng các nh d ng ĩa m m mà không c n ph i có ĩa trong ĩa. Khi t o m t t p tin, hàm CreateFile th c hi n các ch c năng sau: • K t h p các c và thu c tính t p tin ư c xác nh b i c dwFlagsAndAttributes v i giá tr là FILE_ATTRIBUTE_ARCHIVE. • Thi t l p kích thư c t p tin b ng 0. • Chép các thu c tính m r ng c a t p tin t m vào t p tin m i n u bi n hTemplateFile xác nh. Khi m m t t p tin có s n, hàm CreateFile th c hi n các ch c năng sau : • K t h p các c xác nh b i dwFlagsAndAttributes v i các thu c tính c a t p tin hi n có. Hàm CreateFile s b qua các thu c tính c a t p tin xác nh b i c dwFlagsAndAttributes. • Thi t l p kích thư c t p tin d a vào giá tr c a dwCreationDisposition. • B qua giá tr c a bi n hTemplateFile. N u hàm t o m t t p tin trên ĩa m m không có ĩa m m, ho c trên CD-ROM không có ĩa CD, h th ng s ưa ra m t h p tho i thông i p (message box) yêu c u ngư i dùng ưa ĩa m m ho c ĩa CD vào. h th ng không th c hi n thao tác trên, c n thi t l p giá tr uMode trong hàm SetErrorMode là SEM_FAILCRITICALERRORS.

Trang 201

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ UINT SetErrorMode(UINT uMode); Trong ví d sau, hàm CreateFile m m t t p tin ã có
HANDLE hFile; hFile = CreateFile("MYFILE.TXT", // m t p tin MYFILE.TXT GENERIC_READ, // m c c

c:

FILE_SHARE_READ, // chia s NULL, // không b o m t

OPEN_EXISTING, // ch m t p tin ã có FILE_ATTRIBUTE_NORMAL, //T p tin thư ng NULL); // không có th c tính t m if (hFile == INVALID_HANDLE_VALUE) { ErrorHandler("Could not open file."); // l i x lý }

xoá t p tin trên, trư c h t ta óng t p tin l i.
CloseHandle(hFile); DeleteFile("MYFILE.TXT");

Trong ví d sau, hàm t o m t t p tin m i và m
HANDLE hFile;

ch

ghi.

hFile = CreateFile("MYFILE.TXT", // t p tin MYFILE.TXT GENERIC_WRITE, // t o 0, // không chia s NULL, // không b o m t CREATE_ALWAYS, // ghi ch ng n u ã có ghi

Trang 202

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
FILE_ATTRIBUTE_NORMAL | // t p tin bình thư ng FILE_FLAG_OVERLAPPED, // không NULL); // không thu c tính t m if (hFile == INVALID_HANDLE_VALUE) { ErrorHandler("Could not open file."); // l i x lý } ng b I/O

7.3.2 T o t p tin t m
Các ng d ng có th nh n m t t p tin duy nh t cho t p tin t m b ng cách s d ng hàm GetTempFileName. xác nh ư ng d n n thư m c ch a t p tin t m ư c t o, ta dùng hàm GetTempPath. Hàm GetTempFileName t o tên m t t p tin t m. Tên t p tin y g m ư ng d n n i v i m t chu i ký t s th p l c phân th hi n tên t p tin, và ph n m r ng là .TMP. UINT GetTempFileName(LPCTSTR lpPathName, LPCTSTR lpPrefixString, UINT uUnique, LPTSTR lpTempFileName); Trư ng lpPathName tr n m t chu i ký t (k t thúc b ng ký t NULL) xác d n c a t p tin, dùng các ký t ANSI. N u trư ng này b ng NULL, hàm th t b i. nh ư ng

Trư ng lpPrefixString tr n m t chu i ký t (k t thúc b ng ký t NULL). Hàm s d ng 3 ký t u tiên c a chu i như ph n ti n t c a t p tin. Các ký t s d ng ph i là ky t ANSI. Trư ng uUnique xác nh m t s nguyên không d u (mà) hàm chuy n thành chu i ký t th p l c phân s d ng trong vi c t o t p tin t m. Trư ng lpTempFileName tr n vùng nh m ch a tên t p tin t m. Trư ng này là m t chu i ký t k t thúc NULL các ký t ANSI. dài vùng nh m ư c xác nh b i giá tr MAX_PATH c a thư m c tương ng. T p tin t o ư c s có d ng như sau : path\preuuuu.TMP

Trang 203

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ Trong ó path là ư ng d n, xác nh b i giá tr lpPathName; pre là 3 ký t uc a chu i lpPrefixString; và uuuu là giá tr th p l c phân c a uUnique. Khi thoát kh i h ng b xoá. i u hành (t t máy ch ng h n), các t p tin t m t o b ng hàm này s t t o

tránh các l i khi chuy n chu i ANSI, ng d ng c n g i hàm CreateFile trư c t p tin t m.

N u giá tr uUnique b ng 0, hàm GetTempFileName xác l p m t con s duy nh t d a trên th i i m hi n t i c a h th ng. N u t p tin ã có, h th ng t tăng lên m t s m i cho n khi có m t tên duy nh t. N u th c hi n thành công, hàm tr v con s duy nh t xác Ngư c l i, giá tr tr v là 0. nh trong trư ng uUnique.

thu nh n ư ng d n t p tin t m, ta dùng hàm GetTempPath. DWORD GetTempPath(DWORD nBufferLength, LPTSTR lpBuffer); Trư ng nBufferlength xác nh kích thư c vùng m chu i ký t xác nh b i lpBuffer. Trư ng lpBuffer tr n vùng m nh n chu i ký t xác nh ư ng d n t p tin t m. Chu i ký t k t th c b ng ký t ‘\’, ví d : C:\TEMP\. N u thành công, hàm tr v l n xác nh kích thư c chu i zero. N u giá tr tr v l n hơn nBufferLength, giá tr tr v s là kích thư c vùng m c n ch a ư ng d n. Ngư c l i, giá tr tr v là 0 n u hàm th t b i.

7.3.3 Sao chép và di chuy n t p tin
chép (copy) m t t p tin, ta c n m chép vào m t t p tin m i. ch ch c. Sau ó dùng hàm CopyFile

BOOL CopyFile(LPCTSTR lpExistingFileName, LPCTSTR lpNewFileName, BOOL bFailIfExists); Trư ng lpExistingFileName và lpNewFileName tr n chu i (k t thúc NULL) xác nh tên t p tin ã có và tên t p tin m i. Trư ng bFialIfExists xác nh cách t o t p tin v i tên m i trên. N u trư ng ư c thi t l p là TRUE, và t p tin có tên lpNewFileName ã t n t i, hàm th t b i. N u trư ng ư c thi t l p là FALSE và t p tin ã t n t i, hàm s t o t p tin m i ch ng lên t p tin cũ. N u thành công, hàm tr v giá tr khác 0. Ngư c l i, giá tr tr v là 0.

Trang 204

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ di chuy n (move) m t t p tin, trư c h t c n ph i óng t p tin l i (n u ang m ). Ta dùng hàm MoveFile. Hàm này th c hi n thao tác i tên m t t p tin hay thư m c (bao g m c các t p tin con trong thư m c). BOOL MoveFile(LPCTSTR lpExistingFileName, LPCTSTR lpNewFileName); Hai trư ng trên l n lư t tr n tên t p tin (thư m c) hi n có và tên t p tin (thư m c) m i. Tên t p tin (thư m c) m i c n ph i chưa có trong ư ng d n c a nó. Tên t p tin m i có th trên m t h th ng hay ĩa khác, trong khi tên thư m c m i ph i cùng ĩa v i thư m c cũ. N u thành công, giá tr tr v khác 0. Ngư c l i, giá tr tr v là 0. Ví d sau minh h a vi c t o và s d ng t p tin t m copy m t t p tin. u tiên ng d ng m t p tin ORIGINAL.TXT b ng cách s d ng hàm CreateFile. Sau ó ng d ng s d ng hàm GetTempFileName và CreateFile t o t p tin t m. ng d ng c t ng kh i 4K d li u vào vùng m, chuy n n i dung trong vùng m sang ch hoa, và vi t chúng xu ng t p tin t m. Sau khi chuy n toàn b t p tin trên sang t p tin t m, ta i t p tin t m thành ALLCAPS.TXT b ng cách dùng hàm MoveFile.
HANDLE hFile; HANDLE hTempFile; DWORD dwBytesRead, dwBytesWritten, dwPos; char szTempName[MAX_PATH]; char buffer[4096]; /* M t p tin có s n */ hFile = CreateFile("ORIGINAL.TXT", // tên t p tin GENERIC_READ, // m 0, // không chia s NULL, // không b o m t OPEN_EXISTING, // t p tin ã có s n FILE_ATTRIBUTE_NORMAL, // t p tin thông thư ng NULL); // không thu c tính t m if (hFile == INVALID_HANDLE_VALUE) c

Trang 205

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
{ ErrorHandler("Could not open file."); // x lý l i } /* T o t p tin t m */ GetTempFileName("\\TEMP", // thư m c ch a t p tin t m "NEW", // ph n u t p tin t m

0, // t o tên duy nh t szTempName); // vùng m tên

hTempFile = CreateFile((LPTSTR) szTempName, // tên t p tin GENERIC_READ | GENERIC_WRITE, // m d ng 0, // không chia s NULL, // không b o m t CREATE_ALWAYS, // t o ch ng n u t p tin ã có FILE_ATTRIBUTE_NORMAL, // t p tin thông thư ng NULL); // không thu c tính t m if (hTempFile == INVALID_HANDLE_VALUE) { ErrorHandler("Could not create temporary file."); } /* c kh i 4K vào vùng vào t p tin t m. */ do { if (ReadFile(hFile, buffer, 4096, &dwBytesRead, NULL)) { m. Chuy n t t c các ký t trong vùng m sang d ng ch hoa. Vi t vùng m c-ghi

Trang 206

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
CharUpperBuff(buffer, dwBytesRead); WriteFile(hTempFile, buffer, dwBytesRead, &dwBytesWritten, NULL); } } while (dwBytesRead == 4096); /* óng c hai t p tin */ CloseHandle(hFile); CloseHandle(hTempFile); /* Chuy n t p tin t m vào t p tin m i ALLCAPS.TXT */ if (!MoveFile(szTempName, "ALLCAPS.TXT")) { ErrorHandler("Could not move temp. file."); }

Hàm CloseHandle óng m t t p tin ang m . Xem ph n 7.3.6.

7.3.4

c và ghi d li u vào t p tin

M i t p tin ang m có m t con tr t p tin xác nh byte k ti p s ư c c ho c ghi. Khi m t t p tin m l n u tiên, h th ng thi t l p con tr t p tin t i v trí u t p tin. M i khi c ho c ghi vào m t byte, con tr t p tin t ng d ch chuy n. thay i v trí này, ta dùng hàm SetFilePointer. DWORD SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod); Trư ng hFile là handle c a t p tin ch a con tr t p tin c n di chuy n. Handle này c n ư c t o dư i d ng truy c p GENERIC_READ ho c GENERIC_WRITE. Trư ng lDistanceToMove và lpDistanceToMoveHigh xác nh s byte con tr c n d ch chuy n. N u lpDistanceToMoveHigh b ng NULL, 32-bit th p c a lDistanceToMove xác nh s byte c n di d i con tr . Ngư c l i, hai trư ng trên thi t l p m t giá tr 64-bit (không d u) th hi n s byte c n di d i con tr . Trư ng dwMoveMethod xác nh i m g c mà con tr c n di d i. N u trư ng này b ng FILE_BEGIN, i m g c là i m u tiên (byte th 0) c a t p tin. N u là FILE_CURRENT,

Trang 207

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ i m g c là v trí hi n t i c a con tr . Và FILE_END xác nh i m g c là v trí cu i hi n t i c a t p tin. N u thành công, và lpDistanceToMoveHigh b ng NULL, giá tr tr v là DWORD th p c a con tr t p tin. N u lpDistanceToMoveHigh khác NULL, hàm tr v DWORD th p c a con tr t p tin, và tr trư ng này n DWORD cao c a con tr t p tin. N u hàm th t b i và lpDistanceToMoveHigh b ng NULL, giá tr tr v là 0xFFFFFFFF. bi t thêm thông tin l i, ta dùng hàm GetLastError. N u hàm tr v 0xFFFFFFFF và lpDistanceToMoveHigh, có th hàm thành công ho c th t b i, c n ph i g i hàm GetLastError xác nh. o n chương trình sau trình bày v n này :
/* Trư ng h p 1: G i hàm v i lpDistanceToMoveHigh == NULL */ /* C g ng di chuy n con tr t p tin c a hFile m t o n */ dwPtr = SetFilePointer(hFile, lDistance, NULL, FILE_BEGIN); if (dwPtr == 0xFFFFFFFF) // Ki m tra th t b i { dwError = GetLastError() ; // Nh n mã l i . . . // X lý l i } // Cu i ph n x lý l i

/* Trư ng h p 2: G i hàm v i lpDistanceToMoveHigh != NULL */ /* C g ng di chuy n con tr t p tin hFile m t o n dài */ dwPtrLow = SetFilePointer(hFile, lDistLow, & lDistHigh, FILE_BEGIN); /* Ki m tra th t b i */ if (dwPtrLow==0xFFFFFFFF&&(dwError=GetLastError())!=NO_ERROR) { // X lý l i // . . . } // Cu i ph n x lý l i

Trang 208

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ di chuy n ti n, ta thi t l p d ch chuy n m t giá tr dương. Ngư c l i, thi t l p giá tr âm di chuy n lùi con tr t p tin. N u giá tr con tr t p tin sau khi d ch chuy n âm, hàm th t b i, và mã l i mà hàm GetlastError tr v là ERROR_NEGATIVE_SEEK. N u mu n di chuy n con tr SetEndOfFile. n cu i t p tin ghi ti p, ta cũng có th dùng hàm

BOOL SetEndOfFile(HANDLE hFile); Trư ng hFile là handle c a t p tin c n di chuy n con tr n cu i t p tin c n ư c t o v i d ng truy c p GENERAL_WRITE. N u thành công, hàm tr v giá tr khác 0. Ngư c l i, giá tr tr v là 0. Hàm ReadFile c d li u t m t t p tin, t i m xác nh b i con tr t p tin. Sau khi c, con tr t p tin d ch chuy n m t o n ng v i s byte th t s c ư c. Tương t , ghi vào t p tin ta dùng hàm WriteFile. BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped); BOOL WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped); Handle t p tin hFile c n ư c t o v i d ng truy c p GENERAL_READ ho c GENERAL_WRITE. Trư ng lpBuffer tr n vùng nh m nh n d li u c t t p tin, hay ch a d li u c n ghi. Trư ng nNumberOfBytesToRead xác nh s byte c n c. Trư ng lpNumberOfBytesRead tr n các byte c ư c. Hàm ReadFile thi t l p giá tr này b ng 0 trư c khi th c hi n các thao tác khác ki m tra l i. Trư ng nNumberOfBytesToWrite xác nh s byte c n ghi. N u trư ng này b ng 0, hàm không ghi d li u, nhưng v n ư c g i th c hi n. Trư ng lpNumberOfBytesWritten xác nh s byte ghi ư c, trư ng này cũng ư c hàm WriteFile thi t l p v 0 trư c khi th c hi n các thao tác khác ki m tra l i. Cu i cùng, trư ng lpOverlapped tr n c u trúc OVERLAPPED. N u t p tin ư c m v i c FILE_FLAG_OVERLAPPED, giá tr này ph i khác NULL. ơn gi n ta thi t l p giá tr b ng NULL, hàm s c (ghi) t p tin t v trí con tr hi n t i và hàm ch tr k t qu v sau khi c (ghi) xong. ã Hàm ReadFile s d ng v i m t s lý do sau : thao tác ghi hoàn t t cu i ư ng ng ghi, c h t s byte yêu c u, ho c x y ra l i khi c. Trang 209

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ N u thành công, các hàm tr v giá tr khác 0. Ngư c l i, giá tr tr v b ng 0.

7.3.5 Khoá và m khoá t p tin
M c dù h th ng cho phép nhi u ng d ng có th m và ghi vào cùng m t t p tin, các ng d ng không nên th c hi n song song. ngăn ch n ng d ng khác ghi vào ph n d li u c a mình, ta có th s d ng hàm LockFile. m khoá t p tin, cho phép các ng d ng khác truy c p vùng d li u, ta dùng hàm UnlockFile. BOOL LockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh); BOOL UnlockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh); Trư ng hFile là handle c a t p tin ư c m dư i d ng GENERAL_READ ho c GENERAL_WRITE, ho c c hai. offset Trư ng dwFileOffsetLow và dwFileOffsetHigh xác u tiên c n khoá hay m khoá. nh word th p và cao c a byte

Trư ng nNumberofBytesToLockLow (nNumberofBytesTo UnlockLow) và nNumberOfBytesToLockHigh (nNumberOf BytesToUnlockHigh) xác nh word th p và cao dài kho ng byte c n khoá hay m khóa. N u thành công, hàm tr v giá tr khác 0. Ngư c l i, giá tr tr v là 0. Ví d sau ây n i m t t p tin vào m t t p tin khác. ng d ng s d ng hàm CreateFile m t p tin ONE.TXT c, và TWO.TXT vi t. Sau ó ng d ng n i ph n d li u c a t p tin ONE.TXT vào cu i t p tin TWO.TXT b ng cách c (dùng hàm ReadFile) và ghi (dùng hàm WriteFile) t ng kh i 4K d li u. Trư c khi vi t vào t p tin th hai, ng d ng d ch chuy n con tr n cu i t p tin b ng cách dùng hàm SetFilePointer, sau ó khóa vùng c n ghi dùng hàm LockFile. Sau khi th c hi n thao tác ghi xong, ta m khoá, dùng hàm UnlockFile, các ng d ng khác có th s d ng t p tin này.
HANDLE hFile; HANDLE hAppend; DWORD dwBytesRead, dwBytesWritten, dwPos; char buff[4096]; /* M m t t p tin ã có */

Trang 210

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
hFile = CreateFile("ONE.TXT", // m t p tin ONE.TXT GENERIC_READ, // m 0, // không chia s NULL, // không b o m t OPEN_EXISTING, // ch m t p tin ã t n t i FILE_ATTRIBUTE_NORMAL, // t p tin bình thư ng NULL); // không có thu c tính t m if (hFile == INVALID_HANDLE_VALUE) { ErrorHandler("Could not open ONE."); // x lý l i } /* M t p tin ã có. N u chưa có, t o t p tin m i */ hAppend = CreateFile("TWO.TXT", // m t p tin TWO.TXT GENERIC_WRITE, // m 0, // không chia s NULL, // không b o m t OPEN_ALWAYS, // m t p tin cũ ho c t o m i FILE_ATTRIBUTE_NORMAL, // t p tin bình thư ng NULL); // không có thu c tính t m if (hAppend == INVALID_HANDLE_VALUE) { ErrorHandler("Could not open TWO."); // x lý l i } /* N i t p tin th nh t vào cu i t p tin th hai. Khoá t p tin th hai c p khi ang ghi. M khoá sau khi ghi xong */ ngăn ch n các ti n trình khác truy ghi c

Trang 211

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________
do { if (ReadFile(hFile, buff, 4096, &dwBytesRead, NULL)) { dwPos= SetFilePointer(hAppend, 0, NULL, FILE_END); LockFile(hAppend, dwPos, 0, dwPos+dwBytesRead, 0); WriteFile(hAppend, buff, dwBytesRead, &dwBytesWritten, NULL); UnlockFile(hAppend, dwPos, 0, dwPos+dwBytesRead, 0); } } while (dwBytesRead == 4096); /* óng c hai t p tin */ CloseHandle(hFile); CloseHandle(hAppend);

7.3.6 óng và xoá t p tin
s d ng hi u qu tài nguyên h th ng, ng d ng c n óng các t p tin khi không c n dùng n a b ng cách g i hàm CloseHandle. N u ng d ng b ng t và t p tin v n ang m , h th ng s t ng óng t p tin này. BOOL CloseHandle(HANDLE hObject); N u thành công, hàm tr v giá tr khác 0. Ngư c l i, giá tr tr v là 0. tin l i m r ng, ta dùng hàm GetLastError. khi b xóa. BOOL DeleteFile(LPCTSTR lpFileName); Trư ng lpFileName tr n chu i (k t thúc b ng ký t NULL) xác nh t p tin c n xoá. N u thành công, hàm tr v khá tr khác 0. Ngư c l i, giá tr tr v là 0. Hàm th t b i n u t p n u bi t các thông

xoá m t t p tin, ta dùng hàm DeleteFile. Lưu ý r ng t p tin này c n ph i óng trư c

Trang 212

NGÔN NG

L P TRÌNH

L P TRÌNH C TRÊN WINDOWS Created pdf by Nam Nguyeãn http://360.yahoo.com/fptnam

____________________________________________________________________________________ t p tin c n xoá không t n t i. Trong Windows NT, hàm không th xoá các t p tin ang m . Tuy nhiên, trong Windows 95, t p tin ang m v n có th b xoá.

7.3.7 X lý thư m c
nh. Khi ng d ng t o m t t p tin m i, h i u hành s thêm t p tin này vào m t thư m c xác t o và xoá m t thư m c, ta dùng hàm CreateDirectory và RemoveDirectory.

BOOL CreateDirectory(LPCTSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes); BOOL RemoveDirectory(LPCTSTR lpPathName); Trư ng lpPathName tr n chu i (k t thúc b ng ký t NULL) xác nh ư ng d n thư m c c n t o (hay c n xoá). Kích thư c chu i m c nh gi i h n cho ư ng d n là MAX_PATH ký t . Trong trư ng h p xoá thư m c, ư ng d n c n xác nh thư m c là thư m c r ng. Trư ng lpSecurityAttributes tr n c u trúc SECURITY_ATTRIBUTES ch a trư ng lpSecurityDescriptor xác nh mô t m t c a thư m c m i. ơn gi n, ta gán giá tr lpSecurityAttributes b ng NULL, khi ó thư m c m i nh n các giá tr mô t m t m c nh. N u thành công, các hàm tr v giá tr khác 0. Ngư c l i, giá tr tr v là 0. xác nh thư Thư m c cu i c a ư ng d n ang s d ng g i là thư m c hi n hành. m c hi n hành, ng d ng g i hàm GetCurrentDirectory. thay i thư m c hi n hành, ng d ng g i hàm SetCurrentDirectory. DWORD GetCurrentDirectory(DWORD nBufferLength, LPTSTR lpBuffer); Trư ng nBufferLength xác hi n hành. Vùng m này ph i dài ch a chu i ký t này. nh kích thư c vùng m c a chu i ký t th hi n thư m c ch a c ký t NULL cu i chu i. Trư ng lpBuffer s

N u thành công, hàm tr v giá tr xác nh s ký t ư c ghi vào vùng m, không ch a ký t NULL. Ngư c l i, giá tr tr v là 0. N u vùng m lpBuffer không l n, giá tr tr v xác nh kích thư c c n thi t c a vùng m, g m c byte NULL áng d u k t thúc chu i. BOOL SetCurrentDirectory(LPCTSTR lpPathName); Trư ng lpPathName tr n chu i ký t (k t thúc b ng NULL) xác N u thành công, hàm tr v giá tr khác 0. Ngư c l i, giá tr tr v là 0. nh ư ng d n m i.

Trang 213

Sign up to vote on this title
UsefulNot useful