Bài giảng Lập trình hệ thống - Trần Nhật Hóa
Môi trường Windows
Giao tiếp người dùng đồ họa
Đa nhiệm.
Chia sẻ thủ tục mà Windows cung cấp.
Sử dụng thư viện liên kết động (DLL).
Có tính tương thích cao.
Xây dựng dựa trên kiến trúc mở.
he Focus? Các ứng dụng, các cửa sổ con của ứng dụng giao tiếp chung với một bàn phím. Vòng lặp thông điệp chịu trách nhiệm gửi thông điệp đến thủ tục cửa sổ bằng hàm DispatchMessage tương ứng với cửa sổ. Trong một thời điểm chỉ có một cửa sổ có focus, và chỉ có thủ tục cửa sổ của cửa sổ này có khả năng nhận được thông điệp. Một hwnd cho phép xác định cửa sổ có được điều khiển Who's Got the Focus? (con.) Một cửa sổ active luôn là cửa sổ nằm trên cùng, các điểu khiển trong cửa sổ có được điều khiển đều có dấu hiệu để nhận biết. Các thông điệp WM_SETFOCUS và WM_KILLFOCUS cho biết thời điểm mà cửa sổ có được điều khiển hoặc mất điều khiển. Queues and Synchronization Khi người dùng nhấn và nhả phím trên bàn phím, Windows và các trình điều khiển thiết bị sẽ diễn dịch scan code của phần cứng sang hình thức thông điệp. Chúng được lưu trữ vào hàng đợi hệ thống. Windows chỉ gửi các thông điệp đến hàng đợi ứng dụng khi ứng dụng đã xử lý xong thông điệp chuột hay bàn phím trước đó. Queues… (con.) Hàng đợi của hệ thống là hàng đợi duy nhất do Windows quản lý cho việc tiền xử lý thông tin nhập vào từ bàn phím và chuột. Lý do: Đảm bảo quá trình đồng bộ hóa đối với mọi chương trình. Nếu như chương trình của chúng ta chưa kịp xử lý xong Keystrokes and Characters Các thông điệp bàn phím, phân biệt: Thông điệp phím gõ (Keystrokes message) Thông điệp ký tự (Characters message) Keystroke Messages Khi ta nhấn phím, Windows sẽ các đặt thông điệp vào hàng đợi của ứng dụng. Các thông điệp gồm có: Các thông điệp này lần lượt sẽ được gửi đến WndProc. System and Nonsystem Keystrokes Các thông điệp này thường được phát sinh đối với các tổ hợp phím kết hợp với phím Alt. (VD: Alt-Tab, Alt-Esc). Tuy nhiên trừ khi muốn thực hiện những tác vụ đặc biệt, chúng ta mới bẫy các thông điệp này. Thông thường, chúng thường được chuyển đến cho DefWindowProc xử lý). Kết quả là ta sẽ nhận được các thông điệp hữu ích hơn. (VD: WM_CLOSE, với tổ hợp Alt-F4) System and Nonsystem Keystrokes Đoạn mã sau làm cho các phím chức năng Alt-key của Windows tê liệt. Đối với thông điệp phím gõ hệ thống, ta nên gọi hàm DefWindowsProc chứ không nên trả về giá trị 0. System and Nonsystem Keystrokes... Các thông điệp WM_KEYDOWN và WM_KEYUP thường được sinh ra bởi các phím thông thường không kết hợp với Alt. Với các thông điệp phím gõ, tham số wParam sẽ chứa mã ảo của phím (virtual key code). Tham số lParam chứa các thông tin về trạng thái của phím nhấn. Virtual key code Được chứa trong tham số wParam đối với các thông điệp WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN và WM_SYSKEYUP. Mã này là các hằng cho biết giá trị của phím được nhấn hay nhả. Mã của phím thật là mã được phát sinh từ phần cứng vật lý của bàn phím (gọi là mã quét). Tập giá trị phím tổng quát được định nghĩa theo kiểu độc lập với thiết bị gọi là các mã phím ảo. Virtual key code (con.) Các giá trị phím ảo được định nghĩa với tiếp đầu ngữ VK_xxx. Ba trong bốn phím ảo đầu tiên dành cho chuột. Ta sẽ không nhận được mã ảo của phím chuột trong các thông điệp do bàn phím gửi đến. Virtual key code (con.) Mã phím ảo bằng với mã ASCII của ký tự mà phím thể hiện. Chương trình Windows hầu như không dùng đến thông điệp phím gõ đối với các mã ảo này mà dựa vào thông điệp ký tự gõ WM_CHAR. The lParam Information Trong bốn thông điệp phím gõ (WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, WM_SYSKEYUP): wParam mang mã phím ảo. lParam chứa thông tin của phím được gõ, gồm có: Repeat Count Chiếm 16 bit, thể hiện số lần phím được nhấn. Thông thường trường này luôn có giá trị là 1. Nếu như một phím được nhấn, Windows gửi một thông điệp WM_KEYDOWN hoặc WM_SYSKEYDOWN kèm theo giá trị của trường này bằng số lần lặp phím. Với WM_KEYUP hoặc WM_SYSKEYUP giá trị này luôn bằng 1. OEM Scan Code Là mã được sinh ra do phần cứng của bàn phím. Thông thường ta không cần quan tâm đến mã này. Extended Key Flag Chiếm độ dài 1 bit trong lParam. Cờ này có giá trị là 1 nếu như phím được nhấn là một trong những phím mở rộng. Được đặt là 1 với phím Alt và Ctrl bên phải bàn phím, các phím di chuyển con trỏ (bao gồm cả phím Insert và Delete) phím (/) và phím Enter trong vùng phím số và phím Num Lock. Thông thường Windows bỏ qua cờ này. Context Code Được đặt là 1 đối với các thông điệp WM_SYSKEYUP và WM_SYSKEYDOWN (phím Alt được nhấn kèm) Được đặt bằng 0 đối với các thông điệp WM_KEYUP và WM_KEYDOWN, trừ hai trường hợp: Nếu cửa sổ active bị thu nhỏ, tất cả phím nhấn sinh ra thông điệp WM_SYSKEYUP và WM_SYSKEYDOWN. Nếu như phím Alt không được nhấn trường Context Code được đặt là 0. (Windows sử dụng các thông điệp WM_SYSKEYUP và WM_SYSKEYDOWN để cho cửa sổ thu nhỏ này không xử lý phím nhấn). Một số bàn phím nước ngoài, một số kí tự được sinh ra bởi việc nhấn kèm các phím Shift, Ctrl, hoặc Alt. Trong trường hợp này, trường Context Code được đặt bằng 1 nhưng các thông điệp không phải là các thông điệp system keystroke. Previous Key State Trường này cho biết trạng thái của phím trước đó khi phát sinh ra thông điệp. Có giá trị bằng 0 nếu như phím trước đó đang ở trong trạng thái up, bằng 1 nếu như phím ở trạng thái down. Với WM_KEYUP và WM_SYSKEYUP trường này có giá trị là 1. Với WM_KEYDOWN, WM_SYSKEYDOWN nó có giá trị bằng 0 hoặc 1. (1 với trường hợp lặp phím) Transition State Cho biết trạng thái dịch chuyển của phím. Giá trị 0 nếu phím đang được nhấn. Bằng 1 nếu phím đang được nhả. Với WM_KEYDOWN và WM_SYSKEYDOWN trường này luôn có giá trị 0. Với WM_KEYUP hoặc WM_SYSKEYUP trường này luôn có giá trị 1. Shift States Khi xử lý thông điệp phím gõ đôi khi ta cũng cần phải biết một số trạng thái của các phím như Shift, Ctrl và Alt có được nhấn kèm hay không, hoặc Caps Lock, Num Lock, Scroll Lock đang được tắt hay mở. Ta có thể biết được những thông tin này bằng lời gọi hàm GetKeyState. VD: iState = GetKeyState(VK_SHIFT); Thông điệp phím gõ Thông điệp ký tự Một số hàm điều khiển con nháy CreateCaret : Tạo con nháy cho một cửa sổ. SetCaretPos : Đặt vị trí con nháy trong cửa sổ. ShowCaret : Hiển thị con nháy. HideCaret : Ẩn con nháy. DestroyCaret : Hủy con nháy. Ví dụ (Typer) Chương trình Typer. Chương 5. CHUỘT Một số định nghĩa Các thao tác đối với chuột: Clicking Double-clicking Dragging wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ; Một số hàm cơ bản Xác định sự hiển diện của chuột: fMouse = GetSystemMetrics (SM_MOUSEPRESENT) ; Xác định số nút nhấn: cButtons = GetSystemMetrics (SM_CMOUSEBUTTONS) ; Các thông điệp chuột vùng client Bao gồm: Xác định tọa độ của chuột: x = LOWORD (lParam) ; y = HIWORD (lParam) ; Ví dụ (Connect) Ví dụ (tt) Kết quả Các thông điệp chuột vùng nonclient Các thông điệp bao gồm: Thông thường ta đưa các thông điệp này cho DefWindowProc xử lý. Thông điệp Hit-Test Thông điệp WM_NCHITTEST đi trước tất cả các thông điệp vùng client và nonclient. Các ứng dụng thường đưa thông điệp này cho DefWindowProc xử lý, giá trị trả khi xử lý thông điệp WM_NCHITTEST sẽ là thông số wParam trong các thông điệp chuột. HTCLIENT Vùng client HTNOWHERE Không thuộc cửa sổ nào HTTRANSPARENT A window covered by another window HTERROR Tạo ra tiếng beep Thông điệp Hit-Test (tt) Nếu giá trị trả về là HTCLIENT, Windows sẽ chuyển tọa độ màn hình thành tọa độ vùng client và tạo ra một thông điệp chuột vùng client. Ta có thể cấm chức năng chuột bằng cách bẫy thông điệp: case WM_NCHITTEST: return (LRESULT) HTNOWHERE ; Thông điệp tạo ra thông điệp Windows sử dụng WM_NCHITTEST để tạo ra các thông điệp chuột khác. Ví dụ: Double-click vào system menu icon -> WM_NCHITTEST. Thông điệp WM_NCLBUTTONDBLCLK được đặt vào hàng đợi với wParam bằng HTSYSMENU. Thông điệp WM_SYSCOMMAND với wParam bằng SC_CLOSE. DefWindowProc gửi thông điệp WM_CLOSE cho thủ tục cửa sổ. Chương 5. BỘ ĐỊNH THỜI (TIMER) Những khái niệm cơ bản Tác vụ mang tính định kỳ. Được cài đặt trong các ứng dụng để thực hiện các nhiệm vụ: Đa nhiệm. Cập nhật trạng thái. Cơ chế tự động. Thiết kế các ứng dụng hoạt hình... Một số lưu ý Thông điệp WM_TIMER được xử lý tuần tự và bình đẳng như tất cả các thông điệp khác. Windows sẽ không đặt vào hàng đợi hàng loạt thông điệp WM_TIMER. Ta không thể biết được có bao nhiêu thông điệp WM_TIMER bị bỏ qua. Phương pháp sử dụng TIMER Phương pháp 1: Yêu cầu Windows gửi thông điệp WM_TIMER gửi đến hàm WndProc bằng hàm: SetTimer (hwnd, 1, uiMsecInterval, NULL) ; Các tham số: Timer ID, khác 0. Số nguyên 32-bit không dấu xác định mili giây. (60,000 -> 1 phút). Hủy bỏ bộ định thời Timer bằng lời gọi: KillTimer (hwnd, 1) ; Tham số thứ 2 là Timer ID. Phương pháp 1 (tt) Khi nhận được WM_TIMER, wParam sẽ xác định ID của Timer. Cách sử dụng. Định nghĩa ID cho mỗi Timer: #define TIMER_SEC 1 #define TIMER_MIN 2 Tạo ra các Timer: SetTimer (hwnd, TIMER_SEC, 1000, NULL) ; SetTimer (hwnd, TIMER_MIN, 60000, NULL) ; Phương pháp 1 (tt) Cấu trúc xử lý: Ví dụ (Beeper1) case WM_CREATE: SetTimer (hwnd, ID_TIMER, 1000*2, NULL) ; SetTimer (hwnd, ID_TIMER2, 1500*2, NULL) ; return 0 ; case WM_TIMER : MessageBeep (-1) ; fFlipFlop = !fFlipFlop ; InvalidateRect (hwnd, NULL, FALSE) ; return 0 ; case WM_PAINT : hdc = BeginPaint (hwnd, &ps) ; GetClientRect (hwnd, &rc) ; hBrush = CreateSolidBrush (fFlipFlop ? RGB(255,0,0) : RGB(0,0,255)) ; FillRect (hdc, &rc, hBrush) ; EndPaint (hwnd, &ps) ; DeleteObject (hBrush) ; return 0 ; case WM_DESTROY : KillTimer (hwnd, ID_TIMER) ; PostQuitMessage (0) ; return 0 ; Phương pháp 2 Gọi trực tiếp một hàm xây dựng cho việc xử lý định thời (gọi là call-back). Xây dựng hàm: Thiết lập bộ định thời: SetTimer (hwnd, iTimerID, iMsecInterval, TimerProc) ; Ví dụ (Beeper2) VOID CALLBACK TimerProc (HWND hwnd, UINT message, UINT iTimerID, DWORD dwTime) { static BOOL fFlipFlop = FALSE ; HBRUSH hBrush ; HDC hdc ; RECT rc ; MessageBeep (-1) ; fFlipFlop = !fFlipFlop ; GetClientRect (hwnd, &rc) ; hdc = GetDC (hwnd) ; hBrush = CreateSolidBrush (fFlipFlop ? RGB(255,0,0) : RGB(0,0,255)) ; FillRect (hdc, &rc, hBrush) ; ReleaseDC (hwnd, hdc) ; DeleteObject (hBrush) ; } Phương pháp 3 Thiết lập bằng lời gọi hàm: iTimerID = SetTimer (NULL, 0, wMsecInterval, TimerProc) ; Hủy bỏ: KillTimer (NULL, iTimerID) ;
File đính kèm:
- Bài giảng Lập trình hệ thống - Trần Nhật Hóa.ppt