Lập trình C - Bài 4: Giao tiếp thiết bị đồ họa

pdf 73 trang vanle 3020
Bạn đang xem 20 trang mẫu của tài liệu "Lập trình C - Bài 4: Giao tiếp thiết bị đồ họa", để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên

Tài liệu đính kèm:

  • pdflap_trinh_c_bai_4_giao_tiep_thiet_bi_do_hoa.pdf

Nội dung text: Lập trình C - Bài 4: Giao tiếp thiết bị đồ họa

  1. Bài 4 GIAO TI P THI T B ð HA Ph n h th ng c a Microsoft Windows liên quan t i vi c th hi n đ ha trên thi t b giao ti p màn hình, máy in đưc g i là ph n Giao ti p Thi t b ð ha ( GDI – Graphics Device Interface ). ðây chính là c ơ ch mà thơng qua đĩ các l p trình viên thao tác th hi n các thơng tin, d li u m t cách tr c quan trên các ng d ng. Trong bài h c này, chúng ta s tìm hi u cách xu t v ăn b n, v đưng th ng, tơ màu, thơng qua các hàm API v GDI t ươ ng ng mà Windows cung c p. 4.1. T NG QUAN V GDI Chúng ta c n bi t r ng các khái ni m, k thu t v GDI c a Microsoft Windows là r t nhi u. Vì rng đây khơng ch là c ơ ch đ lp trình viên thao tác v ăn b n, hình nh, mà ngay t đu đây cũng chính là c ơ ch mà Windows ph i th c hi n đ th hi n giao di n chung c a mình: cách trình bày menu, icon, cursor, Tuy v y, trong ph m vi c a mơn h c, chúng ta khơng phân tích ti sao Windows t ch c các đi t ưng đ ha, mà ch tìm hi u nh ng hàm, c u trúc d li u c ơ bn nh t v đ ha là gì, c ũng nh ư cách th c đ th hi n chúng trên các ng d ng Windows- based là th nào . 4.1.1. GDI và Thi t b Ng cnh Xét d ưi gĩc đ lp trình, GDI là t p h p hàng tr ăm hàm (function) c ũng nh ư các ki u d li u, macro, và c u trúc mà Microsoft đnh ngh ĩa đ xây d ng giao di n h điu hành Windows. Cơ ch đ ha trên Windows 98 và Microsoft Windows NT đưc qu n lý thơng qua các hàm liên k t t th ư vi n GDI32.DLL. Trên Windows 98, th ư vi n GDI32.DLL s dng các hàm t th ư vi n GDI.EXE 16-bit đ th c hi n các thao tác cài đt th t s ca các hàm. Trên Windows NT, th ư vi n GDI.EXE ch dùng cho các ch ươ ng trình d ng 16-bit. ðim c n chú ý đây là vi c Windows s dng các th ư vi n này đ th hi n d li u đ ha lên các thi t v vt lý c th (video display, printer) nh ư th nào. Câu tr li th hi n qua mơ hình hình 4.1 sau: Hình 4.1 Mơ hình ho t đng c a GDI Nh ư th hi n trên mơ hình, các ng d ng trên Windows khơng th t s thao tác đn thi t b xu t v t lý, mà ch thao tác đn m t đi t ưng logic, g i là Thi t b Ng cnh (DC - Device Context ). Và nh ư v y, mc l p trình, chúng ta ch cn bi t làm th nào đ gi các hàm GDI lên đi t ưng DC mà thơi – chúng ta s tìm hi u các d ng hàm GDI và cách g i các hàm thao tác các đi t ưng đ ha hai ph n ti p theo. 74
  2. Cũng t trên mơ hình, bây gi chúng ta đã cĩ th hi u t i làm sao mà ng v i m i thi t b vt lý nh ư card màn hình, máy in, chúng ta c n phài cài đt trình điu khi n thi t b (driver) t ươ ng ng khi s dng trên Windows. Các driver này cĩ nhi m v chuy n các l nh GDI thành các mã lnh ho c cách truy c p mà thi t b ph n c ng t ươ ng ng cĩ th hi u và th c hi n đúng theo yêu cu c a ng d ng. Và như v y, chúng ta l p trình mà khơng quan tâm t i vi c thi t b máy in hay video display đưc s dng là gì. Vì v y, GDI cịn đưc g i là c ơ ch đ ha đc l p thi t b (device-independent graphics ). trên, chúng ta cĩ nĩi đn Thi t b Ng cnh, v y Thi t b Ng cnh là gì, và cách th c chúng ta l p trình thao tác Thi t b Ng cnh là th nào? Ta cĩ th đnh ngh ĩa nh ư sau, Thi t b Ng cnh bao g m t p h p các “thu c tính” xác đnh cách th c các hàm GDI thao tác trên thi t b. T p thu c tính này t ươ ng ng các c u trúc c a các đi t ưng g i là đi t ưng đ ha (xem ph n 4.1.3). Khi ta g i các hàm GDI đ th c hi n m t thao tác đ ha nào đĩ, ví d dùng hàm LineTo đ v mt đưng th ng đn m t v trí nào đĩ trên DC, thì Windows dùng các thơng tin v bút v (pen) nh ư màu s c, đ dày nét v , s n cĩ trong đi t ưng đ ha này đ v. Trong tr ưng h p chúng ta mu n v vi m t màu s c, ki u v , khác, ta ch vi c thay đi thơng s ca đi t ưng này tr ưc khi th c hi n thao tác v . Chúng ta s tìm hi u cách thao tác m t s đi tưng đ ha c ơ b n là bút v (pen), ch i tơ (brush) và nh bitmap trong các ph n ti p sau. 4.1.2. Các d ng hàm GDI Da vào m c đích s dng, t p h p các hàm GDI cĩ th đưc phân thành m t s lo i sau: 1 Các hàm nh n (ho c t o) và gi i phĩng (ho c hy) đi t ưng DC Nh ư đã th y trong ví d đu tiên, đ xu t dịng ch trong bi n szHello ra màn hình, ta dùng hàm DrawText đ v lên đi t ưng hdc . ði t ưng này nh n đưc qua hàm BeginPaint và gi i phĩng b ng hàm EndPaint bên trong thơng đip WM_PAINT . Chúng ta s nĩi rõ thêm v các hàm này trong ph n 4.1.4. 2 Các hàm l y thơng tin v DC Trong m t s ng d ng, chúng ta c n xác đnh m t s thơng tin v DC nh ư kích th ưc DC tính theo pixel và tính theo milimet, s lưng bút v , ch i tơ, trong DC thì ta dùng nh ng hàm này. Tuy nhiên, v i ph m vi mơn h c chúng ta s khơng tìm hi u v các hàm l y thơng tin DC này. 3 Các hàm th c hi n thao tác v ð xu t m t v ăn b n, v mt đưng th ng, tơ m t hình trịn, GDI cung c p cho chúng ta m t s hàm t ươ ng ng nh ư TextOut , LineTo , Ellipse Trong các ph n ti p theo chúng ta s tìm hi u v mt s hàm thơng qua các ví d tươ ng ng. 4 Các hàm thi t l p ho c l y các thu c tính c a DC Mt “thu c tính” trên DC xác đnh các đc tính liên quan đn d ng th c th c hi n thao tác v . Thơng qua m t s hàm cĩ liên quan, ta cĩ th thi t l p ho c l y xem các thu c tính nào đĩ, ch ng h n ta dùng hàm SetTextColor đ thay đi màu s c c a v ăn b n s đưc v trên màn hình b ng hàm DrawText . 5 Các hàm thao tác các “ đi t ưng” GDI Trong ph n ti p theo, chúng ta s tìm hi u k hơn các “ đi t ưng” mà thơng qua chúng, chúng ta cĩ th thay đi cách th hi n các thơng tin đ 75
  3. ha khác nhau lên DC. M c đnh thì trên DC luơn “cĩ” các đi t ưng GDI v i các “thơng s ” nào đĩ, và chúng ta cĩ th thay đi các “thơng s ” c a chúng khi mu n thay đi k t qu th hi n thao tác v . Ch ng h n, v i m t DC ta luơn th hi n đ dày và màu s c nét v đưng th ng thơng qua đi t ưng bút v (pen), và nh ư th nu ta mu n v vi m t nét v khác thì ph i dùng đi t ưng bút v mi. Các hàm mà chúng ta đang đ cp đây s giúp “thay đi” đi t ưng bút v ho c các đi t ưng đ ha khác trên DC. 4.1.3. Các đi t ưng đ ha c ơ b n Các d ng đ ha th hi n trên màn hình ho c máy in đưc phân thành m t s dng, g i là các đi t ưng “c ơ b n”, d a trên các đc đim riêng c a chúng. 6 Các đi t ưng đưng và cung ðưng ( line ) là thành ph n n n t ng c a các h th ng đ ha vector. GDI h tr các d ng đưng nh ư đưng th ng, hình ch nh t, ellipse, cung ellipse, đưng cong Bezier, polyline, Các d ng đưng này khi đưc g i v bng các thao tác v s s dng thơng tin bút v (pen ) đang đưc ch n trong DC. 7 Các đi t ưng vùng tơ Vi b t c mt vùng khép kín nào t o b i các đưng và cung, ta đu cĩ th tơ v i đi t ưng ch i tơ ( brush ) hi n ti trong DC. Các d ng tơ g m cĩ tơ đc ( solid ), tơ theo m u ( pattern ) ho c ph đy b ng cách l p l i m t nh bitmap nào đĩ trên tồn vùng tơ. 8 ði t ưng nh bitmap Mt bitmap là m t m ng ch nh t các bit d li u t ươ ng ng các pixel nh th hi n trên thi t b hi n th . Khác v i đi t ưng đưng, bitmap là thành ph n n n t ng ca d ng đ ha đim ( raster graphics ). Thơng th ưng, khi nh c đn bitmap, chúng ta s d dàng ngh ĩ ngay đn đĩ là đi t ưng nh th c t th hi n th hi n trên thi t b hi n th . Tuy nhiên, bên c nh đĩ, các đi t ưng nh ư icon, cursor, c ũng là các đi t ưng bitmap. GDI h tr hai d ng bitmap, d ng th nh t là bitmap ph thu c thi t b (device-dependent ), đây là dng bitmap g n li n v i phiên b n đu tiên c a Windows, và v n đưc dùng trong các ng dng sau này. Trong ph m vi mơn h c, chúng ta ch thao tác d ng bitmap này. D ng th hai đưc g i là bitmap đc l p thi t b (DIB – Device Independent Bitmap ), đưc đư a vào t phiên b n Windows 3.0. D ng bitmap này cĩ th đưc l ưu (theo c u trúc riêng) và n p vào các ng d ng t tp tin. Khi l p trình, Windows c ũng h tr chúng ta chuy n đi hai d ng bitmap này v i nhau (v i m t vài “m t mát” thơng tin). 9 ði t ưng v ăn b n Khơng gi ng các đi t ưng đ ha trên, đi t ưng v ăn b n là m t đi tưng khá ph c t p. ð th hi n v ăn b n d ưi các d ng khác nhau, chúng ta c n s dng các cu trúc font đưc đnh ngh ĩa tr ưc. Các c u trúc này là t ươ ng đi l n. Trong ph m vi mơn hc, chúng ta khơng thao tác các d ng font ch , mà ch bàn đn cách g i hàm đ th hi n n i dung v ăn b n ra thi t b xu t. Ngồi các đi t ưng c ơ b n trên, chúng ta cịn cĩ các đi t ưng GDI khác bao g m mapping modes and transforms (ch đ ánh x đim nh), metafiles , regions (vùng), paths (t p h p đưng), clipping (vùng c t), palettes (b ng màu) và printing (đi t ưng in n). Trong ph m vi 76
  4. mơn h c chúng ta khơng tìm hi u thao tác v i các đi t ưng này. Hình 4.2. Quy trình th c hi n thao tác đ ha trên DC hi n th 4.1.4. Quy trình thao tác các đi t ưng đ ha Vi mơ hình hình 4.1, chúng ta đã n m đưc cách mà Windows th c hi n các thao tác đ ha, nh ưng đĩ ch là mơ hình lý thuy t. Trong ph n này chúng ta s gi i quy t cách cài đt code c a mt thao tác đ ha theo quy trình chung th hi n trên mơ hình hình 4.2. Cơng vi c đu tiên c n ph i làm là làm sao cĩ đưc DC c a c a s cn th hi n d li u đ ha, và sau đĩ t t c các hàm đ ha đu s thao tác lên trên DC này. Th t ra, quy trình mà chúng ta đang tìm hi u ch nĩi đn vi c th hi n d li u ra thi t b hi n th video, và chúng ta ch thao tác DC c a d ng thi t b này. N u xét v DC thì Windows cung cp cho chúng ta b n lo i khác nhau: DC hi n th (Display DC ), DC vùng nh (Memory DC ), DC in n ( Printer DC ) và DC thơng tin ( Information DC ). Tu ỳ theo yêu c u ph i qu n lý và thao tác mà chúng ta c n dùng các d ng DC khác nhau thơng qua các hàm khác nhau. ði v i mơn hc này, chúng ta ch thao tác hai d ng DC liên quan t i vi c hi n th d li u lên thi t b video là DC hi n th và DC vùng nh . Vi các thao tác đ ha c ơ b n nh ư xu t v ăn b n (xem ph n 4.2) và thao tác bút v , ch i tơ (xem ph n 4.3), chúng ta ch thao tác lên DC hi n th . Thao tác nh n và gi i phĩng DC hi n th cĩ th đưc th c hi n theo hai cách: 1 Dùng thơng đip WM_PAINT Thơng đip WM_PAINT đưc g i khi h th ng ho c m t ng d ng yêu c u th c hi n thao tác v (paint) l i m t vùng c a s ng d ng. Và vì v y, nu ta mu n th hi n k t qu đ ha lên c a s ng d ng thì ta ch vi c vi t code t i thơng đip này. Trong tr ưng h p này, đ ly DC ta dùng hàm BeginPaint và đ gi i phĩng DC ta dùng hàm EndPaint . HDC BeginPaint (HWND hWnd , LPPAINTSTRUCT lpPaint ); BOOL EndPaint(HWND hWnd , CONST PAINTSTRUCT * lpPaint ); Vi hWnd là ch danh c a c a s cn v , lpPaint tr đn c u trúc PAINSTRUCT xác đnh thơng tin v . 2 Khơng dùng WM_PAINT Bt k ỳ đâu trong ng d ng, ch cn cĩ ch danh hWnd ca ca s , ta đu cĩ th dùng hàm GetDC ho c GetWindowDC đ nh n DC, sau đĩ dùng hàm ReleaseDC đ gi i phĩng DC. HDC GetDC (HWND hWnd ); HDC GetWindowDC (HWND hWnd ); int ReleaseDC( HWND hWnd , HDC hDC ); 77
  5. Hàm GetDC và GetWindowDC khác nhau vi c hàm GetDC tr v DC ch ca vùng client area, trong khi hàm GetWindowDC tr v DC c a tồn c a s , bao g m c thanh tiêu đ, menu Mi DC đu cĩ s n các đi t ưng GDI bên trong nĩ. Khi th c hi n m t thao tác v nào đĩ, Windows s dng các đi t ưng m c đnh đang cĩ. Tuy nhiên, ta c ũng cĩ th lp trình t o m i các đi t ưng khác. Trong các ph n ti p theo, chúng ta s tìm hi u cách t o l p m t s đi t ưng thơng qua các ví d . M t đi t ưng GDI khi mu n đư a vào DC, ta dùng hàm SelectObject , hàm này thao tác chung cho t t c các đi t ưng GDI ( HGDIOBJ ), và vì th khi l p trình thao tác cho d ng đi t ưng c th nào đĩ, ta c n ép ki u (cast) đi t ưng t ươ ng ng (xem thêm các ví d). Sau khi s dng xong đi t ưng GDI, ta ch vi c dùng hàm DeleteObject đ hu b. HGDIOBJ SelectObject(HDC hDC , HGDIOBJ hGDIObj ); BOOL DeleteObject(HGDIOBJ hObject ); 4.2. THAO TÁC V ĂN B N Chúng ta s tìm hi u thao tác v văn b n thơng qua ch ươ ng trình minh ha cách th hi n dịng ch “Hello World!” lên màn hình ng d ng v i màu s c và v trí dịng ch đưc ng ưi dùng ch n t menu. 4.2.1. T o l p project VanBan và tài nguyên menu Vi các project tr ưc đây, chúng ta đã bi t là khi t o m i ng d ng Win32 Application và ch n dng t o là A typical “Hello World!” application, thì ch ươ ng trình khi th c hi n s th hi n dịng ch “Hello World!” màu đen n m gi a và trên c a vùng làm vi c ( client area ). Ta c ũng t o l p project VanBan theo d ng này, sau đĩ vào ResourceView ch n menu IDC_VANBAN đ thêm m t s menu item nh ư sau: 3 Thêm popup menu Color vi các item là Black (IDM_BLACK), Red (IDM_RED), Green (IDM_GREEN) và Blue (IDM_BLUE). 4 Thêm popup menu Alignment vi các item là Left (IDM_LEFT), Center (IDM_CENTER) và Right (IDM_RIGHT). 4.2.2. Vi t code x lý cho ng d ng Nh ư đã tìm hi u trong bài 2, đ ch ươ ng trình th c hi n m t thao tác nào đĩ khi ng ưi dùng ch n các menu item, ta ch vi c vào ch n đnh danh c a chúng thơng qua giá tr LOWORD(wParam) ca thơng đip WM_COMMAND và vi t code thao tác t ươ ng ng. Tuy nhiên ng d ng này, thao tác c a chúng ta là th hi n l i v ăn b n lên DC c a ng d ng khi ng ưi dùng ch n các menu item v màu s c và d ng canh l , và trong tr ưng h p này thì th c hi n thao tác qua thơng đip WM_PAINT . Do đĩ, đ làm điu này ta l i d ng hàm InvalidateRect vi m c đích hàm này s “g i” yêu c u th c hi n thơng đip WM_PAINT c a c a s hWnd tươ ng ng. 78
  6. BOOL InvalidateRect(HWND hWnd , CONST RECT* lpRect , BOOL bErase ); Xét đon code th c hi n thao tác xu t v ăn b n t i thơng đip WM_PAINT . ð xu t m t đon v ăn b n ra DC ta dùng hàm DrawText , hàm này th hi n chu i lpString lên vùng hình ch nh t lpRect ca hDC vi d ng canh l thi t l p qua uFormat. int DrawText(HDC hDC , LPCTSTR lpString , int nCount , LPRECT lpRect , UINT uFormat ); Vi ng d ng này, ta dùng ba d ng canh l vi giá tr uFormat bng DT_LEFT, DT_CENTER, và DT_RIGHT cho các yêu c u th hi n v ăn b n trái, gi a và bên ph i lpRect . Nh ư v y, m i l n ta ch n các menu item canh l thì ta ph i làm sao đĩ chuy n đưc thơng s tươ ng ng đn cho uFormat. Trong tr ưng h p này ta cĩ th dùng m t bi n ph dng tồn c c (global), ho c t ĩnh (static) nh ư bi n nAlign bên trong hàm WndProc . V vi c thay đi màu c a v ăn b n, ta c ũng th c hi n tươ ng t , s dng bi n crColor vi màu mc đnh là màu đen RGB(0,0,0). Hàm SetTextColor là d ng hàm thay đi thu c tính v màu s c v ăn b n c n xu t c a DC. COLORREF SetTextColor(HDC hdc , COLORREF crColor ); Vi nh ng thao tác nh ư trên, ta cĩ đon code hàm WndProc ca ng d ng VanBan trong tp tin VanBan.cpp nh ư sau (các ph n khác trong t p tin này khơng c n thay đi). 1 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, 2 LPARAM lParam) 3 { 4 int wmId, wmEvent; 5 PAINTSTRUCT ps; 6 HDC hdc; 7 TCHAR szHello[MAX_LOADSTRING]; 8 LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING); 9 COLORREF crOldColor; 10 static COLORREF crColor = RGB(0, 0, 0); 11 static UINT nAlign = DT_CENTER; 12 13 switch (message) 14 { 15 case WM_COMMAND: 16 wmId = LOWORD(wParam); 17 wmEvent = HIWORD(wParam); 18 // Parse the menu selections: 19 switch (wmId) 20 { 21 case IDM_BLACK: 22 crColor = RGB(0, 0, 0); 23 break; 24 case IDM_RED: 25 crColor = RGB(255, 0, 0); 26 break; 27 case IDM_GREEN: 28 crColor = RGB(0, 255, 0); 29 break; 30 case IDM_BLUE: 31 crColor = RGB(0, 0, 255); 32 break; 33 case IDM_LEFT: 34 nAlign = DT_LEFT; 79
  7. 35 break; 36 case IDM_CENTER: 37 nAlign = DT_CENTER; 38 break; 39 case IDM_RIGHT: 40 nAlign = DT_RIGHT; 41 break; 42 case IDM_ABOUT: 43 DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, 44 (DLGPROC)About); 45 break; 46 case IDM_EXIT: 47 DestroyWindow(hWnd); 48 break; 49 default: 50 return DefWindowProc(hWnd, message, wParam, 51 lParam); 52 } 53 InvalidateRect(hWnd, NULL, TRUE); 54 break; 55 case WM_PAINT: 56 hdc = BeginPaint(hWnd, &ps); 57 // TODO: Add any drawing code here 58 crOldColor = SetTextColor(hdc, crColor); 59 RECT rt; 60 GetClientRect(hWnd, &rt); 61 DrawText(hdc, szHello, strlen(szHello), &rt, nAlign); 62 SetTextColor(hdc, crOldColor); 63 EndPaint(hWnd, &ps); 64 break; 65 case WM_DESTROY: 66 PostQuitMessage(0); 67 break; 68 default: 69 return DefWindowProc(hWnd, message, wParam, lParam); 70 } 71 return 0; 72 } 4.3. THAO TÁC ðI T ƯNG BÚT V , CH I TƠ So v i quy trình chung th c hi n thao tác các đi t ưng đ ha hình 4.2, vi c th hi n v ăn b n mà chúng ta v a th c hi n khơng nĩi gì đn vi c t o l p và đư a m t đi t ưng GDI (n u cĩ s là font ch ) vào DC mà ch s dng thơng tin m c đnh. Vì th , trong ph n này chúng ta s tìm hi u thêm thao tác đi v i đi t ưng GDI, đng th i tìm hi u cách xu t các đi t ưng đưng, cung và vùng tơ ra thi t b hi n th . 80
  8. Hình 4.3. Kt qu sau khi ng ưi dùng ch n ch c n ăng Ellipse Chúng ta s th c hi n ví d v mt ng d ng cho phép ng ưi dùng ch n menu đ th hi n gi a vùng làm vi c mt đưng th ng, hình ch nh t, ho c m t ellipse v i kích th ưc cho tr ưc và màu s c c ũng đưc ch n t menu - xem hình 4.3. 4.2.1. T o lp project VeHinh và tài nguyên menu Tươ ng t ng d ng v văn b n, chúng ta t o l p project Win32 Application v i tên là VeHinh , dng A typical “Hello World!” application . Sau đĩ ch n menu IDC_VEHINH trong ResourceView và thêm các menu item nh ư sau: 5 Thêm popup menu Shape vi các item là Line (IDM_LINE), Rectangle (IDM_RECTANGLE), và Ellipse (IDM_ELLIPSE). 6 Thêm popup menu Color vi các item là Black (IDM_BLACK), Red (IDM_RED), Green (IDM_GREEN) và Blue (IDM_BLUE). 4.3.2. Vi t code x lý cho ng d ng Tương t ng d ng VanBan , chúng ta vi t code t i thơng đip WM_COMMAND đ x lý cho các thao tác menu item. Ta c ũng dùng bi n t ĩnh crColor ki u COLORREF đ lưu giá tr màu cn v ; dùng bi n int nShape đ lưu d ng hình v , v i các giá tr đt là 1, 2, 3 ng v i d ng hình v là đưng th ng, hình ch nh t và ellipse. Sau khi đã thi t l p các giá tr s dùng đ v hình, c ũng nh ư ng d ng VanBan , ta dùng hàm InvalidateRect đ kích ho t thơng đip WM_PAINT ca c a s chính. Quy trình bên trong thơng đip WM_PAINT đúng nh ư mơ hình hình 4.2. ðu tiên ng dng l y DC b ng hàm BeginPaint , sau đĩ t o l p bút v hPen và ch i tơ hBrush theo màu đã ch n (m c đnh là màu đen) r i đư a vào DC b ng hàm SelectObject . Ti p theo ng d ng c ăn c vào giá tr ca nShape đ th c hi n thao tác v . đây ta dùng m t s hàm API đã đưc 81
  9. Windows cung c p nh ư LineTo , Rectangle , Trong tr ưng h p th c hi n các thao tác đ ha khác ta cĩ các hàm khác, vì th cn tra c u trong MSDN. Cu i cùng, ta ch n l i các đi t ưng GDI ban đu, h y các đi t ưng t o l p tr ưc đĩ b ng hàm DeleteObject , và k t thúc thơng đip WM_PAINT vi hàm EndPaint . Sau đây li t kê prototype các hàm dùng trong ng d ng VeHinh . Hàm CreatePen to l p đi t ưng bút v HPEN theo ki u v fnPenStyle (PS_SOLID , PS_DASH , PS_DOT , ), đ dày nét v nWidth và màu v crColor . HPEN CreatePen (int fnPenStyle , int nWidth , COLORREF crColor ); Hàm CreateSolidBrush to l p đi t ưng ch i tơ đc (solid) v i màu tơ crColor . HBRUSH CreateSolidBrush (COLORREF crColor ); Hàm SelectObject đư a m t đi tưng HGDIOBJ (là bút v HPEN , ch i tơ HBRUSH , font ch HFONT , ) vào DC và tr v đi t ưng c ũ tươ ng ng trong DC. HGDIOBJ SelectObject (HDC hdc , HGDIOBJ hgdiobj ); Hàm DeleteObject hy m t đi t ưng GDI đã đưc t o l p tr ưc đĩ và khơng c n dùng n a. BOOL DeleteObject (HGDIOBJ hObject ); Hàm GetClientRect nh n thơng tin t a đơ c a c a s hWnd và chuy n thơng tin đĩ vào c u trúc hình ch nh t lpRect. BOOL GetClientRect (HWND hWnd , LPRECT lpRect ); Hàm MoveToEx thi t l p l i v trí đim v đn t a đ X, Y và tr v đim v cũ vào bi n lpPoint . BOOL MoveToEx (HDC hdc , int X, int Y, LPPOINT lpPoint ); Hàm LineTo s dng các thơng s ca bút v hi n t i đ v mt đưng th ng t v trí đim v hi n t i đn nXEnd , nYEnd . BOOL LineTo (HDC hdc , int nXEnd , int nYEnd ); Cu i cùng là hàm v hình ch nh t và ellipse n i ti p hình ch nh t cĩ v trí gĩc trái, trên, ph i và d ưi xác đnh b i các tham s nLeftRect , nTopRect , nRightRect , nBottomRect . BOOL Rectangle (HDC hdc , int nLeftRect , int nTopRect , int nRightRect , int nBottomRect ); BOOL Ellipse (HDC hdc , int nLeftRect , int nTopRect , int nRightRect , int nBottomRect ); Và đây là đon code hàm WndProc ca ng d ng VeHinh . 1 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, 2 LPARAM lParam) 3 { 4 int wmId, wmEvent; 5 PAINTSTRUCT ps; 6 HDC hdc; 82
  10. 7 static int nShape = 1; // 1: Line; 2: Rectangle; 3: Ellipse 8 static COLORREF crColor = RGB(0, 0, 0); 9 HPEN hPen, hOldPen; 10 HBRUSH hBrush, hOldBrush; 11 RECT rt; 12 POINT ptCenter; 13 14 switch (message) 15 { 16 case WM_COMMAND: 17 wmId = LOWORD(wParam); 18 wmEvent = HIWORD(wParam); 19 // Parse the menu selections: 20 switch (wmId) 21 { 22 case IDM_LINE: 23 nShape = 1; 24 break; 25 case IDM_RECTANGLE: 26 nShape = 2; 27 break; 28 case IDM_ELLIPSE: 29 nShape = 3; 30 break; 31 case IDM_BLACK: 32 crColor = RGB(0, 0, 0); 33 break; 34 case IDM_RED: 35 crColor = RGB(255, 0, 0); 36 break; 37 case IDM_GREEN: 38 crColor = RGB(0, 255, 0); 39 break; 40 case IDM_BLUE: 41 crColor = RGB(0, 0, 255); 42 break; 43 case IDM_ABOUT: 44 DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, 45 (DLGPROC)About); 46 break; 47 case IDM_EXIT: 48 DestroyWindow(hWnd); 49 break; 50 default: 51 return DefWindowProc(hWnd, message, wParam, 52 lParam); 53 } 54 InvalidateRect(hWnd, NULL, TRUE); 55 break; 56 case WM_PAINT: 57 hdc = BeginPaint(hWnd, &ps); 58 59 hPen = CreatePen(PS_SOLID, 1, crColor); 60 hBrush = CreateSolidBrush(crColor); 61 hOldPen = (HPEN)SelectObject(hdc, hPen); 62 hOldBrush = (HBRUSH)SelectObject(hdc, hBrush); 63 64 GetClientRect(hWnd, &rt); 65 ptCenter.x = (rt.left+rt.right)/2; 66 ptCenter.y = (rt.top+rt.bottom)/2; 67 68 switch(nShape) 69 { 70 case 1: 71 MoveToEx(hdc, ptCenter.x100, ptCenter.y50, NULL); 72 LineTo(hdc, ptCenter.x+100, ptCenter.y+50); 73 break; 83
  11. 74 case 2: 75 Rectangle(hdc, ptCenter.x100, ptCenter.y50, 76 ptCenter.x+100, ptCenter.y+50); 77 break; 78 case 3: 79 Ellipse(hdc, ptCenter.x100, ptCenter.y50, 80 ptCenter.x+100, ptCenter.y+50); 81 break; 82 } 83 84 SelectObject(hdc, hOldPen); 85 SelectObject(hdc, hOldBrush); 86 DeleteObject(hPen); 87 DeleteObject(hBrush); 88 89 EndPaint(hWnd, &ps); 90 break; 91 case WM_DESTROY: 92 PostQuitMessage(0); 93 break; 94 default: 95 return DefWindowProc(hWnd, message, wParam, lParam); 96 } 97 return 0; 98 } 4.4. THAO TÁC NH BITMAP Trong hai ph n v a tìm hi u, chúng ta đã thao tác các đi t ưng đưng và cung , vùng tơ và văn bn. ði t ưng GDI c ơ b n cịn l i là nh bitmap . Tuy nhiên, khác v i các đi t ưng trên, các thao tác đi v i đi t ưng nh bitmap ph c t p h ơn. Ngồi đi t ưng Display DC c a c a s , chúng ta c n thêm đi t ưng DC vùng nh (Memory DC) dùng đ lưu nh cùng các thao tác liên quan tr ưc khi chuy n nh qua Display DC th t s . Sau đây chúng ta s tìm hi u hai quy trình liên quan đn nh bitmap là np - hi n th và zoom nh . 4.4.1. N p và hi n th nh bitmap Nh ư đã gi i thi u trên, m t bitmap là m t m ng ch nh t các bit d li u t ươ ng ng các pixel nh th hi n trên thi t b hi n th , đưc qu n lý trên t p tin thơng qua format riêng (bmp) và khi cn thì n p vào ng d ng và hi n th (DIB), ho c là d li u cĩ s n trong ng d ng và khi c n thì hi n th (DDB). Ta cĩ quy trình n p và hi n th mt nh bitmap nh ư hình 4.4. Hình 4.4. Quy trình n p và hi n th nh bitmap Cũng gi ng nh ư quy trình thao tác đ ha t ng quát (hình 4.2), đ hi n th nh bitmap lên mt c a s , ta c n l y DC c a c a s đĩ – trong quy trình trên minh h a b ng hàm GetDC . Ta cũng c n t o l p đi t ưng GDI - nh bitmap HBITMAP - bng cách n p t tài nguyên b ng hàm LoadBitmap ho c đc t tp tin b t k ỳ (tuy nhiên, đây ta s khơng thao tác v i t p tin). Sau đĩ ta c ũng đư a nh vào DC thơng qua hàm SelectObject . Nu ch nh ư v y thì quy trình hồn tồn gi ng quy trình chung cho các đi t ưng đ ha. Th nh ưng đây chúng ta khơng th c hi n nh ư v y. Thay vì đư a nh vào Display DC c a c a s , ta 84
  12. đư a nh vào m t DC o khác (d ng DC vùng nh ). ðiu này nh m giúp vi c th c hi n thao tác chuy n nh vào DC v n khá ch m s khơng di n ra trên màn hình (s gây ch p) mà di n ra trên DC o. Và vì th ta c n t o đi t ưng DC này. Ta s dng hàm CreateCompatibleDC đ to mt DC o cĩ các thơng s gi ng DC c a c a s đã cĩ r i ch n đi t ưng nh HBITMAP vào DC o này. Cu i cùng ta dùng hàm BitBlt đ chuy n nh t DC o sang Display DC đ th hi n trên c a s . Prototype c a các hàm LoadBitmap , CreateCompatibleDC và BitBlt nh ư sau: Hàm LoadBitmap np nh xác đnh thơng qua tên lpBitmapName trong tài nguyên vào ng dng hInstance . K t qu tr v là ch danh đi t ưng bitmap HBITMAP . HBITMAP LoadBitmap (HINSTANCE hInstance , LPCTSTR lpBitmapName ); Hàm CreateCompatibleDC to l p đi t ưng DC vùng nh da trên đi t ưng DC hdc ban đu. Và hàm HDC CreateCompatibleDC (HDC hdc ); Và hàm chuy n nh t DC ngu n hdcSrc xét t v trí nXSrc, nYSrc sang DC đích hdcDest ti v trí nXDest, nYDest vi kích th ưc là nWidth, nHeight . Tham s cu i cùng dwRop xác đnh dng chuy n d li u: 1 SRCCOPY : copy vùng ch nh t nh ngu n th ng sang nh đích. 2 SRCAND : k t h p giá tr màu t ng đim nh ngu n và đích b ng tốn t AND. 3 SRCPAINT : k t h p b ng tốn t OR. 4 Các giá tr khác c a dwRop xin xem trong MSDN BOOL BitBlt (HDC hdcDest , int nXDest , int nYDest , int nWidth , int nHeight , HDC hdcSrc , int nXSrc , int nYSrc , DWORD dwRop ); Sau đây là m t ví d minh h a thao tác xu t nh bitmap trên c a s chính c a ng d ng. ng dng này cho phép ng ưi dùng ch n th hi n m t vài hình nh cĩ s n trong tài nguyên ra chính gi a màn hình. ðu tiên ta c ũng t o l p project Win32 Application d ng A typical “Hello World!” application cĩ tên là XuatAnh , sau đĩ xây d ng popup menu Bitmap vi các menu item đi di n cho các nh s ch n th hi n. đây tơi minh h a v i ba nh bitmap, và tơi t o ba menu item là Elephant (IDM_ELEPHANT), Pine (IDM_PINE) và Mushroom (IDM_MUSHROOM). Song song v i vi c t o l p menu, ta c ũng t o l p các nh trong resource. Chúng ta cĩ th Insert Bitmap ho c Import các t p tin nh bitmap vào tài nguyên project. Ba đi t ưng nh bitmap đưc đt tên t ươ ng ng là IDB_ELEPHANT, IDB_PINE, và IDB_MUSHROOM - xem hình 4.5. 85
  13. Sau khi đã t o l p tài nguyên, ta s vi t code th c hi n các thao tác hi n th các nh bitmap trên khi ng ưi dùng ch n menu t ươ ng ng c a ng d ng. Hình 4.5. Tài nguyên nh bitmap IDB_ELEPHANT Cũng nh ư các project trên, khi ng ưi dùng ch n các menu item, ta cĩ th dùng m t bi n t ĩnh đ lưu l i giá tr xác đnh nh tươ ng ng. Nh n th y r ng đnh danh c a nh là m t h ng s đưc đnh ngh ĩa tr ưc (IDB_ELEPHANT, ) do đĩ ta đt bi n nh là nIDB , và thi t l p v i các giá tr tươ ng ng, r i dùng hàm InvalidateRect đ “g i” thơng đip WM_PAINT th hi n nh lên màn hình. Bên trong thơng đip WM_PAINT , ta vi t code theo đúng quy trình hi n th mt nh bitmap (n p t resource) lên c a s chính c a ng d ng. Ngồi các hàm và ki u d li u đã li t kê trên, đ cĩ kích th ưc nh nh m th hi n đưc nh chính gi a màn hình, ta dùng thêm c u trúc BITMAP và l y thơng tin nh DDB qua hàm GetObject . typedef struct tagBITMAP { LONG bmType ; LONG bmWidth ; // Chi u r ng c a nh LONG bmHeight ; // Chi u cao c a nh LONG bmWidthBytes ; WORD bmPlanes ; WORD bmBitsPixel ; LPVOID bmBits ; } BITMAP , * PBITMAP ; int GetObject ( HGDIOBJ hgdiobj , // Tr đn đi t ưng GDI 86
  14. int cbBuffer , // Kích th ưc đi t ưng LPVOID lpvObject // Vùng đm thơng tin đi t ưng ); Và đây là đon code hàm WndProc ca ng d ng XuatAnh . 1 LRESULT CALLBACK WndProc(HWND hWnd, UINT me ssage, WPARAM wParam, 2 LPARAM lParam) 3 { 4 int wmId, wmEvent; 5 PAINTSTRUCT ps; 6 static int nIDB = IDB_ELEPHANT; // ID cua bitmap trong resource 7 HDC hdc, hdcMem; 8 HBITMAP hBitmap; 9 BITMAP bitmap; 10 RECT rt; 11 POINT ptOrgBmp; 12 13 switch (message) 14 { 15 case WM_COMMAND: 16 wmId = LOWORD(wParam); 17 wmEvent = HIWORD(wParam); 18 // Parse the menu selections: 19 switch (wmId) 20 { 21 case IDM_ELEPHANT: 22 nIDB = IDB_ELEPHANT; 23 break; 24 case IDM_PINE: 25 nIDB = IDB_PINE; 26 break; 27 case IDM_MUSHROOM: 28 nIDB = IDB_MUSHROOM; 29 break; 30 case IDM_ABOUT: 31 DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, 32 (DLGPROC)About); 33 break; 34 case IDM_EXIT: 35 DestroyWindow(hWnd); 36 break; 37 default: 38 return DefWindowProc(hWnd, message, wParam, 39 lParam); 40 } 41 InvalidateRect(hWnd, NULL, TRUE); 42 break; 43 case WM_PAINT: 44 hdc = BeginPaint(hWnd, &ps); 45 hdcMem = CreateCompatibleDC(hdc); 46 47 hBitmap = LoadBitmap(hInst, MAKEINTRESOURCE(nIDB)); 48 GetObject(hBitmap, sizeof(BITMAP), &bitmap); 49 SelectObject(hdcMem, hBitmap); 50 51 GetClientRect(hWnd, &rt); 52 ptOrgBmp.x = (rt.left + rt.right bitmap.bmWidth)/2; 53 ptOrgBmp.y = (rt.top + rt.bottom bitmap.bmHeight)/2; 54 55 BitBlt(hdc, ptOrgBmp.x, ptOrgBmp.y, bitmap.bmWidth, 56 bitmap.bmHeight, hdcMem, 0, 0, SRCCOPY); 57 58 DeleteDC(hdcMem); 87
  15. 59 EndPaint(hWnd, &ps); 60 break; 61 case WM_DESTROY: 62 PostQuitMessage(0); 63 break; 64 default: 65 return DefWindowProc(hWnd, message, wParam, lParam); 66 } 67 return 0; 68 } 4.4.2. Thao tác zoom nh bitmap ði v i các ng d ng v nh, ngồi vi c th hi n nh v i đúng kích th ưc, đơi lúc chúng ta c ũng cn phĩng l n hay thu nh nh đ quan sát t t h ơn. ð làm điu này, chúng ta th c hi n m t quy trình c ũng t ươ ng t nh ư quy trình hi n th nh. Hình 4.6 trình bày mơ hình quy trình này. Hình 4.6. Quy trình zoom nh bitmap ð zoom (phĩng l n ho c thu nh ) m t đi t ưng nh lên m t c a s , ta c ũng n p nh t tài nguyên (ho c t o l p) và l y DC c a c a s nh ư đã làm trong quy trình hi n th nh. Sau đĩ t o lp thêm hai DC vùng nh (thay vì m t nh ư trong quy trình hi n th ), đt là DC ngu n và DC đích. DC ngu n s ch a nh HBITMAP n p t tài nguyên trên và đư a vào b ng hàm SelectObject . DC đích ch a m t nh “tr ng” đưc t o l p b ng hàm CreateCompatibleBitmap da trên đnh d ng c a nh trong Display DC c a c a s , và c ũng n p vào t ươ ng t bng hàm SelectObject . Sau khi cĩ hai DC vùng nh ch a nh bitmap, ta dùng hàm StretchBlt đ zoom nh t DC ngu n sang DC đích. Cu i cùng ta ch vi c chuy n nh đã đưc zoom v Display DC ca c a s bng hàm BitBlt nh ư đã bi t. Hàm CreateCompatibleBitmap to l p m t bitmap cĩ kích th ưc nWidth x nHeight (pixels) tươ ng thích v i đi t ưng xác đnh hdc . HBITMAP CreateCompatibleBitmap (HDC hdc , int nWidth , int nHeight ); Tươ ng t hàm BitBlt , nh ưng thay vì chuy n nh t DC ngu n hdcSrc sang DC đích hdcDest vi cùng m t kích th ưc, hàm StretchBlt chuy n nh v i kích th ưc ngu n nWidthSrc , nHeightSrc sang kích th ưc đích nWidthDest, nHeightDest . BOOL StretchBlt (HDC hdcDest , int nXOriginDest , int nYOriginDest , int nWidthDest , int nHeightDest , HDC hdcSrc , int nXOriginSrc , int nYOriginSrc , int nWidthSrc , int nHeightSrc , DWORD dwRop ); Chúng ta v a tìm hi u lý thuy t quy trình zoom nh bitmap, ví d c th s đưc minh h a bài h c ti p theo. 4.5. TĨM T T 88
  16. Thơng qua quy trình hi n th văn b n – ph n 4.2, quy trình th c hi n thao tác v cơ b n v i bút v và ch i tơ – ph n 4.3, và quy trình hi n th và zoom nh bitmap – ph n 4.4, chúng ta đã hi u rõ cách th c l p trình đ xu t d li u đ ha ra đi t ưng thi t b ng cnh. Tuy nhiên chúng ta m i ch thao tác các đi t ưng đ ha khá đơ n gi n. Vì th , đ th c hi n các thao tác đ ha đi v i b t k ỳ đi t ưng nào theo quy trình chung đã đưc h c – ph n 4.1.4 – ta c n kt h p tra c u tồn di n v Windows GDI, Platform SDK Documentation trên MSDN. 4.6. CÂU H I ƠN T P – BÀI T P 4.6.1. Trình bày t ng quát v cơ ch GDI c a Windows? Mơ hình ho t đng GDI? S khác bi t khi th hi n hình nh trên ng d ng c a Windows so v i trên MS-DOS? 4.6.2. Thi t b Ng cnh (Device Context) là gì (xét mc l p trình)? Gi i thi u ng n g n v các đi t ưng GDI? Các nhĩm hàm liên quan v đ ha GDI? 4.6.3. Trình bày quy trình th c hi n thao tác đ ha trên thi t b hi n th ? Áp d ng quy trình này vào vi c th hi n v ăn b n, v hình và xu t nh lên c a s ng d ng? 4.6.4*. Tìm hi u m t trong các đi t ưng GDI ph c t p nh ư Color (Palette), Font, trên MSDN. Ki n th c t ng quan? Các c u trúc liên quan? Các nhĩm hàm và thơng đip Windows h tr ? Vi c áp d ng khi l p trình cho các ng d ng? 4.6.5. Vi t ch ươ ng trình th hi n dịng ch “This is a sample text!” nm gi a c a s chính v i màu s c do ng ưi dùng ch n qua các nút nh n (m c đnh là màu đ) – xem hình 4.7. Hình 4.7. Ch ươ ng trình xu t ch vi màu ch n qua nút nh n. Hình 4.7 Ch ươ ng trình xu t ch vi màu ch n qua nút nh n Hưng d n: Ta cĩ th dùng hàm CreateWindow đ to 3 nút nh n static (l p “BUTTON”) trong thơng đip WM_CREATE . Khi ng ưi dùng ch n nút nh n nào, Windows s gi thơng đip WM_COMMAND v i (HWND)lParam là đnh danh c a nút nh n t ươ ng ng, ta vi t code đ xu t l i dịng ch vi màu đã ch n (cĩ th trong thơng đip WM_PAINT). 89
  17. 4.6.6. Vi t ch ươ ng trình th hi n dịng ch gi a c a s chính – hình 4.8a, v i n i dung dịng ch và màu s c do ng ưi dùng nh p vào t hp tho i – hình 4.8b. Hưng d n: Ta t o l p tài nguyên menu và h p tho i nh ư hình trên. Khi ng ưi dùng ch n menu GetText , ta dùng hàm DialogBox đ hi n th hp tho i và chuy n “quy n điu khi n” thơng đip cho h p tho i. Khi ng ưi dùng click ch n các radio button trên h p tho i, ta cĩ th dùng m t bi n tồn c c đ lưu l i thơng tin này. Khi ng ưi dùng ch n nút OK, ta g i d li u text vào m t bi n tồn c c nào đĩ s dng hàm GetDlgItemText , r i đĩng h p tho i b ng hàm EndDialog . Nh n th y r ng khi ch n OK ho c Cancel ta đu đĩng h p tho i, vì th khi EndDialog , ta cĩ th gi giá tr này vào tham s th hai, đĩ c ũng chính là giá tr tr v ca hàm DialogBox , và ta s dng giá tr này đ quy t đnh cĩ th c hi n thao tác th hi n chu i d li u text (tồn c c) v i màu s c (bi n tồn c c đã thi t l p) lên màn hình hay khơng (dùng hàm DrawText ). Hình 4.8. Ch ươ ng trình xu t ch đưc nh p t hp tho i. 4.6.7. Vi t ch ươ ng trình th hi n dịng ch sau khi nh n t hp tho i – hình 4.9b – lên màn hình – hình 4.9a, v i n i dung và d ng canh l do ng ưi dùng ch n. 90
  18. Hình 4.9. Ch ươ ng trình xu t ch theo d ng canh l . Hưng d n: Trong bài t p 4.6.6, chúng ta t o các radio button trên h p tho i v i các thơng s mc đnh, trong đĩ cĩ chúc n ăng t đng check khi ng ưi dùng ch n m t button (trong c nhĩm), tuy nhiên bài này thì khác, chúng ta cĩ hai nhĩm radio button khác nhau, vì th khi t o lp trong tài nguyên, ta b ch n ki u t đng ( Style Auto ) đi. Khi đĩ, vi c vi t code x lý t ươ ng t bài t p trên, nh ưng ta ph i vi t hàm check radio CheckRadioButton ng m i thao tác ch n trên h p tho i. Ngồi ra, đi v i ch ươ ng trình này, nhĩm radio Top , Vertical Center , và Bottom ch cĩ hi u l c khi check box Single Line đưc ch n, vì th ta c n dùng các hàm CheckDlgButton , IsDlgButtonChecked đ check và ki m tra check box cĩ đưc ch n hay khơng; đng th i dùng hàm EnableWindow đ enable hay disable radio button. Cu i cùng, khi ng ưi dùng ch n OK thì ta c ăn c trên tr ng thái (enable, check) ca các radio mà thi t l p giá tr dng canh l (dùng thêm hàm IsWindowEnabled ) theo các c s dùng cho hàm DrawText và ly text g i v cho c s chính và th c hi n gi ng nh ư bài 4.6.6. 4.6.8. Vi t ch ươ ng trình v lên chính gi a màn hình m t hình trịn – hình 4.10a – vi bán kính và màu s c đưc ch n t hp tho i – hình 4.10b. Hình 4.10. Ch ươ ng trình xu t hình trịn gi a màn hình. Hưng d n: ði v i bài này, nên ch n edit text nh n d li u cĩ ki u Number , và nh ư v y ta dùng hàm GetDlgItemInt đ ly giá tr bán kính hình trịn ( Circle Radius ). R i khi th hi n hình trịn, ta t o bút v và ch i tơ theo màu đã ch n và dùng hàm Ellipse đ v hình (sau khi xác đnh đưc v trí c n v ). 91
  19. Bài 5 BÀN PHÍM, THI T B CHU T VÀ B ðNH TH I GIAN Trong các bài h c tr ưc chúng ta đã tìm hi u cách th c x lý các tác đng c a ng ưi dùng lên ng d ng thơng qua các đi t ưng nh ư menu, control v i thơng đip WM_COMMAND , cách th c Windows v li c a s vi thơng đip WM_PAINT , g i thơng đip WM_SIZE khi thay đi kích th ưc c a s . Bài h c này ti p t c cung c p cho chúng ta m t s thơng đip quan tr ng khác v cơ ch Windows x lý tác đng t bàn phím (keyboard ), thi t b chu t (mouse ) và b đnh th i gian (timer ) nh m giúp chúng ta cĩ th xây d ng các ng d ng d ng Win32 Application hi u qu hơn. 5.1. THƠNG ðIP VÀ X LÝ THƠNG ðIP Vi ph n gi i thi u chung bài 1, c ũng nh ư xuyên su t quá trình h c, điu quan tr ng nh t khi lp trình trên Windows là hi u đưc vn đ thơng đip. Chúng ta cĩ th tĩm l ưc l i v n đ này thơng qua mơ hình hình 5.1. Khi ng ưi dùng ho c m t ng d ng tác đng lên m t đi t ưng c a s , thao tác đĩ s đưc chuy n thành d ng thơng tin g i là thơng đip (message ) và đưc chuy n vào hàng đi c a h th ng ( Windows message queue ). M i d ng tác đng s tươ ng ng v i m t mã thơng đip riêng (thơng đip liên quan đn menu, control là WM_COMMAND , liên quan đn thao tác thay đi kích th ưc c a s là WM_SIZE , ). M i thơng đip đưc Windows đnh ngh ĩa là m t c u trúc thơng tin v i nh ng giá tr gi kèm nh ư đnh danh c a c a s (window handle ), hai word g i kèm ( WPARAM và LPARAM ) – xem l i c u trúc thơng đip ph n 1.3.1. – bài 1. Khi đĩ, v i thơng tin v đnh danh c a c a s cĩ đưc, h th ng chuy n thơng đip t ươ ng ng vào hàng đi thơng đip ng d ng ( application message queue ) cho ng d ng qu n lý c a s này – đây chính là vịng l p GetMessage trong hàm WinMain ca m t ng d ng Win32 Application. Hình 5.1. Mơ hình thơng đip trên Windows Thơng qua hàm DispatchMessage , Windows chuy n thơng đip t ươ ng ng đn hàm x lý ca c a s (đưc xác đnh b i đnh danh c a nĩ trong thơng đip) và ta ch vi c nh n thơng đip này trong hàm x lý c a c a s tươ ng ng và vi t code theo yêu c u c a ng d ng. Chúng ta đã quen thu c thao tác này khi vi t code cho các thơng đip WM_COMMAND , WM_PAINT , trong hàm x lý c a s chính WndProc ca m t ng d ng Win32 Application; ho c t ươ ng t là hàm x lý h p tho i (ví d hàm About quen thu c) v i thơng đip WM_INITDIALOG và WM_COMMAND . 92
  20. Ngồi ra, chúng ta c ũng đã bi t cách g i thơng đip cho m t ng d ng b ng hàm SendMessage , PostMessage ho c b ng các c ơ ch h tr riêng c a t ng d ng thơng đip (ví d dùng hàm InvalidateRect tươ ng t vi c “kích ho t” thơng đip WM_PAINT ). Tươ ng t nh ư v y, trong các ph n ti p theo chúng ta s ln l ưt tìm hi u các thơng đip v bàn phím, thi t b chu t và b đnh th i gian v i nh ng ki n th c c ơ b n nh t thơng qua các ví d minh h a. 5.2. THI T B BÀN PHÍM Thi t b nh p li u c ơ b n nh t luơn ph i cĩ khi s dng máy tính là bàn phím ( keyboard ). C ũng tươ ng t nh ư các d ng thao thác khác, khi chúng ta thao tác bàn phím, Windows nh n và x lý chúng d ưi d ng thơng tin thơng đip. Trong ph n này, chúng ta s tìm hi u khái ni m c ơ b n v mơ hình nh p li u bàn phím – ph n 5.2.1, các d ng thơng đip c ơ b n v phím ( key ) và ký t (character ) – ph n 5.2.2 – và các giá tr WPARAM và LPARAM gi kèm – ph n 5.2.3. Cu i cùng là m t ví d minh h a thao tác nh n phím + và - đ phĩng to và thu nh nh bitmap th hi n trên c a s chính c a ng d ng. 5.2.1. N n t ng c ơ s v bàn phím V cơ b n, t ươ ng t cơ ch xu t d li u đc l p thi t b GDI đã h c, Windows c ũng cung c p c ơ ch nh p li u đc l p thi t b (device-independent keyboard ). Thơng qua trình điu khi n thi t b bàn phím đã đưc cài đt, m t thao tác phím s đưc chuy n thành m t d ng mã, g i là mã quét (scan code ) đ gi đn cho ng d ng x lý. Trình điu khi n bàn phím thơng d ch m t mã quét và ánh x thành m t d ng mã khác g i là mã phím o ( virtual-key code ), giá tr mã phím o này đưc h th ng đnh ngh ĩa tr ưc theo m c đích s dng c a phím. Trong ph n tìm hi u các thơng tin g i kèm các thơng đip bàn phím (ph n 5.2.2), chúng ta s tìm hi u chi ti t h ơn. Sau khi d ch mã quét, h th ng keyboard t o l p thơng đip ch a mã quét, mã phím o, cùng ki u gõ và đư a vào hàng đi c a h th ng đ h th ng chuy n đn cho ng d ng theo mơ hình thơng đip hình 5.1. Mt v n đ quan tr ng khi nĩi đn thao tác bàn phím trên Windows c ũng c n tìm hi u là focus . Ai trong chúng ta c ũng đu bi t là m c dù Windows x lý đng th i nhi u ti n trình ng dng ( process ), tuy nhiên mt th i đim thì ch cĩ m t c a s ng d ng đưc xem là đang tr ng thái ho t đng ( active ), cịn các c a s khác đưc xem là khơng ho t đng ( inactive ). N u mt ng d ng đang active (c th hơn là m t c a s trên m t ng d ng active) thì t t c thao tác bàn phím thơng th ưng đu đưc g i cho c a s này. Khi đĩ ta nĩi c a s này đang nh n focus . Chúng ta đã thao tác v vn đ này thơng qua thơng đip WM_SETFOCUS bài 2 khi thi t l p cho edit text nh n t t c các thao tác phím t ng ưi dùng. Thơng đip WM_SETFOCUS đưc Windows g i cho m t c a s nào đĩ sau khi c a s này 93
  21. nh n đưc focus bàn phím. T ươ ng t , thơng đip WM_KILLFOCUS đưc g i cho c a s ngay tr ưc khi c a s này b mt focus. Ta c ũng cĩ th dùng hàm GetFocus và SetFocus đ nh n bi t ca s đang gi focus ho c thi t l p focus cho m t c a s nào đĩ. HWND GetFocus (VOID ); HWND SetFocus (HWND hWnd ); 5.2.2. Các d ng thơng đip bàn 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 mt phím. Khi thao tác nh n mt phím trên bàn phím đưc th c hi n thì Windows s phát sinh thơng đip WM_KEYDOWN hay WM_SYSKEYDOWN và đư a vào hàng đi thơng đip c a ng d ng hay c a s gi focus. Tươ ng t , khi ta nh phím thì thơng đip WM_KEYUP hay WM_SYSKEYUP s đưc h điu hành phân phát t i hàng đi h th ng. Thơng đip 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. Ch ng h n, khi ng ưi dùng nh n phím Alt kt h p v i phím khác, th ưng dùng thao tác m t menu item, control, thì h th ng phát sinh thơng đip WM_SYSKEYDOWN và WM_SYSKEYUP . V i các ng d ng thơng th ưng, chúng ta khơng quan tâm đn các thơng đip này mà ch cn dùng hàm DefWindowProc cu i m i x lý c a s đ Windows x lý m c đnh. Sau đây là b ng mơ t các thơng đip phát sinh t bàn phím (theo th t Alphabet). Bảng 5.1. Mơ t thơng đip phát sinh t bàn phím Thơng đip Nguyên nhân phát sinh Thơng đip này cùng đưc g i đn các ca 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 đip này s đưc truy n m t cách đng b , đu tiên WM_ACTIVATE th tc Windows c a c a s trên cùng b mt kích ho t, sau đĩ đn th tc 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 đip 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 rng ng ưi dùng WM_APPCOMMAND đã t o m t s ki n l nh ng d ng, ví d khi ng ưi dùng kích vào button s dng 94
  22. chu t hay đánh vào m t kí t kích ho t mt l nh c a ng d ng. Thơng đip này đưc g i t i c a s cĩ s quan tâm khi thơng đip WM_CHAR WM_KEYDOWN đã đưc d ch t hàm TranslateMessage . Thơng đip WM_CHAR cĩ ch a mã kí t ca phím đưc nh n. Thơng đip này đưc g i t i c a s cĩ s quan tâm khi thơng đip WM_KEYUP đã đưc x lý t hàm TranslateMessage . Thơng đip này WM_DEADCHAR xác nh n mã kí t khi m t phím dead key đưc nh n. Phím dead key là phím kt h p đ to 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 đip này đ xác WM_GETHOTKEY đnh m t phím nĩng liên quan đn m t ca s . ð gi thơng đip này thì dùng hàm SendMessage . Thơng đip này đưc g i khi ng ưi dùng WM_HOTKEY nh n m t phím nĩng đưc đă ng kí trong RegisterHotKey . Thơng đip này đưc g i cho c a s nh n đưc s quan tâm khi ng ưi dùng WM_KEYDOWN 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 đip này đưc g i cho c a s nh n đưc s quan tâm khi ng ưi dùng nh mt phím đã đưc nh n tr ưc WM_KEYUP đĩ.Phím này khơng ph i phím h th ng (Phím khơng cĩ nh n phím Alt ). 95
  23. Thơng đip này đưc g i t i c a s đang WM_KILLFOCUS nh n đưc s quan tâm tr ưc khi nĩ m t quy n này. Thơng đip này đưc g i t i c a s sau WM_SETFOCUS khi c a s nh n đưc s quan tâm c a Windows ng d ng s gi thơng đip này đn c a s liên quan đn phím nĩng, khi ng ưi WM_SETHOTKEY 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 đip 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 WM_SYSCHAR đip WM_SYSKEYDOWN . Thơng đip 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à t hp phím khác. Thơng đip này đưc g i t i c a s nh n đưc s quan tâm khi m t thơng đip WM_SYSKEYDOWN đưc biên d ch WM_SYSDEADCHAR trong hàm TranslateMessage . Thơng đip này xác nh n mã kí t ca phím h th ng deadkey đưc nh n. Thơng đip 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 đip này c ũng đưc WM_SYSKEYDOWN gi 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 đip này đưc g i t i c a s nh n WM_SYSKEYUP đưc s quan tâm khi ng ưi dùng nh n mt phím mà tr ưc đĩ đã gi phím Alt . 96
  24. Cũng t ươ ng t nu khơng cĩ c a s nào nh n đưc s quan tâm thì thơng đip này s đưc g i cho c a s đang đưc kích ho t. 5.2.3. Tham s wParam và lPram c a thơng đip bàn phím Trong ph m vi mơn h c chúng ta ch tìm hi u thơng tin c a các thơng đip v phím ( key ) và ký t (character ). Nh ư đã gi i thi u trên, m i khi chúng ta nh n phím thì h th ng g i cho ng d ng đang gi focus các thơng đip WM_KEYDOWN , WM_KEYUP , WM_SYSKEYDOWN , và WM_SYSKEYUP . Khi đĩ, tham s wParam s nh n giá tr mã phím o, và tham s lParam ch a thơng tin chi ti t v phím đưc gõ vào. Thơng qua hàm TranslateMessage , thơng đip WM_KEYDOWN đưc thơng d ch sang thêm thơng đip WM_CHAR . T ươ ng t ta cĩ các thơng đip WM_DEADCHAR , WM_SYSCHAR , và WM_SYSDEADCHAR t các thơng đip WM_KEYUP , WM_SYSKEYDOWN , và WM_SYSKEYUP . Gi ng nh ư các thơng đip v phím, giá tr lParam ca các thơng đip v ký t xác đnh thơng tin chi ti t c a ký t phím nh n đưc; cịn wParam thì ch a mã ký t (thay vì mã phím o). Khái ni m phím o trên Windows g n li n v i đc tr ưng đc l p thi t b (device independent ) c a bàn phím. Nh ư đã đ cp trên, khi m t phím đưc nh n thì ph n c ng vt lý phát sinh ra m t mã quét ( scan code ). Trên các bàn phím t ươ ng thích IBM các phím đưc gán vi các mã c th , 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. Tuy nhiên, nhng 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 (các bàn phím luơn ph i đưc s n xu t d a trên các thơng s đã cĩ). Do đĩ h 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 gi 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 ca phím o này đưc đnh ngh ĩa trong tp tin tiêu đ WINUSER.H và đưc b t đu v i các ti p đu ng VK_xxxxx . Sau đây là các 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. Bảng 5.2. Mơ t các phím o Thp Thp Hng phím đnh Windows Bàn phím IBM phân lc nghĩa trong dùng tương thích phân WINUSER.H 97
  25. 1 01 VK_LBUTTON Nút chu t trái 2 02 VK_RBUTTON Nút chu t ph i 3 03 VK_CANCEL X Ctrl –Break 4 04 VK_MBUTTON Nút chu t gi a Các thơng đip trên ch đưc nh n khi dùng chu t, ta khơng bao gi nh n đưc thơng đip 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. Bảng 5.3. Mơ t các phím o (ti p theo) Thp Thp Hng phím đnh Windows Bàn phím IBM phân lc nghĩa trong dùng tương thích phân WINUSER.H 8 08 VK_BACK X Backspace 9 09 VK_TAB X Tab 12 0C VK_CLEAR X Phím s 5 trong NumPad v i đèn Numlock t t. 13 0D VK_RETURN X Enter (hai phím) 16 10 VK_SHIFT X Shift (hai phím) 17 11 VK_CONTROL X Ctrl (hai phím) 18 12 VK_MENU X Alt (hai phím) 19 13 VK_PAUSE X Pause 20 14 VK_CAPITAL X Caps Lock 27 1B VK_ESCAPE X Esc 32 20 VK_SPACE X Spacebar Bng mơ t phím o ti p sau đây là các phím th ưng đưc s dng nhi u trong Windows. Bảng 5.4. Mơ t các phím o (ti p theo) Thp Thp Hng phím đnh Windows Bàn phím IBM phân lc nghĩa trong dùng tương thích phân WINUSER.H 33 21 VK_PRIOR X Page Up 34 22 VK_NEXT X Page Down 35 23 VK_END X End 98
  26. 36 24 VK_HOME X Home 37 25 VK_LEFT X Phím trái 38 26 VK_UP X Phím m ũi tên lên 39 27 VK_RIGHT X Phím ph i 40 28 VK_DOWN X Phím xu ng 41 29 VK_SELECT - 42 2A VK_PRINT - 43 2B VK_EXECUTE - 44 2C VK_SNAPHOT Print Screen 45 2D VK_INSERT X Insert 46 2E VK_DELETE X Delete 47 2F VK_HELP Mt 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 lp mà chúng ta ít khi g p. 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. Bảng 5.5. Mơ t các phím ch và s trên bàn phím chính Thp Thp Hng phím đnh Windows Bàn phím IBM phân lc nghĩa trong dùng tương thích phân WINUSER.H 48- 30- Khơng X T phím 0 đn 57 39 phím 9 trên bàn phím chính 65- 41- Khơng X T phím A đn 90 5A phím Z. 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 dng 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 đip 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 rng Num Pad (bên ph i c a bàn phím) và các phím ch c n ăng (F1, F2, F3 ). Bảng 5.6. Mơ t các phím b sung Thp Thp Hng phím đnh Windows Bàn phím IBM phân lc nghĩa trong dùng tương thích phân WINUSER.H 96- 60- VK_NUMPAD0 Phím 0 – 9 khi đn 99
  27. 105 69 VK_NUMPAD9 đèn Num Lock đưc b t 106 6A VK_MULTIPLY Phím * 107 6B VK_ADD Phím + 108 6C VK_SEPARATOR 109 6D VK_SUBTRACT Phím - 110 6E VK_DECIMAL Phím . 111 6F VK_DIVIDE Phím / 112- 70- VK_F1 đn X Phím F1 đn F10 121 79 VK_F10 122- 7A- VK_F11 đn Phím F11 đn 135 87 VK_F24 F24 144 90 VK_NUMLOCK Num Lock 145 91 VK_SCROLL Scroll Lock Mt s các phím o nh ư F13 - F24 thì đưc Windows t o ra d phịng 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. ðĩ là các b ng mã phím o c a các thơng đip v key. Trong tr ưng h p thao tác ký t , ta s dng luơn mã ký t cĩ đưc (ví d 0x0D là ký t xu ng dịng) ho c cĩ th ly bi n ký t bng (TCHAR)wParam . Cu i cùng, thơng tin ch a trong 32 bit c a tham s lParam ca các thơng đip trên đưc mơ t trong b ng sau: Bảng 5.7. Mơ t thơng tin ch a trong tham s lParam Bit Ni dung nhn dng 0-15 Ch a s ln l p c a thơng đip đang đưc g i (WM_KEYDOWN, WM_CHAR, ). 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 ln này s tăng theo. 16-23 Ch a mã quét OEM (Original Equipment Manufacturer ) do nhà s n xu t ph n c ng quy đnh, ta h u nh ư khơng quan tâm đn thơng tin này. 24 C này cĩ giá tr 1 khi phím đưc nh n là phím thu c nhĩm phím m rng 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 ca c 100
  28. này. 25-28 ð dành, khơng s dng. 29 Mã ng cnh c a phím ( Context code ), n u c này cĩ giá tr bng 1 thì phím Alt đưc nh n, điu này tươ ng ng v i thơng đip WM_SYSKEYDOWN hay WM_SYSKEYUP đưc phát sinh 30 Tr ng thái c a phím tr ưc đĩ, bit này b ng 0 n u phím tr ng thái nh tr ưc đĩ, và b ng 1 n u phím tr ng thái nh n. 31 Tr ng thái d ch chuy n c a phím, c này b ng 0 nu phím đang đưc nh n, và b ng 1 n u phím nh . 5.2.4. Ví d ZoomAnh s dng thao tác bàn phím Trong bài h c này, chúng ta ch minh h a thao tác đơ n gi n v phím nh n đ th hi n thao tác zoom nh bitmap (theo quy trình đã đưc h c bài 4). ng d ng th hi n m t nh bitmap cĩ trong resource ra gi a vùng làm vi c c a c a s ng d ng. Khi ng ưi dùng nh n phím + thì phĩng l n g p đơi n u nh v n cĩ th th hi n trong ph m vi vùng làm vi c, và thu nh mt n a khi ch n phím -. ðu tiên, ta c ũng t o project d ng A typical “Hello World!” application cĩ tên là ZoomAnh . Sau đĩ t o m t đi t ưng nh bitmap s đưc dùng đ hi n th , đnh danh là IDB_ANH , và v mt hình nh b t k ỳ ( đây là hình ch A) – xem hình 5.2. Hình 5.2 . To l p resource IDB_ANH ð hi n th nh ra chính gi a vùng làm vi c c a ng d ng, ta c n xác đnh v trí tâm màn hình. Ta dùng m t bi n t ĩnh static POINT ptCenter trong hàm WndProc đ lưu v trí tâm vùng 101
  29. làm vi c và bi n t ĩnh static LPARAM dwSize đ lưu thơng s kích th ưc vùng làm vi c. Giá tr này đưc c p nh t trong thơng đip WM_SIZE mi khi kích th ưc c a s b thay đi. Thơng qua v trí tâm màn hình, k t h p v i kích th ưc nh c n th hi n ta d dàng th hi n nh b ng các hàm zoom nh trong thơng đip WM_PAINT . Chi u r ng và chi u cao nh đưc l ưu trong c u trúc bi n t ĩnh static BITMAP bmpInfo đưc kh i gán t i thơng đip WM_CREATE . Ngồi ra, ta dùng thêm hai bi n static int nBmpWidth , nBmpHeight th hi n kích th ưc đang zoom và đưc c p nh t m i khi th c hi n thao tác nh n phím + ho c - trong thơng đip WM_KEYDOWN tr ưc khi g i hàm InvalidateRect đ kích ho t thơng đip WM_PAINT xu t l i nh. Ta cĩ đon code hàm WndProc nh ư sau: 1 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, 2 LPARAM lParam) 3 { 4 int wmId, wmEvent; 5 PAINTSTRUCT ps; 6 HDC hDC, hSrcMemDC, hDestMemDC; 7 HBITMAP hOldBmp, hBlankBmp, hOldBlankBmp; 8 static HBITMAP hBmp; 9 static BITMAP bmpInfo; 10 static int nBmpWidth, nBmpHeight; 11 static LPARAM dwSize; 12 static POINT ptCenter; 13 POINT ptOrgBmp; 14 15 switch (message) 16 { 17 case WM_CREATE: 18 hBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_ANH)); 19 GetObject(hBmp, sizeof(BITMAP), &bmpInfo); 20 nBmpWidth = bmpInfo.bmWidth; 21 nBmpHeight = bmpInfo.bmHeight; 22 break; 23 case WM_SIZE: 24 dwSize = lParam; 25 ptCenter.x = LOWORD(lParam)/2; 26 ptCenter.y = HIWORD(lParam)/2; 27 break; 28 case WM_COMMAND: 29 wmId = LOWORD(wParam); 30 wmEvent = HIWORD(wParam); 31 // Parse the menu selections: 32 switch (wmId) 33 { 34 case IDM_ABOUT: 35 DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, 36 (DLGPROC)About); 37 break; 38 case IDM_EXIT: 39 DestroyWindow(hWnd); 40 break; 41 default: 42 return DefWindowProc(hWnd, message, wParam, 43 lParam); 44 } 45 break; 46 case WM_PAINT: 47 hDC = BeginPaint(hWnd, &ps); 102
  30. 48 49 hSrcMemDC = CreateCompatibleDC(hDC); 50 hDestMemDC = CreateCompatibleDC(hDC); 51 52 hBlankBmp = CreateCompatibleBitmap(hDC, LOWORD(dwSize), 53 HIWORD(dwSize)); 54 55 hOldBmp = (HBITMAP)SelectObject(hSrcMemDC, hBmp); 56 hOldBlankBmp = (HBITMAP)SelectObject(hDestMemDC, 57 hBlankBmp); 58 59 ptOrgBmp.x = ptCenter.x nBmpWidth/2; 60 ptOrgBmp.y = ptCenter.y nBmpHeight/2; 61 62 StretchBlt(hDestMemDC, ptOrgBmp.x, ptOrgBmp.y, nBmpWidth, 63 nBmpHeight, hSrcMemDC, 0, 0, bmpInfo.bmWidth, 64 bmpInfo.bmHeight, SRCCOPY); 65 BitBlt(hDC, ptOrgBmp.x, ptOrgBmp.y, nBmpWidth, nBmpHeight, 66 hDestMemDC, ptOrgBmp.x, ptOrgBmp.y, SRCCOPY); 67 68 SelectObject(hSrcMemDC, hOldBmp); 69 SelectObject(hDestMemDC, hOldBlankBmp); 70 DeleteObject(hBlankBmp); 71 DeleteDC(hSrcMemDC); 72 DeleteDC(hDestMemDC); 73 74 EndPaint(hWnd, &ps); 75 break; 76 case WM_KEYDOWN: 77 switch(wParam) 78 { 79 case VK_ADD: // Ma ao ky tu + 80 if(nBmpWidth*2 1 && nBmpHeight>1) 90 { 91 nBmpWidth/=2; 92 nBmpHeight/=2; 93 InvalidateRect(hWnd, NULL, TRUE); 94 } 95 break; 96 } 97 break; 98 case WM_DESTROY: 99 PostQuitMessage(0); 100 break; 101 default: 102 return DefWindowProc(hWnd, message, wParam, lParam); 103 } 104 return 0; 105 } 5.3. THI T B CHU T Trong mơi tr ưng giao ti p đ ha nh ư Windows, vi c s dng thi t b đnh v chu t là h t s c cn thi t. Nh thi t b chu t ta cĩ th di chuy n đn m t v trí b t kỳ trên màn hình và ch cn 103
  31. th c hi n thao tác click nút chu t đ x lý m t cơng vi c nào đĩ. 5.3.1. C ơ b n v thi t b chu t trên 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, ngồi ra Windows cịn cĩ th dùng thi t b khác nh ư joystick hay bút v đ bt 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 dng 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 cnh ( 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 . int GetSystemMetrics (int nIndex ); Ta dùng giá tr nIndex là SM_MOUSEPRESENT đ ki m tra cĩ t n t i thi t b chu t trong h th ng hay khơng – Giá tr tr v là TRUE (1) n u cĩ và FALSE (0) n u khơng. Và dùng SM_CMOUSEBUTTONS cho nIndex đ ki m tra s nút chu t c a thi t b chu t cĩ trong h th ng; giá tr tr v là s nút nh n và b ng 0 n u khơng cĩ thi t b chu t đưc cài đt. 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 đim gi là đim nĩng ( hot spot ), đim 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 đ ca đim nĩng này. ð đư a m t con tr chu t vào ng d ng hInstance , cách đơ n gi n nh t là dùng hàm LoadCursor đ np m t đi t ưng con tr chu t lpCursorName t tài nguyên. HCURSOR LoadCursor (HINSTANCE hInstance , LPCTSTR lpCursorName ); Thơng th ưng ta s dng các đi t ưng con tr chu t chu n đưc Windows đnh ngh ĩa s n khi g i hàm này, v i các giá tr ca lpCursorName tươ ng ng là IDC_ARROW (hình m ũi tên), IDC_HELP (hình d u h i đi kèm m ũi tên), IDC_WAIT (hình đng h cát), IDC_CROSS (hình du c ng). Chúng ta cĩ th th thay đi các giá tr này cho đi t ưng con tr chu t c a l p c a s ng dng (xem ph n thi t l p thơng s lp c a s trong hàm MyRegisterClass ca các ng dng đã làm) và xem k t qu th c thi c a ng d ng. 5.3.2. X lý các thơng đip t thi t b chu t Vi thi t b chu t ta cĩ th th c hi n các thao tác nh ư click chu t (nh n và th nút nh n), double click (nh n và th nhanh hai l n li n) ho c kéo rê (move) con tr chu t trên màn hình, và t t c các thao tác này đu đưc chuy n thành các thơng đip g i cho c a s nh n tác đng t ươ ng ng. Nh ư v y, b t c lúc nào c ũng cĩ m t c a s nh n đưc m t thơng đip v thi t b chu t. Windows đnh ngh ĩa 21 thơng đip đưc phát sinh t thi t b chu t, phân thành hai nhĩm chính. Nhĩm các thơng đip trong vùng làm vi c ( client area messages ) g i cho c a s khi thi t b 104
  32. chu t n m trong vùng làm vi c (11 thơng đip). Nhĩm cịn l i là các thơng đip khơng thu c vùng làm vi c ( nonclient-area messages ), nhĩm này th ưng đưc các ng d ng b qua khơng x lý. Trong các ví d minh h a, chúng ta c ũng khơng thao tác các thơng đip này. 5.3.2.1. Thơng đip 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 , Windows phát sinh thơng đip cĩ tên là WM_MOUSEMOVE . Khi ng ưi dùng click chu t, tu ỳ theo cách thao tác mà chúng ta cĩ các thơng đip đưc li t kê trong b ng 5.1. sau: Bảng 5.8. Mơ t thơng đip click chu t trong vùng làm vi c Nút Nhn Th Nhn đúp Trái WM_LBUTTONDOWN WM_LBUTTONUP WM_LBUTTONDBLCLK Gia WM_MBUTTONDOWN WM_MBUTTONUP WM_MBUTTONDBLCLK Phi WM_RBUTTONDOWN WM_MBUTTONUP WM_RBUTTONDBLCLK Th tc c a s ca ng d ng s nh n đưc thơng đip c a nút chu t gi a n u máy tính cài thi t b chu t cĩ ba nút. T ươ ng t nh ư v y v i thơng đip thi t b chu t ph i, chúng ta c n cĩ thi t b chu t dùng hai nút. ð nh n đưc thơng đip kích đúp thi t b chu t th tc c a s phi khai báo nh n thơng đip này. Wndclass.style = CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS; Trong thơng đip 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 ta đ x, cịn 16 byte cao s ch a giá tr ta đ ca y. ð ly ra hai giá tr này ta cĩ th dùng macro là LOWORD và HIWORD . Bảng 5.9. Mơ t tr ng thái c a chu t và phím nh n MK_LBUTTON Nút chut trái nhn MK_MBUTTON Nút chut gia nhn MK_RBUTTON Nút chut phi nhn MK_SHIFT Phím Shift đưc nhn MK_CONTROL Phím Ctrl đưc nhn Giá tr wParam 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 ). B ng 5.2 li t kê mt s giá tr tr ng thái nút nh n th ưng g p. Nh ư v y, khi l p trình chúng ta ch vi c ch n thơng đip t ươ ng ng c n x lý trong hàm x lý c a c a s , và c ăn c vào các thơng s v trí (lParam), tr ng thái phím và nút nh n (wParam) 105
  33. gi kèm đ vi t các x lý khác nhau. 5.3.2.2. Thơng đip c a thi t b chu t ngồi vùng làm vi c Các thơng đip 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 ca c a s nh ưng v n trong ph m vi c a c a s (trên thanh tiêu đ, menu, thanh cu n, ) thì Windows c ũng phát sinh các thơng đip t ươ ng t , v i tên g i cĩ thêm ti p đu ng NC (nonclient ) vào sau ký t “_” nh ư WM_NCMOUSEMOVE , WM_NCLBUTTONDOWN , WM_NCMBUTTONUP , WM_NCRBUTTONBDLCLK , Các tham s lParam và wParam cũng h ơi khác so v i các thơng đip thi t b chu t phát sinh trong vùng làm vi c. Tham s lParam ca thơng đip phát sinh t ngồi vùng làm vi c s ch ra v trí ngồ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 xác đnh bi các giá tr đnh ngh ĩa trong WINUSER.H đưc b t đu v i HT (vi t t t cho hit-test ) nh ư HTBORDER (trên border), HTCLOSE (trên nút Close ). Ta cĩ th nh n các giá tr HT này qua thơng đip WM_NCHITTEST , tuy nhiên v i ph m vi mơn h c chúng ta s khơng tìm hi u k v vn đ này. Hình 5.3 . 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à ta đ màn hình, khơng ph i là t a đ vùng làm vi c gi ng nh ư thơng đip phát sinh t vùng làm vi c. Ta s dng các macro GET_X_LPARAM và GET_Y_LPARAM đ ly các giá tr này tươ ng ng. N u mu n chuy n v ta đ vùng làm vi c đ x lý khi c n thi t ta dùng các hàm Windows đã cung c p. BOOL ScreenToClient (HWND hWnd , LPPOINT lpPoint ); 106
  34. BOOL ClientToScreen (HWND hWnd , LPPOINT lpPoint ); Hàm ScreenToClient chuy n t a đ màn hình sang t a đ vùng làm vi c c a c a s hWnd và hàm ClientToScreen th c hi n ng ưc l i. Giá tr ca đim lpPoint s thay đi n u thao tác chuy n đi th c hi n thành cơng (giá tr hàm tr v là TRUE (1)). 5.3.3. Ví d VeDaGiac minh h a thao tác thi t b chu t ng d ng VeDaGiac cho phép ng ưi dùng click chu t trái đ v các đưng th ng trong m t đa giác. V i thao tác click chu t trái l n đu tiên (xét cho m t đa giác), ta l ưu l i v trí đim v a đưc click, và khi th c hi n thao tác click ti p theo ta s v t đim đưc click tr ưc t i đim va đưc click. Quy trình th c hi n cho đn khi ng ưi dùng click chu t ph i, lúc đĩ ta s v t đim đu tiên c a đa giác đn đim v a đưc click chu t ph i đ hồn thành đa giác. Ngồi ra, ng d ng cịn cĩ ch c n ăng h tr ng ưi dùng ch n menu File -> New (IDM_NEW) đ xĩa s ch màn hình và b t đu thao tác v đa giác khác (cho dù ch ưa hồn thành v đa giác tr ưc đĩ); và ch n màu bút v thơng qua menu Color vi các item Black (IDM_BLACK), Red (IDM_RED), Green (IDM_GREEN) và Blue (IDM_BLUE) trong quá trình v . Ta t o l p project VeDaGiac và menu resource gi ng nh ư đã làm v i các project khác. V vi c vi t code, nh n th y r ng trong quá trình thao tác click chu t, ta c n l ưu v trí đim đu tiên ca đa giác, v trí đim v a nh n thao tác click và v trí đim tr ưc đĩ đ v, do đĩ ta dùng ba bi n t ĩnh static POINT ptFirst, ptCurrent, ptPast đ lưu. Ngồi ra, ta c ũng c n m t bi n xác đnh là đang trong quá trình v đa giác hay là đã k t thúc quá trình này (khi click chu t ph i ho c ch n menu New), vì th ta dùng bi n static BOOL bClicked . Da trên thao tác ch n các menu item v i thơng đip WM_COMMAND , và thơng đip click chu t v i các thơng đip WM_LBUTTONDOWN và WM_RBUTTONDOWN , ta cĩ đon code hàm WndProc nh ư sau: 1 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, 2 LPARAM lParam) 3 { 4 int wmId, wmEvent; 5 PAINTSTRUCT ps; 6 HDC hdc; 7 static BOOL bClicked; 8 static POINT ptFirst, ptCurrent, ptPast; 9 static COLORREF crColor; 10 HPEN hPen, hOldPen; 11 12 switch (message) 13 { 14 case WM_CREATE: 15 bClicked = FALSE; 16 crColor = RGB(0, 0, 0); 17 break; 18 case WM_COMMAND: 19 wmId = LOWORD(wParam); 20 wmEvent = HIWORD(wParam); 21 // Parse the menu selections: 22 switch (wmId) 107
  35. 23 { 24 case IDM_NEW: 25 bClicked = FALSE; 26 ptCurrent.x = 0; 27 ptCurrent.y = 0; 28 ptPast = ptCurrent; 29 InvalidateRect(hWnd, NULL, TRUE); 30 break; 31 case IDM_BLACK: 32 crColor = RGB(0, 0, 0); 33 break; 34 case IDM_RED: 35 crColor = RGB(255, 0, 0); 36 break; 37 case IDM_GREEN: 38 crColor = RGB(0, 255, 0); 39 break; 40 case IDM_BLUE: 41 crColor = RGB(0, 0, 255); 42 break; 43 case IDM_ABOUT: 44 DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, 45 (DLGPROC)About); 46 break; 47 case IDM_EXIT: 48 DestroyWindow(hWnd); 49 break; 50 default: 51 return DefWindowProc(hWnd, message, wParam, 52 lParam); 53 } 54 break; 55 case WM_PAINT: 56 hdc = BeginPaint(hWnd, &ps); 57 58 hPen = CreatePen(PS_SOLID, 1, crColor); 59 hOldPen = (HPEN)SelectObject(hdc, hPen); 60 MoveToEx(hdc, ptPast.x, ptPast.y, NULL); 61 LineTo(hdc, ptCurrent.x, ptCurrent.y); 62 SelectObject(hdc, hOldPen); 63 DeleteObject(hPen); 64 65 EndPaint(hWnd, &ps); 66 break; 67 case WM_LBUTTONDOWN: 68 if(!bClicked) 69 { 70 bClicked = TRUE; 71 ptFirst.x = LOWORD(lParam); 72 ptFirst.y = HIWORD(lParam); 73 } 74 else 75 { 76 ptPast = ptCurrent; 77 InvalidateRect(hWnd, NULL, FALSE); 78 } 79 ptCurrent.x = LOWORD(lParam); 80 ptCurrent.y = HIWORD(lParam); 81 break; 82 case WM_RBUTTONDOWN: 83 bClicked = FALSE; 84 ptPast = ptFirst; 85 InvalidateRect(hWnd, NULL, FALSE); 86 break; 87 case WM_DESTROY: 88 PostQuitMessage(0); 89 break; 108
  36. 90 default: 91 return DefWindowProc(hWnd, message, wParam, lParam); 92 } 93 return 0; 94 } 5.4. B ðNH TH I GIAN Vi các thơng đip v thi t b chu t và bàn phím v a tìm hi u, chúng ta đã cĩ th x lý các ng dng trên Windows hi u qu hơn. Tuy nhiên, tr ưc khi k t thúc mơn h c, chúng ta s tìm hi u thêm m t d ng thơng đip c ũng r t h u d ng là thơng đip v th i gian. Cĩ khá nhi u ng d ng địi h i ng ưi l p trình th c hi n m t thao tác m t cách t đng theo chu k ỳ ho c m t kho ng th i gian đnh tr ưc nào đĩ. ð làm điu này, chúng ta ch vi c đnh ngh ĩa m t đi t ưng g i là b đnh th i gian (Timer ) v i các thơng s cn thi t, và sau đĩ là vi t code x lý trong thơng đip ho c hàm x lý cĩ liên quan. 5.4.1. ðnh ngh ĩa b đnh th i gian trong ng d ng Khơng nh ư các thơng đip xu t phát t thi t b chu t và bàn phím đưc Windows g i t đng vào hàng đi thơng đip c a ng d ng; đ cĩ các thơng đip v th i gian, ta ph i khai báo các đi t ưng b đnh th i gian tr ưc b ng hàm SetTimer . Sau khi khai báo hàm này thì Windows s gi thơng đip WM_TIMER đu đn vào hàng đi c a ng d ng. Hàm SetTimer thi t l p b đnh th i gian xác đnh b i đnh danh nIDEvent , dùng cho c a s hWnd , v i thơng s th i gian mà Windows s gi thơng đip WM_TIMER là uElapse ph n nghìn giây (milisecond). Tham s lpTimerFunc tr đn hàm s x lý khi thơng đip WM_TIMER phát sinh. N u giá tr này là NULL thì Windows s gi thơng đip WM_TIMER vào hàng đi thơng đip c a c a s tươ ng ng. UINT_PTR SetTimer (HWND hWnd , UINT_PTR nIDEvent , UINT uElapse , TIMERPROC lpTimerFunc ); Khi khơng dùng b đnh th i gian n a hay k t thúc ng d ng ta g i hàm KillTimer, v i các thơng s gi vào là đnh danh nIDEvent ca b đnh th i gian đã đnh ngh ĩa c ũng nh ư c a s hWnd qu n lý nĩ. BOOL KillTimer (HWND hWnd , UINT_PTR nIDEvent ); V mt lý thuy t thì thơng đip th i gian do Windows cung c p là chính xác đn tng ph n nghìn giây, th nh ưng trên th c t thì khơng hồn tồn nh ư v y. S chính xác cịn ph thu c vào đng h ca 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 đip th i gian WM_TIMER cĩ đ ưu tiên th p, nh ư thơng đip tơ v li màn hình WM_PAINT , chúng th ưng ph i ch cho các thơng đip cĩ đ ưu tiên cao h ơn x lý xong tr ưc đã. 109
  37. 5.4.2. Ví d v b đnh th i gian Ch ươ ng trình DongHo minh h a c ơ ch x lý c a b đnh th i gian, th c hi n vi c xu t gi ra gi a màn hình ng d ng ki u đng h đin t dng hh:mm:ss (gi :phút:giây). ð th c hi n thao tác trên, ta cho ng d ng c p nh t giá tr bi n th i gian và v li trên màn hình m i 1 giây (1000 ms), vì th khi kh i t o ng d ng, trong thơng đip WM_CREATE ta đnh ngh ĩa m t b đnh th i gian cĩ đnh danh là IDT_TIMER vi giá tr uElapse là 1000. Ch ươ ng trình này minh h a thao tác g i thơng đip v th i gian vào hàm x lý TimerProc . Trong hàm này ta ch đơ n gi n g i hàm InvalidateRect đ gi yêu c u th c hi n WM_PAINT trong c a s chính. Và nh ư v y, ta ch cn l y th i gian hi n t i trên máy tính b ng hàm GetLocalTime , chuy n thơng s th i gian vào chu i szTimer và xu t ra màn hình b ng hàm DrawText quen thu c. VOID GetLocalTime (LPSYSTEMTIME lpSystemTime ); Riêng cách s dng thơng đip WM_TIMER (khơng dùng hàm x lý riêng) xin xem thêm trong ví d tng h p ph n tĩm t t 5.5. 1 // DongHo.cpp : Defines the entry point for the application. 2 // 3 4 #include "stdafx.h" 5 #include "resource.h" 6 7 #define IDT_TIMER 1 8 9 #define MAX_LOADSTRING 100 10 11 // Global Variables: 12 HINSTANCE hInst; // current instance 13 TCHAR szTitle[MAX_LOADSTRING]; // The title bar text 14 TCHAR szWindowClass[MAX_LOADSTRING]; // The title bar text 15 16 // Foward declarations of functions included in this code module: 17 ATOM MyRegisterClass(HINSTANCE hInstance); 18 BOOL InitInstance(HINSTANCE, int); 19 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 20 LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM); 21 VOID CALLBACK TimerProc(HWND, UINT, UINT_PTR, DWORD); 22 23 // ðon này xin xem code t phát sinh 24 25 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, 26 LPARAM lParam) 27 { 28 int wmId, wmEvent; 29 PAINTSTRUCT ps; 30 HDC hdc; 31 SYSTEMTIME st; 32 TCHAR szTimer[MAX_LOADSTRING]; 33 34 switch (message) 35 { 36 case WM_CREATE: 37 SetTimer(hWnd, IDT_TIMER, 1000, (TIMERPROC)TimerProc); 38 break; 39 case WM_COMMAND: 110
  38. 40 wmId = LOWORD(wParam); 41 wmEvent = HIWORD(wParam); 42 // Parse the menu selections: 43 switch (wmId) 44 { 45 case IDM_ABOUT: 46 DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, 47 (DLGPROC)About); 48 break; 49 case IDM_EXIT: 50 DestroyWindow(hWnd); 51 break; 52 default: 53 return DefWindowProc(hWnd, message, wParam, 54 lParam); 55 } 56 break; 57 case WM_PAINT: 58 hdc = BeginPaint(hWnd, &ps); 59 RECT rt; 60 GetClientRect(hWnd, &rt); 61 GetLocalTime(&st); 62 wsprintf(szTimer,"%2d : %2d : %2d", st.wHour, st.wMinute, 63 st.wSecond); 64 DrawText(hdc, szTimer, strlen(szTimer), &rt, 65 DT_CENTER|DT_VCENTER|DT_SINGLELINE); 66 EndPaint(hWnd, &ps); 67 break; 68 case WM_DESTROY: 69 KillTimer(hWnd, IDT_TIMER); 70 PostQuitMessage(0); 71 break; 72 default: 73 return DefWindowProc(hWnd, message, wParam, lParam); 74 } 75 return 0; 76 } 77 78 VOID CALLBACK TimerProc( HWND hWnd, UINT uMsg, UINT_PTR idEvent, 79 DWORD dwTime) 80 { 81 InvalidateRect ( hWnd, NULL, TRUE ); 82 } 5.5. TĨM T T Trong bài h c cu i này, chúng ta m t l n n a đưc nh c l i đc đim quan tr ng nh t khi l p trình trên Windows là v n đ thơng đip v i mơ hình thao tác nh ư hình 5.1. Bên c nh các thơng đip phát sinh t các đi t ưng trên ng d ng nh ư WM_COMMAND , WM_SIZE , bài h c này, chúng ta đã tìm hi u thêm m t s thơng đip c ơ b n v nh p li u nh ư WM_KEYDOWN , WM_CHAR , c a bàn phím ph n 5.2, thơng đip WM_LBUTTONDOWN , WM_RBUTTONDOWN , c a thi t b chu t ph n 5.3, c ũng nh ư thơng đip v th i gian WM_TIMER vi đi t ưng b đnh th i gian – ph n 5.4. Vi t ng d ng thơng đip chúng ta c ũng đã th c hành cài đt x lý chúng trong hàm WndProc ca ng d ng Win32 Application. Và đây, đ kt thúc bài h c, chúng ta s cùng 111
  39. nhau vi t ng d ng MoveImg th hi n m t con b ưm đang v cánh, k t h p t t c các thao tác v bàn phím, thi t b chu t và b đnh th i gian. ðu tiên, ta c ũng t o l p project d ng A typical “Hello World!” application , cùng v i ba nh bitmap trong resource là IDB_BFLY1 , IDB_BFLY2 , và IDB_MASK vi kích th ưc 77*77 tươ ng ng là hai hình con b ưm v i t ư th v cánh khác nhau cùng v i m t hình tr ng dùng làm mt n đ xố nh c ũ trên màn hình khi c n thi t sau này. Hình 5.4 th hi n nh con b ưm IDB_BFLY2 ngay gi a vùng làm vi c c a ng d ng. Hình 5.4. Th hi n nh IDB_BFLY2 c a ng d ng MoveImg ð th hi n nh bitmap t resource lên màn hình, ta c n t o đi t ưng nh HBITMAP, vì th đây ta cĩ th dùng ba bi n tồn c c HBITMAP hBfly1, hBfly2, hMask đ lưu d li u ba đi tưng nh cho ti n trình (instance) c a ng d ng. Khi ng d ng th c thi, ta n p ngay d li u cho các đi t ưng này b ng hàm LoadBitmap trong thơng đip WM_CREATE . Bên c nh đĩ, đ th hi n thao tác con b ưm v cánh thơng qua hai nh khác nhau, chúng ta ch vi c thi t l p m t b đnh th i gian sao cho ng v i m t kho ng th i gian nh t đnh thì th hi n trên màn hình ch mt trong hai nh. Và v i cách thay th hai nh nh ư th , ta s th y nh ư cĩ mt con b ưm đang v cánh. Do đĩ, trong thơng đip WM_CREATE , ta c ũng t o l p b đnh th i gian cĩ đnh danh là IDT_BFLY và dùng thêm bi n t ĩnh xác đnh hình (con b ưm) hi n t i static int nCurBmp . Bi n nCurBmp s nh n m t trong các giá tr đưc đnh ngh ĩa tr ưc là BITMAP_BFLY1 , BITMAP_BFLY2 và BITMAP_MASK ; giá tr ban đu là BITMAP_BFLY1 . Trong ng d ng này, đ xu t nh ra màn hình, ta khơng dùng thơng đip WM_PAINT na 112
  40. mà vi t riêng hàm DrawBfly đ v nh. V i m i l n Windows gi thơng đip WM_TIMER , ta gi hàm này đ xu t nh v i m t giá tr nh nCurBmp tươ ng ng. Nh ư v y chúng ta đã th c hi n đưc thao tác v b đnh th i gian. Chúng ta s thao tác ti p v bàn phím và thi t b chu t. V thao tác bàn phím, ng d ng này th hi n vi c d ch chuy n v trí con b ưm lên, xu ng, qua trái, ph i theo thao tác các phím m ũi tên. ð th c hi n điu này, ta đơ n gi n ch n thơng đip WM_KEYDOWN vi giá tr wPraram là VK_UP , VK_DOWN , VK_LEFT và VK_RIGHT , cp nh t v trí xu t nh r i g i hàm DrawBfly đ xu t nh. V thao tác thi t b chu t, ng d ng này ch n các thơng đip WM_LBUTTONDOWN , WM_LBUTTONUP và WM_MOUSEMOVE đ thi t l p vi c cho phép di chuy n nh khi ng ưi dùng click chu t lên đi t ưng nh trên màn hình và kéo rê đn v trí khác. Ta c ăn c vào giá tr lParam xác đnh v trí nh đưc c p nh t và v li nh. Ngồi ra, trong ng d ng cịn s dng thơng đip WM_SIZE đ ly kích th ưc vùng làm vi c. Giá tr kích th ưc này đưc dùng đ xác đnh ph m vi cho phép th hi n đi t ưng nh trên ca s ng d ng. M i l n c p nh t kích th ưc màn hình thì ch n l i v trí xu t nh chính gi a vùng làm vi c. Cu i cùng, khi ng ưi dùng k t thúc ng d ng thì ta h y đi t ưng b đnh th i gian đã t o l p trên b ng hàm KillTimer . ðon code t p tin MoveImg.cpp nh ư sau (b các hàm WinMain , InitInstance , cho g n): 1 // MoveImg.cpp : Defines the entry point for the application. 2 // 3 #include "stdafx.h" 4 #include "resource.h" 5 #define MAX_LOADSTRING 100 6 #define IDT_BFLY 1 7 #define BITMAP_BFLY1 1 8 #define BITMAP_BFLY2 2 9 #define BITMAP_MASK 3 10 #define DIS_MOVE 4 11 #define BITMAP_WIDTH 77 12 #define BITMAP_HEIGHT 77 13 14 // Global Variables: 15 HINSTANCE hInst; // current instance 16 TCHAR szTitle[MAX_LOADSTRING]; // The title bar text 17 TCHAR szWindowClass[MAX_LOADSTRING]; // The title bar text 18 HBITMAP hBfly1, hBfly2, hMask; 19 20 // Foward declarations of functions included in this code module: 21 ATOM MyRegisterClass(HINSTANCE hInstance); 22 BOOL InitInstance(HINSTANCE, int); 23 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 24 LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM); 25 void DrawBfly(HWND hWnd, POINT pt, int curBmp); 26 27 // Các hàm WinMain, InitInstance xin xem code t phát sinh 28 29 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, 30 LPARAM lParam) 31 { 32 int wmId, wmEvent; 113
  41. 33 static BOOL bMouseDown; 34 static POINT ptOrg, ptFromOrg; 35 static LPARAM lParamSize; 36 static int nCurBmp; 37 38 switch (message) 39 { 40 case WM_CREATE: 41 SetTimer(hWnd, IDT_BFLY, 300, NULL); 42 43 hBfly1 = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BFLY1)); 44 hBfly2 = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BFLY2)); 45 hMask = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_MASK)); 46 47 nCurBmp = BITMAP_BFLY1; 48 bMouseDown = FALSE; 49 break; 50 51 case WM_COMMAND: 52 wmId = LOWORD(wParam); 53 wmEvent = HIWORD(wParam); 54 // Parse the menu selections: 55 switch (wmId) 56 { 57 case IDM_ABOUT: 58 DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, 59 (DLGPROC)About); 60 break; 61 case IDM_EXIT: 62 DestroyWindow(hWnd); 63 break; 64 default: 65 return DefWindowProc(hWnd, message, wParam, 66 lParam); 67 } 68 break; 69 70 case WM_LBUTTONDOWN: 71 if(LOWORD(lParam)>=ptOrg.x && LOWORD(lParam) =ptOrg.y && 73 HIWORD(lParam) 0) 114
  42. 100 { 101 DrawBfly(hWnd, ptOrg, BITMAP_MASK); 102 ptOrg.x=DIS_MOVE; 103 DrawBfly(hWnd, ptOrg, nCurBmp); 104 } 105 break; 106 case VK_RIGHT: 107 if(ptOrg.x+BITMAP_WIDTH 0) 116 { 117 DrawBfly(hWnd, ptOrg, BITMAP_MASK); 118 ptOrg.y=DIS_MOVE; 119 DrawBfly(hWnd, ptOrg, nCurBmp); 120 } 121 break; 122 case VK_DOWN: 123 if(ptOrg.y+BITMAP_HEIGHT<HIWORD(lParamSize)) 124 { 125 DrawBfly(hWnd, ptOrg, BITMAP_MASK); 126 ptOrg.y+=DIS_MOVE; 127 DrawBfly(hWnd, ptOrg, nCurBmp); 128 } 129 break; 130 } 131 break; 132 133 case WM_TIMER: 134 DrawBfly(hWnd, ptOrg, nCurBmp); 135 if(nCurBmp == BITMAP_BFLY1) 136 nCurBmp = BITMAP_BFLY2; 137 else 138 nCurBmp = BITMAP_BFLY1; 139 break; 140 141 case WM_SIZE: 142 lParamSize = lParam; 143 ptOrg.x = (LOWORD(lParamSize)BITMAP_WIDTH)/2; 144 ptOrg.y = (HIWORD(lParamSize)BITMAP_HEIGHT)/2; 145 break; 146 147 case WM_DESTROY: 148 KillTimer(hWnd, IDT_BFLY); 149 PostQuitMessage(0); 150 break; 151 152 default: 153 return DefWindowProc(hWnd, message, wParam, lParam); 154 } 155 return 0; 156 } 157 158 void DrawBfly(HWND hWnd, POINT pt, int curBmp) 159 { 160 HDC hDC, hMemDC; 161 HBITMAP hOldBmp; 162 163 hDC = GetDC(hWnd); 164 hMemDC = CreateCompatibleDC(hDC); 165 166 switch(curBmp) 115
  43. 167 { 168 case BITMAP_BFLY1: 169 hOldBmp = (HBITMAP)SelectObject(hMemDC, hBfly1); 170 break; 171 case BITMAP_BFLY2: 172 hOldBmp = (HBITMAP)SelectObject(hMemDC, hBfly2); 173 break; 174 case BITMAP_MASK: 175 hOldBmp = (HBITMAP)SelectObject(hMemDC, hMask); 176 break; 177 } 178 179 BitBlt(hDC, pt.x, pt.y, BITMAP_WIDTH, BITMAP_HEIGHT, hMemDC, 0, 0, 180 SRCCOPY); 181 SelectObject(hMemDC, hOldBmp); 182 DeleteObject(hMemDC); 183 ReleaseDC(hWnd, hDC); 184 } 5.6. CÂU H I ƠN T P – BÀI T P 5.6.1. Trình bày mơ hình x lý thơng đip c a các ng d ng trên Windows? Áp d ng mơ hình này đ gi i thích c ơ ch x lý thao tác và l p trình t ươ ng ng v thi t b bàn phím và thi t b chu t? L y ví d cho m t thơng đip c th nào đĩ? 5.6.2. Trình bày hi u bi t c a b n v thơng tin mã phím o và mã ký t khi thao tác bàn phím? S khác nhau c a thơng đip key ( phím ) và char ( ký t )? S khác nhau gi a thao tác các phím thơng th ưng và các phím h th ng ( system )? 5.6.3. Trình bày các d ng thơng đip liên quan đn thi t b chu t ( mouse ), c th là thơng đip phát sinh trong vùng làm vi c ( client-area messages )? Tìm hi u các thơng đip thi t b chu t tươ ng ng ngồi vùng làm vi c ( nonclient-area messages ) trên MSDN? 5.6.4. Trình bày hi u bi t c a b n v b đnh th i gian ( timer )? S khác nhau gi a thơng đip v b đnh th i gian so v i các thơng đip v bàn phím và thi t b chu t? 5.6.5. Vi thao tác ng ưi dùng ch n m t đi t ưng control (nút nh n, edit text, ) trên m t h p tho i, hãy trình bày l i mơ hình thao tác và x lý thơng đip t ươ ng ng? Hưng d n: L ưu ý c a s nh n thơng đip là h p tho i, và thơng đip t ươ ng ng là WM_COMMAND . 5.6.6. Vi t ch ươ ng trình minh h a thao tác nh n phím t ươ ng t ví d ZoomAnh trên. Ch ươ ng trình th c hi n thao tác phĩng to ho c thu nh mt nh bitmap khi ng ưi dùng click chu t trái ho c ph i t ươ ng ng trên màn hình? 5.6.7. M rng ch ươ ng trình 5.6.6 th c hi n thao tác zoom nh theo t l đưc ch n trên m t 1 menu cho tr ưc, g m zoom ½, ¼, và /8? 5.6.8. M rng ch ươ ng trình 5.6.6 th c hi n thao tác zoom nh ch khi ng ưi dùng click vào bên trong đi t ưng nh đang hi n th ? 5.6.9. Vi t ch ươ ng trình xu t ra chính gi a màn hình t a đ con tr chu t (thay đi khi ng ưi dùng di chuy n thi t b chu t trong vùng làm vi c)? 5.6.10. Vi t ch ươ ng trình xu t ra màn hình ng u nhiên các đưng trịn v i màu s c và bán kính bt k ỳ mi m t giây (second)? 116
  44. Hưng d n: S dng b đnh th i gian đ thi t l p đnh k ỳ gi thơng đip v th i gian. M i khi thơng đip này đưc kích ho t, ta dùng hàm int rand( void ); - th ư vi n stdlib.h – đ phát sinh giá tr ng u nhiên cho bán kính, tâm đưng trịn, c ũng nh ư giá tr màu s c. L ưu ý là tâm đưng trịn nên đưc xác đnh thơng qua kích th ưc c a màn hình (xác đnh b ng thơng đip WM_SIZE ), và giá tr màu s c là 0 255 cho t ng thơng s Red, Green, Blue khi dùng macro RGB . 117
  45. Bài 6 CƠ B N V LP TRÌNH V I MFC Vi các bài h c v a qua, chúng ta đã n m đưc các đc đim c ơ b n nh t v lp trình trên Windows, s dng các hàm API đ vi t các ng d ng d ng Win32 Application . ðây là cách th c l p trình khá đơ n gi n, đng th i giúp ng ưi h c hi u và v n d ng c th các ki n th c v Windows đ x lý cho các ng d ng, tuy nhiên nĩ l i khơng ph i là cách mà các l p trình viên th ưng s dng đ xây d ng các ng d ng Windows-based b ng ngơn ng C. Kt h p c ơ ch hưng đi t ưng ( object oriented ), các chuyên gia c a Microsoft đã m rng cách l p trình, thao tác các hàm API m t cách gián ti p đ to các ng d ng trên Windows. Cách l p trình này s dng th ư vi n các l p đi t ưng n n t ng trên Windows đã đưc Microsoft t ch c l i, g i là MFC (Microsoft Foundation Class ) theo khung ng d ng ( Application Framework ) riêng. Bài h c này đưc chúng tơi đư a thêm vào cu i giáo trình nh ư ph n đc thêm ca mơn Lp trình Windows , v i mong mu n cung c p cho sinh viên nh ng ki n th c c ơ s nh t v MFC đ các b n cĩ th t tìm hi u và phát tri n kh năng l p trình c a mình sau khi đã cĩ m t kh i l ưng ki n th c c ơ b n v lp trình tr c ti p các hàm API các bài h c tr ưc. 6.1. MFC APPLICATION FRAMEWORK Mi m t ng d ng, khi l p trình, đu ph i tuân theo m t c u trúc nh t đnh g n li n v i ngơn ng và trình biên d ch h tr nĩ. Chúng ta đã quen thu c v i vi c th hi n m i thao tác c a ng dng trong hàm main vi t b ng C chu n trên DOS, ho c là hàm WinMain ca m t ng d ng Win32 Application kh i t o c a s ri sau đĩ x lý v i hàm WndProc . Tươ ng t , đ xây d ng m t ng d ng trên Windows s dng c ơ ch h tr ca MFC, chúng ta c ũng c n th c hi n theo m t đnh d ng khung ng d ng cho tr ưc, đưc g i là MFC Application Framework . Khung ng d ng này c a MFC đưc đnh ngh ĩa nh ư là “m t b tích hp các thành ph n ph n m m h ưng đi t ưng v i m c đích h tr tt c nh ng gì c n thi t cho lp trình viên t o l p và qu n lý code ng d ng”. Gi i thích đơ n gi n h ơn, chúng ta ch cn hi u đĩ là c u trúc cĩ th kt h p ch t ch các l p đi t ưng c a th ư vi n MFC vào trong ng d ng đ qu n lý (ch khơng s dng riêng l mt đi tưng b t k ỳ nào đĩ đưc đnh ngh ĩa ch trong ng d ng theo khái ni m l p trình h ưng đi tưng thu n tuý). Th t ra, ng d ng MFC là m t m rng cho d ng ng d ng Win Application trên Windows, 118
  46. th nên c ũng tuân th cu trúc x lý c a m t ng d ng Windows v i các hàm API đã đưc đnh ngh ĩa tr ưc, ngh ĩa là c ũng c n cĩ m t đi t ưng ti n trình (instance), c ũng đnh nghĩa m t c a s chính (window), c ũng b t đu ng d ng b ng kh i t o hàm WinMain , r i x lý theo c ơ ch thơng đip Và ch khác là t t c nh ng đc đim này đưc ánh x sang Application Framework mà thơi. ð d dàng n m b t v n đ hơn, chúng ta cùng nhau xây d ng ng d ng d ng MFC Application và cùng phân tích các đc đim v a nêu thơng qua ví d MFCExample . 6.1.1. T o l p project MFC s dng AppWizard Tươ ng t vi c t o l p project Win32 Application, khi t o l p m t project MFC, ta c ũng nên s dng cơng c AppWizard mà Microsoft Visual C++ 6.0 h tr đ phát sinh các thành ph n c ơ bn nh t cho project theo các c u trúc đã đưc đnh ngh ĩa tr ưc. Thay vì ch n ch n project d ng Win32 Application, ta ch n project d ng MFC AppWizard (exe) ri gõ tên project nh ư đã bi t – xem hình 6.1. Hình 6.1. Project MFCExample dng MFC AppWizard (exe) Sau khi ch n OK , AppWizard chuy n sang b ưc 1 cho phép l p trình viên ch n d ng ng dng cho project này. Trên Windows, các ng d ng th ưng thu c m t trong ba d ng chính là: ng d ng đơ n tài li u ( single document ), ví d nh ư ng d ng Microsoft Paint , ch thao tác m t tài li u t i m t th i đim; ng d ng đa tài li u ( multiple documents ), v i ph n m m Microsoft Visual C++ 6.0 mà chúng ta đang dùng là m t đin hình, cho phép ta cĩ th m nhi u c a s đ so n th o các n i dung khác nhau; và ng d ng d ng h p tho i ( dialog based ) v i giao di n chính là m t h p tho i, ví d nh ư là ng d ng Microsoft Calculator . 119
  47. Hình 6.2. Ch n project d ng Single document đây chúng ta ch n project d ng Single document cĩ h tr ki n trúc Document-View (xem ph n 6.3). Sau đĩ qua các b ưc ti p theo. các b ưc t 2 đn 5 ta ch n các thơng tin mc đnh mà AppWizard cung c p. Cu i cùng, bưc th 6, Visual C++ 6.0 li t kê 4 l p đi tưng chính c u thành project MFC AppWizard mà chúng ta c n phân tích, bao g m l p khung nhìn CMFCExampleView , l p đi t ưng ng d ng CMFCExampleApp , l p c a s ng d ng CMainFrame và l p d li u CMFCExampleDoc . Bình th ưng ta dùng luơn thơng s các lp cơ s (base class) c a chúng, tuy nhiên đây ta ch n l p c ơ s v khung nhìn là CScrollView đ minh h a m t s thao tác khi trình bày m t s vn đ ti p theo - xem hình 6.3. 120
  48. Hình 6.3. Các l p đi t ưng chính c a project MFCExample Sau khi ch n Finish , MS Visual C ++ 6.0 thơng báo k t qu to l p project v i các thơng s đã ch n. Chúng ta ch n OK đ kt thúc và chuy n sang tìm hi u code c a chúng. 6.1.2. ði t ưng ng d ng và c a s vi th ư vi n MFC Nh ư đã trình bày trên, m t project ng d ng d ng MFC là m t khung k t h p các l p đi tưng đã đưc Microsoft đnh ngh ĩa vào m t c u trúc ch t ch . Các l p đi t ưng này cĩ th k th a, tác đng qua l i l n nhau d a trên các đc tr ưng hưng đi t ưng ca chúng. Hình 6.4 mơ t mt ph n b ng phân c p các l p trong th ư vi n MFC 7.0 giúp ta cĩ m t cái nhìn tồn v n h ơn v chúng. Hình 6.4. 121
  49. Mt ph n b ng phân c p các l p c a th ư vi n MFC 7.0 Mt ng d ng thơng th ưng và c ơ b n nh t d ng MFC ph i cĩ duy nh t m t đi t ưng ng dng - trong ví d va t o l p là đi t ưng CMFCExampleApp theApp - tươ ng t nh ư đi tưng HINSTANCE hInst ca ng d ng d ng Win32 Application, và m t ca s - đây là CMainFrame - tươ ng t đi t ưng HWND hWnd xác đnh giao di n chính c a ng d ng. Hai đi t ưng này đưc c u trúc và cài đt d a trên hai l p c ơ s CWinApp và CFrameWnd ca MFC. ð phân tích k hơn v chúng, chúng ta cùng xem code trong project MFCExample đưc Visual C ++ 6.0 phát sinh. Tp tin header MFCExample.h đnh ngh ĩa c u trúc l p CMFCExampleApp nh ư sau: 1 // MFCExample.h : main header file for the MFCEXAMPLE application 2 // 3 4 #if !defined(AFX_MFCEXAMPLE_H__9735298D__INCLUDED_) 5 #define AFX_MFCEXAMPLE_H__9735298D__INCLUDED_ 6 7 #if _MSC_VER > 1000 8 #pragma once 9 #endif // _MSC_VER > 1000 10 11 #ifndef __AFXWIN_H__ 12 #error include 'stdafx.h' before including this file for PCH 13 #endif 14 15 #include "resource.h" // main symbols 16 122
  50. 17 ////////////////////////////// /////////////////////////////////////////////// 18 // CMFCExampleApp: 19 // See MFCExample.cpp for the implementation of this class 20 // 21 22 class CMFCExampleApp : public CWinApp 23 { 24 public: 25 CMFCExampleApp(); 26 27 // Overrides 28 // ClassWizard generated virtual function overrides 29 //{{AFX_VIRTUAL(CMFCExampleApp) 30 public: 31 virtual BOOL InitInstance(); 32 //}}AFX_VIRTUAL 33 34 // Implementation 35 //{{AFX_MSG(CMFCExampleApp) 36 afx_msg void OnAppAbout(); 37 // NOTE the ClassWizard will add and remove member functions here. 38 // DO NOT EDIT what you see in these blocks of generated code ! 39 //}}AFX_MSG 40 DECLARE_MESSAGE_MAP() 41 }; 42 43 44 ///////////////////////////////////////////////////////////////////////////// 45 46 //{{AFX_INSERT_LOCATION}} 47 // Microsoft Visual C++ will insert additional declarations immediately before the 48 previous line. 49 50 #endif // !defined(AFX_MFCEXAMPLE_H__9735298D__INCLUDED_) Chi ti t cài đt đưc th hi n trong t p tin MFCExample.cpp . 1 // MFCExample.cpp : Defines the class behaviors for the application. 2 // 3 4 #include "stdafx.h" 5 #include "MFCExample.h" 6 7 #include "MainFrm.h" 8 #include "MFCExampleDoc.h" 9 #include "MFCExampleView.h" 10 11 #ifdef _DEBUG 12 #define new DEBUG_NEW 13 #undef THIS_FILE 14 static char THIS_FILE[] = __FILE__; 15 #endif 16 17 ///////////////////////////////////////////////////////////////////////////// 18 // CMFCExampleApp 19 20 BEGIN_MESSAGE_MAP(CMFCExampleApp, CWinApp) 21 //{{AFX_MSG_MAP(CMFCExampleApp) 22 ON_COMMAND(ID_APP_ABOUT, OnAppAbout) 23 // NOTE the ClassWizard will add and remove mapping macros here. 24 // DO NOT EDIT what you see in these blocks of generated code! 25 //}}AFX_MSG_MAP 26 // Standard file based document commands 27 ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) 28 ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) 29 // Standard print setup command 123
  51. 30 ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp:: OnFilePrintSetup) 31 END_MESSAGE_MAP() 32 33 ///////////////////////////////////////////////////////////////////////////// 34 // CMFCExampleApp construction 35 36 CMFCExampleApp::CMFCExampleApp() 37 { 38 // TODO: add construction code here, 39 // Place all significant initialization in InitInstance 40 } 41 42 ///////////////////////////////////////////////////////////////////////////// 43 // The one and only CMFCExampleApp object 44 45 CMFCExampleApp theApp; 46 47 ///////////////////////////////////////////////////////////////////////////// 48 // CMFCExampleApp initialization 49 50 BOOL CMFCExampleApp::InitInstance() 51 { 52 AfxEnableControlContainer(); 53 54 // Standard initialization 55 // If you are not using these features and wish to reduce the size 56 // of your final executable, you should remove from the following 57 // the specific initialization routines you do not need. 58 59 #ifdef _AFXDLL 60 Enable3dControls(); // Call this when using MFC in a shared DLL 61 #else 62 Enable3dControlsStatic(); // Call this when linking to MFC statically 63 #endif 64 65 // Change the registry key under which our settings are stored. 66 // TODO: You should modify this string to be something appropriate 67 // such as the name of your company or organization. 68 SetRegistryKey(_T("Local AppWizardGenerated Applications")); 69 70 LoadStdProfileSettings(); // Load standard INI file options (including MRU) 71 72 // Register the application's document templates. Document templates 73 // serve as the connection between documents, frame windows and views. 74 75 CSingleDocTemplate* pDocTemplate; 76 pDocTemplate = new CSingleDocTemplate( 77 IDR_MAINFRAME, 78 RUNTIME_CLASS(CMFCExampleDoc), 79 RUNTIME_CLASS(CMainFrame), // main SDI frame window 80 RUNTIME_CLASS(CMFCExampleView)); 81 AddDocTemplate(pDocTemplate); 82 83 // Parse command line for standard shell commands, DDE, file open 84 CCommandLineInfo cmdInfo; 85 ParseCommandLine(cmdInfo); 86 87 // Dispatch commands specified on the command line 88 if (!ProcessShellCommand(cmdInfo)) 89 return FALSE; 90 91 // The one and only window has been initialized, so show and update it. 92 m_pMainWnd>ShowWindow(SW_SHOW); 93 m_pMainWnd>UpdateWindow(); 94 95 return TRUE; 96 } 124
  52. 97 98 99 ///////////////////////////////////////////////////////////////////////////// 100 // CAboutDlg dialog used for App About 101 102 class CAboutDlg : public CDialog 103 { 104 public: 105 CAboutDlg(); 106 107 // Dialog Data 108 //{{AFX_DATA(CAboutDlg) 109 enum { IDD = IDD_ABOUTBOX }; 100 //}}AFX_DATA 111 112 // ClassWizard generated virtual function overrides 113 //{{AFX_VIRTUAL(CAboutDlg) 114 protected: 115 virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support 116 //}}AFX_VIRTUAL 117 118 // Implementation 119 protected: 120 //{{AFX_MSG(CAboutDlg) 121 // No message handlers 122 //}}AFX_MSG 123 DECLARE_MESSAGE_MAP() 124 }; 125 126 CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) 127 { 128 //{{AFX_DATA_INIT(CAboutDlg) 129 //}}AFX_DATA_INIT 130 } 131 132 void CAboutDlg::DoDataExchange(CDataExchange* pDX) 133 { 134 CDialog::DoDataExchange(pDX); 135 //{{AFX_DATA_MAP(CAboutDlg) 136 //}}AFX_DATA_MAP 137 } 138 139 BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) 140 //{{AFX_MSG_MAP(CAboutDlg) 141 // No message handlers 142 //}}AFX_MSG_MAP 143 END_MESSAGE_MAP() 144 145 // App command to run the dialog 146 void CMFCExampleApp::OnAppAbout() 147 { 148 CAboutDlg aboutDlg; 149 aboutDlg.DoModal(); 150 } 151 152 ///////////////////////////////////////////////////////////////////////////// 153 // CMFCExampleApp message handlers Bi n đi t ưng ng d ng theApp đưc khai báo dịng 45 c a t p tin cài đt, và nh ư đã nĩi, đây chính là đi t ưng mà Windows dùng đ qu n lý ng d ng khi th c thi. ð ý r ng t t c các ng d ng trên Windows đu đưc b t đu g i th c thi t hàm WinMain , vì th ng d ng MFC cũng cĩ hàm WinMain , tuy nhiên Application Framework đã gi u hàm này, và chúng ta khơng th y trong source code. Khi hàm WinMain đưc g i, ng d ng s tìm đi t ưng tồn c c trên và 125