Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 20 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
20
Dung lượng
408,07 KB
Nội dung
Iczelion’s Tutorial Win32 ASM Tutorial 3 : A Simple Window Tìmhiểuvềcửasổứngdụng Trong bài viết này, chúng ta sẽ xây dựng một chương trình với đầy đủ chức năng của một cửasổứngdụng trên desktop. Tìmhiểuvềcửa sổ, lớp cửasổ Trong một ứngdụng đồ họa 32-bit, cửasổ (window) là một vùng hình chữ nhật trên màn hình, nơi mà ứngdụng có thể hiện thị thông tin và nhận thông tin vào từ người dùng (users). Do vậy, nhiệm vụ đầu tiên của một ứngdụng đồ họa 32-bit là tạo một cửa sổ. Một cửasổ sẽ chia sẻ màn hình với các cửasổ khác trong cùng một ứngdụng hay với các ứngdụng khá c. Chỉ một cửasổ trong một thời điểm nhận được thông tin nhập từ người dùng thông qua 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ửasổ và ứng dụng. Tất cả các cửasổ đều đựơc tạo từ một cấu trúc được cung cấp sẵn gọi là lớp cửasổ (window class). Cấu trúc này là một tập hợp các 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ửasổ phải là thành viên của một lớp cửa sổ. Tất cả các lớp cửasổ này đều được xử lý riêng biệt. Người dịch: Benina (REA TEAM) Trang 1 Tổng hợp và hiệu chỉnh: NhatPhuongLe (VNCERT TEAM) Iczelion’s Tutorial Win32 ASM Tutorial 3 : A Simple Window Các chương trình trên Windows thường sử dụng các API để thiết kế giao diện (GUI) cho chúng. Bằng cách này, nó có lợi cho cả người sử dụng và cả lập trình viên. Đối với người sử dụng, họ không cần phải tìmhiểu làm thế nào để sử dụng giao diện đồ họa cho mỗi chương trình mới, giao diện của các chương trình là tương tự nhau. Đối với các lập trình viên, mã lệnh để tạo nên giao diện chương trình đã sẵn, đư ợc test và sẵn sàng cho việc sử dụng. Nhưng mặt khác, việc giao diện được thiết kế sẵn theo khuôn mẫu của HĐH sẽ làm tăng thêm sự tạp trong việc các lập trình muốn cài đặt hay thao tác trên các đối tượng bất kỳ của giao diện như là hộp thoại , menus, icons, … vì họ phải tuân theo một nguyên tắc chính xác, nhưng điều này có thể khắc phục bằng cách lập trình theo đơn thể hoặc theo hướng đối tượng ( OOP). Tôi sẽ phát thảo những bước cần thiết để xây dựngcửasổứngdụng trên desktop: 1. Lấy handle của thể hiện – chính là bản thân ứngdụng Handle là một số nguyên không dấu 32bit do HĐH tạo ra để làm định danh cho mỗi đối tượng. Còn lý do tại sao phải xin HĐH cấp một handle và vì sao gọi là instance handle (handle của thể hiện). Vì Windows là HĐH đa nhiệm, có thể có nhiều bản của cùng một chương trình cùng chạy vào cùng một thời điểm nên phải cần phải có 1 handle của chương trình ngay lúc chúng đang được active (nghĩa là đang được thao tác). Ngoài ra, để quản lý chặt chẽ hơn, HĐH còn có khái niệm hPrevinst là chỉ sốcủa bản đã được khởi động trước đó và chúng luôn có giá trị NULL 2. Lấy địa chỉ của xâu ký tự các đối số dòng lệnh (command line), không cần thiết trừ khi chương trình thực hiện bằng dòng lệnh) 3. Định nghĩa lớp cửasổ và đăng ký nó với HĐH (trừ khi bạn dùng loại cửasổ đã được HĐH định nghĩa trước như MessageBox hay Dialogbox). 4. Tạo lập cửasổ làm việc cho ứng dụng. 5. Hiển thị cửasổ trên desktop (trừ khi bạn không muốn hiển thị cửasổ nga y) 6. Luôn luôn vẽ (paint) và vẽ lại (repaint) vùng client củacửasổHiểu như thế nào là vẽ và vẽ lại? Có nghĩa là người dùng có thể di chuyển cửaa sổcủa một hay nhiều chương trình khác trên màn hình và sự di chuyển sẽ che một phần cửasổcủaứng dụng. HĐH sẽ không lưu phần cửasổ mà bị chương trình khác che. Khi cửasổ bị/được di chuyển, HĐH sẽ gửi yêu cầu vẽ lại vùng client củacửa sổ. Người dịch: Benina (REA TEAM) Trang 2 Tổng hợp và hiệu chỉnh: NhatPhuongLe (VNCERT TEAM) Iczelion’s Tutorial Win32 ASM Tutorial 3 : A Simple Window 7. Nhận và xử lý thông điệp thông qua vòng lặp thông điệp. Chúng ta xét qua lược đồ quản lý sự kiện và thông điệp của HĐH : Trình tự xử lý thông điệp được mô tả như sau: Nhận một thông điệp thông qua hàm API GetMessage() từ hàng đợi thông điệp củaứng dụng. Ngoại trừ thông điệp WM_QUIT, mỗi thông điệp sẽ trả về cho hàm GetMessage() một thông số khác 0 (TRUE). Khi nhận thông điệp WM_QUIT thì chương trình sẽ thoát khỏi vòng lặp và chấm dứt hoạt động chương trình. Hàm GetMessage() này nhận vào 4 tham số đầu vào tro ng đó tham số thứ 1 quan trọng là con trỏ trỏ về một cấu trúc kiểu MSG. Sau đó, giải mã thông điệp này thông qua hàm API TranslateMessage(). Hàm này sẽ gọi trình điều khiển bàn phím (Keyboard driver) để chuyển đổi những thông điệp từ bàn phím do người dùng gõ (ví dụ WM_KEYDOWN, WM_KEYUP, …) thành những ký tự để đưa các trị này vào hàng đợi thông điệp củaứngdụng dưới dạng thông điệp WM_CHAR. Nghĩa là chương trình của Người dịch: Benina (REA TEAM) Trang 3 Tổng hợp và hiệu chỉnh: NhatPhuongLe (VNCERT TEAM) Iczelion’s Tutorial Win32 ASM Tutorial 3 : A Simple Window bạn có đủ khả năng phân biệt chữ A (a hoa) và a (a thường) mà không cần biết có phím SHIFT đang hoạt động. Rồi sau đó, phân công giải quyết bởi một hàm thích hợp thông qua hàm API DispatchMessage() để xem dữ kiện chứa trong cấu trúc MSG để gọi cho đúng hàm giải quyết thông điệp. Hàm này sẽ push thông điệp vào Window Procedure để bắt đầu xử lý thông điệp. Vòng lặp While tiếp tục chạy cho đến khi nào GetMessage() trả về giá trị 0 cho biết là không còn cái thông điệp nào trong hàng đợi thông điệp và lúc này thông điệp chấm dứt. Hệ điều hành Windows sẽ phân công giải quyết các thông điệp thông qua một thủ tục gọi là Windows Procedure () và thường được lập trình viên đặt tên là WinProc(). Đoạn code trong thủ tục WndProc() này là phần mà bạn phải nhọc công lập trình. Các thông số bên trong các lớp Window (Window Class - WNDCLASS), các hàm API như GetMessage(), ShowWindow(), … bạn có thể tự tì m hiểu thông qua MSDN hoặc ebook Microsoft® Win32® Programmer's Reference. 8. Nếu thông điệp được gởi tới cửa sổ, chúng sẽ được xử lý bởi một hàm đặc biệt (được gọi là Window Procedure) củacửa sổ. Trong mỗi chương trình trên nền Windows, bộ phận trung tâm là 1 hoặc nhiều hàm nhận và xử lý các thông điệp. Các hàm này được gọi là Window Procedure() viết tắt là WndProc(). Đứngvề mặt lập trình, thì cấu trúc của WndProc thường là lệnh switch() với những trường hợp cho những thông điệp khác nhau. Trong trường hợp của chúng ta, chỉ có hai case là xử lý thông điệp WM_PAINT và thông điệp WM_DESTROY. Trong thực tế các ứngdụng thường chứa một switch khổng lồ với số lượng trường hợp nhiều kinh khủng. Giá trị trả vềcủa WndProc() tùy thuộc vào loại thông điệp. Mỗi WndProc() đều cần 4 tham số đầu vào : hwnd : handle của thông điệp msg và 2 thông số khác là wparam và lparam. Tham số hwnd này rất quan trọng vì một WndProc() có thể hỗ trợ nhiều cửasổ khác nhau trên màn hình cùng một lúc. Do đó, tham số hwnd sẽ nhận diện cửasổ nào đã gọi WndProc() của chúng ta. msg : cho số thứ tự của thô ng điệp. Nếu hwnd cho biết ai gọi thì msg cho biết nó muốn gì. Có thể. Có thể nó muốn nói là cửasổ mới tạo xong (WM_CREATE) hoặc di chuyển đến vị trí mới (WM_MOVE) hoặc thay đổi kích thước (WM_SIZE) hoặc vẽ lại ứngdụng (WM_PAINT) hoặc khi người dùng nhấn nút Close đóng cửasổứngdụng lại (WM_DESTROY). 9. Thoát chương trình nếu người dùng đóng cửasổ Như bạn thấy, cấu trúc của một chương trình chạy trên nền Windows khá phức tạp so với chương trình chạy trên nền Dos. Nhưng trong thế giới Windows khác hoàn toàn so với thế giới Dos. Những chương trình Winodws có thể “chung sống” êm thắm với nhau. Chúng phải tuân thủ theo các nguyên tắc. Bạn - một lập trình viên - càng phải nghiêm ngặt hơn trong thói quen và phong cách lập trình của mình. Người dịch: Benina (REA TEAM) Trang 4 Tổng hợp và hiệu chỉnh: NhatPhuongLe (VNCERT TEAM) Iczelion’s Tutorial Win32 ASM Tutorial 3 : A Simple Window Xây dựng một ứngdụng Win32 ASM đơn giản Dưới đây là source code xây dựng một cửasổứngdụng đơn giản. Trước khi đi vào các chi tiết phức tạp trong việc lập trình Win32 ASM , tôi sẽ điểm qua một số điểm quan trọng để cho bạn lập trình được dễ dàng. Bạn nên sẽ đặt tất cả các hằng số, cấu trúc và các khai báo hàm (prototypes) trong một file include và include nó ngay lúc bắt đầu code của file .asm của bạn. Nó sẽ giúp bạn tránh đư ợc lỗi do gõ sai. Hiện thời, file include hòan chỉnh nhất cho MASM là windows.inc. Bạn cũng có thể định nghĩa những hằng số cho riêng bạn và những định nghĩa cấu trúc ,nhưng bạn sẽ đặt chúng vào trong một file include riêng biệt với windows.inc. Dùng chỉ thị includelib để chỉ rõ thư viện nhập nào được sử dụng trong chương trình của bạn. Ví dụ, nếu chương trình của bạn gọi Me ssageBox, bạn sẽ gọi chỉ thị includelib với cú pháp như sau: includelib user32.lib tại vị trí bắt đầu trong file .asm của bạn. Chỉ thị này nói cho MASM biết rằng chương trình của bạn có sử dụng những hàm trong thư viện nhập có tên là user32.lib. Nếu chương trình gọi những hàm mà những hàm này nằm trong nhiều hơn một thư viện nhập, chỉ cần thêm một includelib cho mỗi thư viện bạn dùng. Bằng các h sử dụng chỉ thị includelib, bạn sẽ không phải lo lắng về các thư viện nhập này trong lúc liên kết chương trình để tạo ra file thực thi (file .EXE). Bạn có thể dùng /LIBPATH để nói cho trình liên kết biết tất cả các thư viên đó ở đâu. Khi khai báo prototypes các hàm API, cấu trúc hay hằng số trong file include của bạn, hãy cố bám sát các tên gốc được dùng trong file include của HĐH. Điều này giúp bạn đỡ phải tra cứu một vài mục Win32 API reference. Sử dụng makefile để trình biê n dịch tự động dịch chương trình của bạn. Điều này sẽ giúp bạn tiết kiệm thời gian thay vì phải gõ lệnh biên dịch. .386 .model flat,stdcall option casemap:none include windows.inc include user32.inc includelib user32.lib ; Goi cac ham trong user32.lib ; va kernel32.lib include kernel32.inc includelib kernel32.lib ; Khai bao prototype ham WinMain WinMain proto :DWORD,:DWORD,:DWORD,:DWORD .DATA ; Nhung du lieu duoc khoi tao truoc ClassName db "SimpleWinClass",0 ; Ten cua lop cuaso AppName db "Our First Window",0 ; Ten cuacuaso Người dịch: Benina (REA TEAM) Trang 5 Tổng hợp và hiệu chỉnh: NhatPhuongLe (VNCERT TEAM) Iczelion’s Tutorial Win32 ASM Tutorial 3 : A Simple Window .DATA? ; Nhung du lieu khong duoc khoi tao hInstance HINSTANCE ? ; handle cua the hien cuaungdung CommandLine LPSTR ? .CODE ; Here begins our code start: invoke GetModuleHandle, NULL ; Lay handle cua the hien cuaungdung hInstance,eax mov hInstance,eax invoke GetCommandLine ; Lay dia chi cua xau ky tu chua ; cac doi so dong lenh. ; Ban khong can goi ham nay neu nhu ; chuong trinh cua ban khong thuc hien ; bang dong lenh mov CommandLine,eax invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT ; Goi ham ; WinMain invoke ExitProcess, eax ; Thoat khoi ung dung. ; Gia tri tra vecua ExitProcess duoc ; luu trong eax cua WinMain. WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE, CmdLine:LPSTR,CmdShow:DWORD LOCAL wc:WNDCLASSEX ; Tao cac bien cuc bo trong ngan xep LOCAL msg:MSG LOCAL hwnd:HWND mov wc.cbSize,SIZEOF WNDCLASSEX ; Dien day du gia tri cho ; cac bien cua lop cuaso mov wc.style, CS_HREDRAW or CS_VREDRAW mov wc.lpfnWndProc, OFFSET WndProc mov wc.cbClsExtra,NULL mov wc.cbWndExtra,NULL push hInstance pop wc.hInstance mov wc.hbrBackground,COLOR_WINDOW+1 mov wc.lpszMenuName,NULL mov wc.lpszClassName,OFFSET ClassName invoke LoadIcon,NULL,IDI_APPLICATION mov wc.hIcon,eax mov wc.hIconSm,eax invoke LoadCursor,NULL,IDC_ARROW mov wc.hCursor,eax invoke RegisterClassEx, addr wc ; Dang ky lop cuaso voi HDH invoke CreateWindowEx,NULL,\ ADDR ClassName,\ ADDR AppName,\ WS_OVERLAPPEDWINDOW,\ CW_USEDEFAULT,\ CW_USEDEFAULT,\ CW_USEDEFAULT,\ CW_USEDEFAULT,\ NULL,\ NULL,\ hInst,\ NULL mov hwnd,eax invoke ShowWindow, hwnd,CmdShow ; Hien thi cuaso ra desktop invoke UpdateWindow, hwnd ; Ve va ve lai vung client cuacuaso Người dịch: Benina (REA TEAM) Trang 6 Tổng hợp và hiệu chỉnh: NhatPhuongLe (VNCERT TEAM) Iczelion’s Tutorial Win32 ASM Tutorial 3 : A Simple Window .WHILE TRUE ; Vong lap thong diep invoke GetMessage, ADDR msg,NULL,0,0 .BREAK .IF (!eax) invoke TranslateMessage, ADDR msg invoke DispatchMessage, ADDR msg .ENDW mov eax,msg.wParam ; Tra gia tri trong thanh ghi eax ret WinMain endp WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM .IF uMsg==WM_DESTROY ; Neu nguoi dung dong cuaso dong cuaso invoke PostQuitMessage,NULL ; thi thoat ungdung .ELSE invoke DefWindowProc,hWnd,uMsg,wParam,lParam ; Nguoc lai thi xu ly thong diep theo mac dinh cua HDH ret .ENDIF xor eax,eax ret WndProc endp end start Phân tích mã lệnh Bạn đã thấy một chương trình tạo một cửasổứngdụng đơn giản cần phải code rất nhiều mã lệnh như trên. Nhưng phần lớn những đoạn code đó chỉ là một template code (mã nguồn mẫu) mà bạn có thể copy từ mã lệnh của file này đến mã lệnh của một file khác. Hay nếu bạn thích, bạn có thể dịch một vài đoạn mã nguồn đó vào trong một thư viện để dùng như một đọan mở đầu hay đọan code cuối. Bạn có thể chỉ viết code trong hàm WinMain. Thật vậy, đây là những gì mà trình biên dịch C đã làm sẵn. Chúng cho phép bạn viết code hàm WinMain không cần phải lo làm những công việc “vặt vảnh” khác. Khác với trình biên dịch C là bạn phải có một hàm có tên là WinMain, nếu không sẽ không thể kết hợp code của bạn với đoạn đầu hay đọan cuối của code. Bạn không bị hạn chế vấn đề nà y trong ngôn ngữ ASM. Bạn có thể dùng bất kỳ tên hàm nào không nhất thiết là WinMain hoặc không có hàm nào cũng không sao. Tiếp theo là những giải thích về đoạn code đã viết ở trên. Nó rất dài, chúng ta hãy cùng nhau phân tích chương trình này để làm rõ vấn đề xây dựng một ứngdụng Win32 ASM không đến nổi quá phức tạp như bạn nghĩ. .386 .model flat,stdcall option casemap:none WinMain proto :DWORD,:DWORD,:DWORD,:DWORD include windows.inc include user32.inc include kernel32.inc includelib user32.lib includelib kernel32.lib Người dịch: Benina (REA TEAM) Trang 7 Tổng hợp và hiệu chỉnh: NhatPhuongLe (VNCERT TEAM) Iczelion’s Tutorial Win32 ASM Tutorial 3 : A Simple Window Ba dòng trước tiên rất cần thiết vì: .386: nói cho MASM biết rằng chúng ta có ý định sử dụng cấu trúc bộ lệnh 80386 trong chương trình. .model flat,stdcall: nói cho MASM rằng kiểu bộ nhớ đang sử dụng cho chương trình là kiểu flat memory. Cũng như bạn sẽ dùng tham số stdcall để quy ướ cách truyền tham số cho hàm như thế nào. option casemap:none nói cho MASM biết rằng tên các nhãn trong chương trình phân biệt chữ hoa, chữ thường, vì vậy ExitProcess sẽ khác với exitprocess. Kế đến là khai báo prot otype của hàm WinMain. Sau này, khi chúng ta gọi hàm WinMain, chúng ta ta phải định nghĩa lại prototype của hàm để có thể sử dụng được hàm invoke. Chúng ta phải include file windows.inc phần bắt đầu trong mã nguồn. Nó chứa các cấu trúc quan trọng, các hằng số được dùng trong chương trình của chúng ta. File include windows.inc chỉ là một file text. Bạn có thể mở nó với bất kỳ trình sọan thảo vănbản nào. Xin chú ý rằng file windows.inc không chứa tất cả các cấu trúc và các hằng số. Bạn c ó thể thêm các đối tượng mới (cấu trúc, hằng số, …) mới nếu không có trong file. Chương trình ứngdụng gọi các hàm API chứa trong user32.dll (CreatWindowEx, RegisterWindowClassEx và gọi hàm API chứa trong kernal32.dll (ExitProcess), vì thế chúng ta phải liên kết chương trình với các thư viện nhập này. Câu hỏi kế tiếp là: “Làm thế nào tôi biết được thư viện nhập nào được liên kết với chương trình của chúng ta? ” Bạn phải biết API nằm ở đâu để có thể gọi các hàm API. Ví dụ: nếu bạn gọi một hàm API trong gdi32.dll , bạn phải liên kết với với gdi32.lib. Đây là cách mà MASM giải quyết vấn đề. Còn đối với TASM, cách liên kết với các thư viện nhập thì đơn giản hơn, chỉ cần liên kết đến một và chỉ một file mà thôi: import32.lib. .DATA ClassName db "SimpleWinClass",0 AppName db "Our First Window",0 .DATA? hInstance HINSTANCE ? CommandLine LPSTR ? Kế đến là section “DATA” Trong section .DATA, chúng ta khai báo những chuỗi kết thúc bằng zero. Classname là tên của lớp cửasổ (Window class) Appname là tên cửasổứngdụngcủa chúng ta. Người dịch: Benina (REA TEAM) Trang 8 Tổng hợp và hiệu chỉnh: NhatPhuongLe (VNCERT TEAM) Iczelion’s Tutorial Win32 ASM Tutorial 3 : A Simple Window Chú ý rằng: hai biến này được khởi tạo giá trị từ ban đầu. Trong section .DATA?, hai biến được khai báo: hInstance: viết tắt của 2 từ instance handle – là định danh của thể hiện của chương trình được HĐH cấp phát. CommandLine : địa chỉ của xâu ký tự dòng lệnh của chương trình. Bạn để ý biến hInstance chúng ta báo kiểu dữ liệu là HINSTANCE và biến CommandLine khai báo kiểu LPSTR. Đây là 2 kiểu dữ liệu mới, n hưng thật ra chính là một tên khác cho kiểu DWORD, là số nguyên 32-bit không dấu. Bạn có thể nhìn thấy chúng trong windows.inc. HINSTANCE typedef DWORD LPSTR typedef DWORD Chú ý rằng tất cả các biến trong section .DATA? không được gán giá trị khởi tạo ban đầu, đó là do chúng không lưu giữ một giá trị nào khi chương trình được load lên bộ nhớ, nhưng chúng ta muốn dành một vùng nhớ để sau này sử dụng. .CODE start: invoke GetModuleHandle, NULL mov hInstance,eax invoke GetCommandLine mov CommandLine,eax invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT invoke ExitProcess,eax . end start Section .CODE chứa tất cả các chỉ thị lệnh. Các mã lệnh của bạn phải nằm giữa nhãn <nhãn>: và end <nhãn>. Tên của nhãn không quan trọng. Bạn có thể đặt tên cho nó bất kỳ và miễn sao không trùng với các từ khóa, toán tử của MASM. Chỉ thị đầu tiên của chúng ta là gọi hàm GetModuleHandle để lấy instance handle củacửasổứng dụng. Dưới Win32, handle của thể hiện của chương trình và handle của đơn thể là một và giống nha u (tức instance handle = module handle). Bạn có thể tưởng tượng rằng instance handle như là một ID củacửasổ chương trình. Nó được sử dụng như một tham số cho các hàm API khác mà chương trình bạn cần gọi đến, vì vậy thông thường một ý tưởng tốt là copy ID này và lưu nó (hay lưu giữ nó) với một tham số khác có tên là module handle ngay lúc chương trình bắt đầu thực thi. Chú ý: thực tế dưới platfor m Win32, instance handle là một địa chỉ tuyến tính (linear address) của chương trình trong bộ nhớ. Người dịch: Benina (REA TEAM) Trang 9 Tổng hợp và hiệu chỉnh: NhatPhuongLe (VNCERT TEAM) Iczelion’s Tutorial Win32 ASM Tutorial 3 : A Simple Window Vậy địa chỉ tuyến tính là gì ? Lập trình Win32 dựa trên cơ sở flat memory model, mỗi chương trình hoạt động một cách độc lập trên 1 đoạn địa chỉ cơ sở được gọi là linear address space (chứa đựng code, data, và đoạn mã con trong stack - lưu ý: mỗi địa địa chỉ linear address space chứa tối đa khoảng 2^32-1 ô nhớ, bất kỳ địa chỉ nào trong linear address space gọi là linear address) Trở lại đoạn code trên, ta có thể tìm giá trị trả vềcủa hàm trong Win32 trong thanh ghi EAX. Tất cả những giá trị khác được trả về qua những biến được chuyển vào danh sách tham sốcủa hàm mà bạn đã định nghĩa cho lời gọi hàm. Một hàm Win32 mà bạn gọi, chúng sẽ luôn cất giữ giá trị của các thanh ghi đoạn và các thanh ghi EBX,EDI,ESI và EBP. Trái lại, ECX và EDX được xem xét là thanh ghi dùng để xóa giá trị luôn luôn không được dùng để lưu trữ giá trị trả vềcủa một hàm. Ch ú ý: Không có gì chắc rằng giá trị của các thanh ghi EAX, ECX và EDX được cất giữ thông qua lời gọi hàm API. Dòng tiếp theo ( mov hInstance,eax ) có nghĩa là: khi gọi một hàm API, luôn bảo đảm rằng giá trị trả vềcủa hàm được chứa trong thanh ghi EAX. Nếu bất cứ hàm nào của bạn được gọi bởi HĐH, bạn phải làm đúng theo nguyên tắc sau: cất giữ và phục hồi giá trị của các thanh ghi đoạn và EBX, EDI, ESI, EBP trước khi hàm trả về giá trị. Nếu không, chương trình của bạn sẽ bị lỗi ngay lập tức, nguyên tắc này áp dụng bao gồm cả Windows Procedure (WndPr oc) và hàm CALLBACK. Lời gọi hàm GetCommandLine không cần thiết nếu chương trình của bạn không thực thi bằng dòng lệnh. Trong ví dụ này, tôi sẽ chỉ cho bạn gọi nó như thế nào trong trường hợp bạn cần nó trong chương trình. Kế đến là lời gọi hàm WinMain. Trong các chương trình C/C++ viết trên môi trường DOS, thì thường hàm main() được xem là điểm vào chính thức của chương trình (tức là khi bạn nhấn CTRL + F5 để thực thi chương trình thì hệ điều hành sẽ gọi hàm WinMain() này thực hiện trước, và hệ điều hành sẽ load ứngdụngcủa bạn lên trên bộ nhớ RAM. Do đó, WinMain còn được gọi với tên là Program Entry Point hoặc là Orginal Entry Point. int WINAPI WinMain( HINSTANCE hInstance, // handle to current instance HINSTANCE hPrevInstance, // handle to previous instance LPSTR lpCmdLine, // pointer to command line int nCmdShow // show state of window ); Người dịch: Benina (REA TEAM) Trang 10 Tổng hợp và hiệu chỉnh: NhatPhuongLe (VNCERT TEAM) [...]... HĐH rằng cửasổ này là con (cửa sổ cấp thấp hơn) củacửasổ nào khác Nếu vậy thì sẽ có một cửasổ nào đó đóng vai trò là cửasổ cha Chú ý rằng đây không phải là quan hệ chacon như Multiple Document interface - MDI Cửasổ con không nhất định phải thuộc vùng client củacửasổ cha Khái niệm về mối quan hệ này đặc biệt chỉ sử dụng bên trong HĐH Windows Nếu cửasổ cha mất hiệu lực, tất cả các cửasổ con cũng... dụng khi tài nguyên bộ nhớ rất ít ỏi Điểm đáng chú ý ở đây là nếu bạn chỉ định nghĩa riêng cửasổứng dụng, bạn phải điền đầy đủ thông tin của các thuộc tính củacửasổ trong cấu trúc WNDCLASS hay WNDCLASSEX và gọi hàm RegisterClass hay RegisterClassEx để đăng ký với HĐH biết là ứngdụngcủa bạn có sử dụngcửa sổ, trước khi bạn có thể tạo cửasổ cho ứngdụng Tuy nhiên, bạn chỉ đăng ký một lớp cửa sổ. .. mỗi tham số: dwExStyle: Kiểu mở rộng cửasổ Đây là một tham số mới được thêm vào (so với hàm API CreatWindow) Bạn có thể sử dụng những kiểu cửasổ mới của Wins 95 và WinNT Bạn có thể chỉ định kiểu cửasổ thông thường bởi tham số dwStyle nhưng nếu bạn muốn kiểu cửasổ bắt mắt hơn chút xíu như cửasổứngdụng bạn luôn ở trên cùng, hay trong suốt hơn so các cửasổứngdụng khác, bạn phải chỉ rõ chúng tại... tên củacửasổ Chuỗi này sẽ hiện ra trên thanh tiêu đề củacủacửasổ Nếu thông số này có giá trị là NULL, thanh tiêu đề củacửasổ là chuỗi trắng dwStyle: Kiểu củacửasổ Bạn có thể chọn giao diện củacửasổ ở đây Giá trị của thuộc tính này nếu là NULL thì vẫn cửasổ vẫn tồn tại nhưng nó sẽ không có thanh menu, không có các button thu nhỏ, phóng to, và không có button đóng cửasổ Kiểu cửasổ này không... trên bên trái củacửasổ Thông thường giá trị này sẽ là CW_USEDEFAULT, đó là bạn muốn HĐH lựa chọn cho bạn nơi để hiển thị cửasổ ra màn hình desktop nWidth, nHeight: chiều rộng và chiều cao củacửasổ tính bằng pixels Bạn cũng có thể sử dụng CW_USEDEFAULT để HĐH chọn lựa chiều rộng và cao thích hợp cho cửasổứngdụngcủa bạn hWndParent: handle củacửasổ cha (nếu có tồn tạicửasổ cha) Tham số này... rất dễ hiểu Thực chất đó là các thuộc tính của một lớp cửasổ Một lớp cửasổ không có gì hơn là một tập hợp khuôn mẫu hay là sự mô tả rõ ràng của một cửasổ Nó định nghĩa những thuộc tính quan trọng của một cửasổ như: icon, cursor của nó, các hàm thực hiện việc load icon, cursor củacửasổ lên màn hình desktop, như hình dáng, màu sắc của icon thì như thế nào… Bạn tạo một cửasổ từ một lớp cửasổ Đây... Nếu chỉ có một cửa sổ, chúng ta sẽ gán tham số này trị là NULL hMenu: handle củacủa menu cửasổ NULL nếu lớp menu đã được sử dụng Hãy nhìn lại một thành phần của WNDCLASSEX là lpszMenuName lpszMenuName chỉ định menu “mặc định” cho lớp cửasổ Mọi cửasổ được tạo từ lớp cửasổ này sẽ có menu giống nhau Trừ khi bạn chỉ định một kiểu menu mới và sẽ “chồng lên” kiểu menu mặc định cho một cửasổ qua tham số... không có dữ liệu được truyền cho CreateWindow() Cửasổ có thể khôi phục lại giá trị của tham số này bới gọi hàm GetWindowLong mov hwnd,eax invoke ShowWindow, hwnd,CmdShow invoke UpdateWindow, hwnd Khi hàm CreateWindowEx trả về giá trị khác NULL, tức là việc tạo cửasổứngdụng thành công; handle củacửasổ cất trong thanh ghi eax Chúng ta phải nhớ giá trị này để sử dụng trong tương lai Cửasổ mà chúng... lại là WM_DESTROY Thông điệp này được gởi đến thủ tục window khi nào cửasổứngdụng bị đóng lại Trong thời gian cửasổ nhận được thông điệp này, nó sẽ biến mất khỏi màn hình Đây chỉ là sự thông báo cửasổcủa bạn mất hiệu lực, do chính bạn muốn trở về màn hình desktop Nếu bạn muốn có cách để ngăn không cho người dùng đóng cửasổứng dụng, bạn sẽ thi hành thông điệp WM_CLOSE Bây giờ trở lại với thông... cách sử dụng chỉ thị CLASS trong file tài nguyên, HĐH phải set thành phần này bằng DLGWINDOWEXTRA hInstance: handle của chương trình hIcon : Handle của icon Icon được hiển thị trên ứngdụng bằng cáchsử dụng hàm API LoadIcon hCursor : Handle của cursor Con trỏ chuột được hiển thị trên ứngdụng bằng cáchsử dụng hàm API LoadCursor hbrBackground : màu nền củacửasổ được cài đặt từ lớp cửasổ lpszMenuName . Window Tìm hiểu về cửa sổ ứng dụng Trong bài viết này, chúng ta sẽ xây dựng một chương trình với đầy đủ chức năng của một cửa sổ ứng dụng trên desktop. Tìm hiểu. tiên của một ứng dụng đồ họa 32-bit là tạo một cửa sổ. 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 với các ứng dụng khá