Biểu tượng. Menu. Bảng mô tả các chuỗi ký tự. Bảng mô tả thông tin phiên bản. Một số kiểu dữ liệu mới Kiểu dữ liệu • HWND : window • HMENU : menu • HCURSOR : cursor (brush) mẫu tô: solid, dash, dot, cross, … (pallete) bảng màu (font) Facename, size, style bitmap icon Nét vẽ: solid, dot, dash, size, color Device context (long pointer string) con trỏ đến chuỗi ký tự (word) các tham số đi kèm message. (long) kiểu trả về của hàm xử lý Message. Con trỏ đến kiểu dữ liệu bất kỳ. Chú thích (nguyên không dấu...
Bài 1:Giới thiệu chung Trần Minh Thái Icon Biểu tượng Menu Menu String-table entry Bảng mô tả chuỗi ký tự Version information Bảng mô tả thông tin phiên 11 Stt Một số kiểu liệu Kiểu liệu Chú thích (ngun khơng dấu 16 bit) dùng để định danh đối tượng HANDLE • HWND : window • HMENU : menu • HCURSOR : cursor HBRUSH (brush) mẫu tô: solid, dash, dot, cross, … HPALLETE (pallete) bảng màu HFONT (font) Facename, size, style HBITMAP bitmap HICON icon HPEN Nét vẽ: solid, dot, dash, size, color HINSTANCE Instance HDC Device context 10 LTSTR (long pointer string) trỏ đến chuỗi ký tự 11 LPARAM (word) tham số kèm message 12 LRESULT (long) kiểu trả hàm xử lý Message 13 LPVOID Con trỏ đến kiểu liệu 12 WPARAM Phân tích, tìm hiểu source code project // bt1.cpp : Defines the entry point for the application #include "stdafx.h" #include "resource.h" #define MAX_LOADSTRING 100 // Global Variables: HINSTANCE hInst; // current instance TCHAR szTitle[MAX_LOADSTRING]; // The title bar text Bài giảng: Lập trình C for Win .Trang 19/69 Bài 1:Giới thiệu chung 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 Trần Minh Thái TCHAR szWindowClass[MAX_LOADSTRING];// The title bar text // Foward declarations of functions included in this code module: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM); int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // TODO: Place code here MSG msg; HACCEL hAccelTable; // Initialize global strings LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_BT1, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); // Perform application initialization: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_BT1); // Main message loop: while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return msg.wParam; } // FUNCTION: MyRegisterClass() // PURPOSE: Registers the window class // COMMENTS: // This function and its usage is only necessary if you want this code // to be compatible with Win32 systems prior to the 'RegisterClassEx' // function that was added to Windows 95 It is important to call this function // so that the application will get 'well formed' small icons associated // with it ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; Bài giảng: Lập trình C for Win .Trang 20/69 Bài 1:Giới thiệu chung 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 Trần Minh Thái wcex.lpfnWndProc = (WNDPROC)WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_BT1); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = (LPCSTR)IDC_BT1; wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance,(LPCTSTR)IDI_SMALL); return RegisterClassEx(&wcex); } // FUNCTION: InitInstance(HANDLE, int) // PURPOSE: Saves instance handle and creates main window // COMMENTS: // In this function, we save the instance handle in a global variable and // create and display the main program window BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd; hInst = hInstance; // Store instance handle in our global variable hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } // FUNCTION: WndProc(HWND, unsigned, WORD, LONG) // PURPOSE: Processes messages for the main window // WM_COMMAND - process the application menu // WM_PAINT - Paint the main window // WM_DESTROY - post a quit message and return Bài giảng: Lập trình C for Win .Trang 21/69 Bài 1:Giới thiệu chung 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 Trần Minh Thái LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent,x,y; PAINTSTRUCT ps; HDC hdc; TCHAR szHello[MAX_LOADSTRING]; LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING); switch (message) { case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // Parse the menu selections: switch (wmId) { case IDM_ABOUT: DialogBox(hInst,(LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_LBUTTONDOWN: hdc = GetDC(hWnd); // TODO: Add any drawing code here x=LOWORD(lParam); y=HIWORD(lParam); TextOut(hdc,x,y,(LPCTSTR)szHello, strlen(szHello)); break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // TODO: Add any drawing code here RECT rt; GetClientRect(hWnd, &rt); DrawText(hdc, szHello, strlen(szHello), &rt, DT_CENTER); EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); break; default: Bài giảng: Lập trình C for Win .Trang 22/69 Bài 1:Giới thiệu chung 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 Trần Minh Thái return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } // Mesage handler for about box LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_INITDIALOG: return TRUE; case WM_COMMAND: if (LOWORD(wParam)== IDOK||LOWORD(wParam)== IDCANCEL) { EndDialog(hDlg, LOWORD(wParam));return TRUE; } break; } return FALSE; } Bài giảng: Lập trình C for Win .Trang 23/69 Bài 2:Paint repaint Trần Minh Thái Bài 2: PAINT VÀ REPAINT Phân bố thời lượng: - Số tiết giảng lớp: tiết - Số tiết tự học nhà: tiết - Số tiết cài đặt chương trình nhà: 12 tiết Giới thiệu Windows khơng giữ lại chúng hiển thị vùng làm việc cửa sổ, chương trình ứng dụng phải hiển thị nội dung cửa sổ cần thiết Vẽ lại nội dung cửa sổ khi: Dùng hàm ScrollWindow: Dữ liệu hiển thị thay đổi Æ cập nhật lại Hàm InvalidateRect: Làm bất hợp lệ phần hay toàn vùng làm việc Menu chương trình bật xuống làm che khuất phần cửa sổ Di chuyển chuột, di chuyển icon ¾ Vùng hình chữ nhật hợp lệ bất hợp lệ thông qua lời gọi hàm BOOL InvalidateRect(HWND hwnd, CONST RECT *lpRect, BOOL bErase); với: bErase = TRUE tơ lại nền, FALSE giữ ngun Ỵ Hàm BeginPaint() làm hợp lệ lại vùng bất hợp lệ ¾ Trong cửa sổ chứa PAINTSTRUCT, mục đích tổ hợp lại hay nhiều vùng bất hợp lệ chồng lên typedef struct tagPAINTSTRUCT { HDC hdc; BOOL fErase; RECT rcPaint; BOOL fRestore; BOOL flncUpdate; BYTE rgReserved[32]; }PAINTSTRUCT; Với: fErase = TRUE: xố vùng hình chữ nhật bất hợp lệ FALSE: Khơng xố mà ghi chồng lên rcPaint chứa toạ độ vùng bất hợp lệ Bài giảng: Lập trình C for Win .Trang 24/69 Bài 2:Paint repaint Trần Minh Thái typedef tagRECT { LONG left, top; LONG right, bottom; }RECT; Tổng quan GDI (Graphics Device Interface) Ứng dụng Windows Ngữ cảnh thiết bị GDI Trình điều khiển thiết bị Thiết bị xuất a) Làm việc với ngữ cảnh thiết bị hdc chứa thông tin cần thiết cho việc vẽ lên hình, tự động giao tiếp với phần cứng Có nhiều cách để nhận giải phóng hdc o BeginPaint() EndPaint() : Cặp hàm chủ yếu dùng phần WM_PAINT HDC BeginPaint(HWND hwnd, LPPAINTSTRUCT lpPS); BOOL EndPaint(HWND hWnd, CONST PAINTSTRUCT *lpPaint); o GetDC() ReleaseDC() : Không làm hợp lệ vùng bất hợp lệ HDC GetDC(HWND hwnd); int ReleaseDC(HWND hwnd, HDC hdc); Ỉ trả TRUE giải phóng hdc Việc lấy giải phóng hdc nên tiến hành bên phần xử lý message Ngồi ra, cịn nhận device context tồn hình hàm: hDC = CreateDC( "DISPLAY", NULL, NULL, NULL); Để lấy toạ độ kích thước cửa sổ làm việc ta dùng hàm BOOL GetClientRect(HWND hWnd, LPRECT lpRect); trả giá trị khác không thành công, ngược lại trả Hiển thị số lên hình wsprintf(s, “%d + %d= %d”, a, b, a+b); TextOut(hdc, x, y, s, wsprintf()); b) Chế độ ánh xạ Bài giảng: Lập trình C for Win .Trang 25/69 Bài 2:Paint repaint Trần Minh Thái Vị trí hiển thị ký tự TextOut() tọa độ tương đối cửa sổ (tọa độ logic) Windows ánh xạ đơn vị thành pixel hiển thị ký tự Ở chế độ mặc định tọa độ logic ≈ pixel c) Mơ hình màu RGB (Red – Green – Blue) Byte Byte Byte Byte 0 Blue Green Red Có giá trị từ – 255 (0, 0, 0) đen Ỉ (255, 255, 255) trắng Các hàm API liên quan đến màu sử dụng mơ hình RGB Định nghĩa màu COLORREF RGB (int red, int green, int blue) Ví dụ : Vẽ hình chữ nhật HDC hDC; HPEN hPen, oldHPen; hDC=GetDC(hWnd); hPen=CreatePen(PS_SOLID, 5, RGB(0, 0, 255)); oldHPen=(HPEN)SelectObject(hDC, hPen); Rectangle(hDC, 20, 20, 100, 100); SelectObject(hDC, oldHPen); DeleteObject(hPen); ReleaseDC(hWnd, hDC); d) Tạo lập giải phóng memory device context Memory device context (MDC) device context ảo không gắn với thiết bị xuất cụ thể Muốn kết kết xuất thiết bị vật lý ta phải chép MDC lên device context thật sự(device context có liên kết với thiết bị vật lý) MDC thường dùng device context trung gian để vẽ trước thực xuất thiết bị, nhằm giảm chớp giật thiết bị xuất window hay hình Để tạo MDC tương thích với hDC cụ thể, sử dụng hàm CreateCompatibleDC: HDC hMemDC; hMemDC = CreateCompatibleDC(hDC); Đơn giản hơn, đặt NULL vào vị trí hDC, Windows tạo device context tương thích với hình Bài giảng: Lập trình C for Win .Trang 26/69 Bài 2:Paint repaint Trần Minh Thái Hủy MDC hàm DeleteDC MDC có bề mặt hiển thị thiết bị thật Tuy nhiên, bề mặt hiển thị lúc đầu nhỏ, pixel đơn sắc Khơng thể làm với bề mặt hiển thị gồm bit Do cần làm cho bề mặt hiển thị rộng cách chọn đối tượng bitmap GDI vào MDC: SelectObject(hMemDC, hBitmap); Chỉ chọn đối tượng bitmap vào MDC, chọn vào device context cụ thể Sau chọn đối tượng bitmap cho MDC, dùng MDC device context thật Sau hoàn tất MDC, ảnh đưa device context thật hàm BitBlt: BitBlt(hDC, xDest, yDest, nWidth, nHeight, hMemDC, xSource, ySource); Ví dụ : Chuẩn bị ảnh trước đưa hình, tránh gây chớp hình thơng điệp WM_PAINT case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // Lấy kích thước vùng client cửa sổ hành RECT rect; GetClientRect(hWnd, &rect); // Tạo MDC tương thích với DC cửa sổ HDC hMemDC; hMemDC = CreateCompatibleDC(hdc); // Chọn đối tượng bitmap để mở rộng vùng hiển thị cho MDC HBITMAP bitmap,oBitmap; bitmap = CreateCompatibleBitmap(hdc, rect.right, rect.bottom); oBitmap = (HBITMAP)SelectObject(hMemDC, bitmap); // Vẽ lại MDC FillRect(hMemDC, &rect, HBRUSH (GetBkColor(hMemDC))); // Xuất hình ảnh, text MDC SetPixel(hMemDC, 0, 0, RGB(255,0,0)); MoveToEx(hMemDC, 50, 50, NULL); LineTo(hMemDC, 100, 100); Rectangle(hMemDC, 10, 10, 100, 100); TextOut(hMemDC, 15 ,15, "Testing MDC", 11); Bài giảng: Lập trình C for Win .Trang 27/69 Bài 2:Paint repaint Trần Minh Thái If (!BitBlt(hdc, 0, 0, rect.right, rect.bottom, hMemDC, 0, 0, SRCCOPY)) MessageBox(hWnd, "Failed to transfer bit block", "Error",MB_OK); // Phục hồi lại bitmap cũ cho MDC SelectObject(hMemDC, oBitmap); // Giải phóng MDC, bitmap tạo DeleteDC(hMemDC); DeleteObject(bitmap); EndPaint(hWnd, &ps); break; Một số hàm đồ họa sở a) Nhóm hàm vẽ COLORREF GetPixel(HDC hDC, int nXPos, int nYPos); Lấy giá trị màu vị trí (nXPos, nYPos) hDC, trả -1 điểm nằm vùng hiển thị COLORREF SetPixel(HDC hDC, int nXPos, int nYPos, COLORREF clrRef); Vẽ điểm màu clrRef vị trí (nXPos, nYPos) lên hDC Giá trị trả màu điểm (nXPos, nYPos) -1 điểm nằm vùng hiển thị DWORD MoveToEx(HDC hDC, int x, int y); Di chuyển bút vẽ đến tọa độ (x, y) hDC Giá trị trả tọa độ cũ bút vẽ, x = LOWORD, y = HIWORD BOOL LineTo(HDC hDC, int xEnd, int yEnd); Vẽ đoạn thẳng từ vị trí hành đến vị trí (xEnd, yEnd) hDC Hàm trả TRUE thành công, FALSE thất bại BOOL Polyline(HDC hDC, const POINT FAR *lpPoints, int nPoints); Vẽ đường gấp khúc lên hDC đoạn thẳng liên tiếp, số đỉnh nPoints với tọa độ đỉnh xác định lpPoints Hàm trả TRUE thành công, FALSE thất bại BOOL Polygon(HDC hDC, const POINT FAR *lpPoints, int nPoints); Vẽ đa giác có nPoints đỉnh, tọa độ đỉnh xác định lpPoints Hàm trả TRUE thành công, FALSE thất bại Bài giảng: Lập trình C for Win .Trang 28/69 Bài 2:Paint repaint Trần Minh Thái BOOL Rectangle(HDC hDC, int left, int top, int right, int bottom); Vẽ hình chữ nhật có tọa độ left, top, right, bottom lên hDC HPEN CreatePen(int penStyle, int penWidth, COLORREF penColor); Tạo bút vẽ có kiểu penStyle, độ dày nét vẽ penWidth, màu penColor Hàm trả handle bút vẽ thành công trả NULL thất bại Các giá trị penStyle sau : Giá trị Giải thích PS_SOLID PS_DASH PS_DOT PS_DASHDOT PS_DASHDOTDOT PS_NULL Không hiển thị PS_INSIDEFRAME Các kiểu bút vẽ penStyle Ví dụ : Tạo bút vẽ dùng bút vẽ vẽ số đường sở HDC hDC; POINT PointArr[3]; HPEN hPen, hOldPen; hDC = GetDC(hWnd); PointArr[0].x = 50; PointArr[0].y = 10; PointArr[1].x = 250; PointArr[1].y = 50; PointArr[2].x = 125; PointArr[2].y = 130; Polyline(hDC, PointArr, 3); hPen = (HPEN)CreatePen(PS_SOLID, 1, RGB(0, 0, 255)); hOldPen = SelectObject(hDC, hPen); MoveToEx(hDC, 100, 100, NULL); LineTo(hDC, 200, 150); SelectObject(hDC, hOldPen); DeleteObject(hPen); ReleaseDC(hWnd, hDC); b) Nhóm hàm miền HBRUSH CreateSolidBrush(COLORREF cRef); Tạo mẫu tô đặc với màu cRef Bài giảng: Lập trình C for Win .Trang 29/69 Bài 2:Paint repaint Trần Minh Thái HBRUSH CreateHatchBrush(int bStyle, COLORREF cRef); Tạo mẫu tô dạng lưới kiểu bStyle với màu cRef Các kiểu bStyle : HS_HORIZONTAL HS_BDIAGONAL HS_VERTICAL HS_CROSS HS_FDIAGONAL HS_DIAGCROSS BOOL FloodFill(HDC hDC, int xStart, int yStart, COLORREF cRef); Tơ màu vùng kín, màu đường biên cRef BOOL ExtFloodFill(HDC hDC, int xStart, int yStart, COLORREF cRef, UINT fillStyle); Tơ màu vùng kín, fillStyle định cách tô : o FLOODFILLBORDER : Tô màu vùng có màu đường biên cRef o FLOODFILLSURFACE : Tơ vùng có màu cRef Ví dụ : Sử dụng mẫu có sẵn tạo mẫu tơ để tô HDC hDC; HPEN hPen; HBRUSH hBrush, hOldBrush; hDC = GetDC(hWnd); //Vẽ hai hình chữ nhật với bút vẽ Black hPen = (HPEN)GetStockObject(BLACK_PEN); SelectObject(hDC, hPen); Rectangle(hDC, 10, 10, 50, 50); Rectangle(hDC, 100, 100, 200, 200); // Dùng mẫu tơ có sẵn để tơ hình hBrush = (HBRUSH)GetStockObject(GRAY_BRUSH); SelectObject(hDC, hBrush); FloodFill(hDC, 30, 30, RGB(0,0,255)); // Tạo mẫu tơ để tơ hình thứ hai hBrush = (HBRUSH)CreateHatchBrush(HS_DIAGCROSS, RGB(0, 255, 255)); hOldBrush = (HBRUSH)SelectObject(hDC, hBrush); FloodFill(hDC, 150, 150, RGB(0, 0, 0)); SelectObject(hDC, hOldBrush); //Xóa mẫu tơ giải phóng hDC DeleteObject(hBrush); ReleaseDC(hWnd, hDC); Kết luận WM_PAINT message có độ ưu tiên thấp Khi WM_PAINT hàng chờ có số Window Message khác Windows xử lý WM khác xử lý WM_PAINT Bài giảng: Lập trình C for Win .Trang 30/69 Bài 3:Các thiết bị nhập liệu Trần Minh Thái Bài 3: CÁC THIẾT BỊ NHẬP LIỆU Phân bố thời lượng: - Số tiết giảng lớp: 15 tiết - Số tiết tự học nhà: 15 tiết - Số tiết cài đặt chương trình nhà: 30 tiết Bàn phím a Chương trình điều khiển bàn phím (Keyboard.drv) Windows nạp Keyboard.drv khởi động xử lý phím Sau keyboard.drv chuyển cho USER biến phím nhấn thành message đưa vào hàng đợi (Hàng đợi hệ thống hàng đợi chương trình) b Cửa sổ có focus Khi cửa sổ có focus phát sinh thơng điệp WM_SETFOCUS Ngược lại phát sinh WM_KILLFOCUS c Thông điệp phím MSG msg; while(GetMessage(&msg,NULL,0,0)) { TranslateMessage(&msg); DispatchMessage(&msg); } Thơng điệp Nguyên nhân phát sinh WM_ACTIVATE Thông điệp gởi đến cửa sổ bị kích hoạt cửa sổ khơng bị kích hoạt Nếu cửa sổ hàng đợi nhập liệu, thông điệp truyền cách đồng bộ, thủ tục Windows cửa sổ bị kích hoạt, sau đến thủ tục cửa sổ kích hoạt Nếu cửa sổ khơng nằm hàng đợi thơng điệp gởi cách khơng đồng bộ, cửa sổ kích hoạt WM_APPCOMMAND Thơng báo đến cửa sổ người dùng tạo kiện lệnh ứng dụng, ví dụ người dùng kích vào button sử dụng chuột hay đánh vào kí tự kích hoạt lệnh ứng dụng Bài giảng: Lập trình C for Win .Trang 31/69 Bài 3:Các thiết bị nhập liệu Trần Minh Thái WM_CHAR Thông điệp gởi tới cửa sổ có quan tâm thông điệp WM_KEYDOWN dịch từ hàm TranslateMessage Thơng điệp WM_CHAR có chứa mã kí tự phím nhấn WM_DEADCHAR Thơng điệp gởi tới cửa sổ có quan tâm thơng điệp WM_KEYUP xử lý từ hàm TranslateMessage Thông điệp xác nhận mã kí tự phím dead key nhấn Phím dead key phím kết hợp để tạo kí tự ngơn ngữ khơng có tiếng anh (xuất bàn phím hỗ trợ ngơn ngữ khác tiếng Anh) WM_GETHOTKEY Ứng dụng gởi thông điệp để xác định phím nóng liên quan đến cửa sổ Để gởi thơng điệp dùng hàm SendMessage WM_HOTKEY Thông điệp gởi người dùng nhấn phím nóng đăng kí RegisterHotKey WM_KEYDOWN Thông điệp gởi cho cửa sổ nhận quan tâm người dùng nhấn phím bàn phím Phím khơng phải phím hệ thống (Phím khơng có nhấn phím Alt) WM_KEYUP Thơng điệp gởi cho cửa sổ nhận quan tâm người dùng nhả phím nhấn trước đó.Phím khơng phải phím hệ thống (Phím khơng có nhấn phím Alt) WM_KILLFOCUS Thơng điệp gởi tới cửa sổ nhận quan tâm trước quyền WM_SETFOCUS Thông điệp gởi tới cửa sổ sau cửa sổ nhận quan tâm Windows WM_SETHOTKEY Ứng dụng gởi thông điệp đến cửa sổ liên quan đến phím nóng, người dùng nhấn phím nóng cửa sổ tương ứng liên quan tới phím nóng kích hoạt WM_SYSCHAR Thông điệp gởi tới cửa sổ nhận quan tâm hàm TranslateMesage xử lý xong thơng điệp WM_SYSKEYDOWN Bài giảng: Lập trình C for Win .Trang 32/69 Bài 3:Các thiết bị nhập liệu Trần Minh Thái Thông điệp WM_SYSCHAR chứa mã cửa phím hệ thống Phím hệ thống phím có chứa phím Alt tổ hợp phím khác WM_SYSDEADCHAR Thơng điệp gởi tới cửa sổ nhận quan tâm thông điệp WM_SYSKEYDOWN biên dịch hàm TranslateMessage Thơng điệp xác nhận mã kí tự phím hệ thống deadkey nhấn WM_SYSKEYDOWN Thơng điệp gởi tới cửa sổ nhận quan tâm người dùng nhấn phím hệ thống d Ví dụ 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 #define BUFSIZE 65535 #define SHIFTED 0x8000 LONG APIENTRY MainWndProc(HWND hwndMain, UINT uMsg, WPARAM wParam, LPARAM lParam) { HDC hdc; // handle to device context TEXTMETRIC tm; // structure for text metrics static DWORD dwCharX; // average width of characters static DWORD dwCharY; // height of characters static DWORD dwClientX; // width of client area static DWORD dwClientY; // height of client area static DWORD dwLineLen; // line length static DWORD dwLines; // text lines in client area static int nCaretPosX = 0; // horizontal position of caret static int nCaretPosY = 0; // vertical position of caret static int nCharWidth = 0; // width of a character static int cch = 0; // characters in buffer static int nCurChar = 0; // index of current character static PTCHAR pchInputBuf; // input buffer int i, j; // loop counters int cCR = 0; // count of carriage returns int nCRIndex = 0; // index of last carriage return int nVirtKey; // virtual-key code TCHAR szBuf[128]; // temporary buffer TCHAR ch; // current character PAINTSTRUCT ps; // required by BeginPaint RECT rc; // output rectangle for DrawText SIZE sz; // string dimensions COLORREF crPrevText; // previous text color Bài giảng: Lập trình C for Win .Trang 33/69 Bài 3:Các thiết bị nhập liệu 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 Trần Minh Thái COLORREF crPrevBk; // previous background color switch (uMsg) { case WM_CREATE: // Get the metrics of the current font hdc = GetDC(hwndMain); GetTextMetrics(hdc, &tm); ReleaseDC(hwndMain, hdc); // Save the average character width and height dwCharX = tm.tmAveCharWidth; dwCharY = tm.tmHeight; // Allocate a buffer to store keyboard input pchInputBuf = (LPTSTR) GlobalAlloc(GPTR, BUFSIZE * sizeof(TCHAR)); return 0; case WM_SIZE: // Save the new width and height of the client area dwClientX = LOWORD(lParam); dwClientY = HIWORD(lParam); // Calculate the maximum width of a line and the // maximum number of lines in the client area dwLineLen = dwClientX - dwCharX; dwLines = dwClientY / dwCharY; break; case WM_SETFOCUS: // Create, position, and display the caret when the // window receives the keyboard focus CreateCaret(hwndMain, (HBITMAP) 1, 0, dwCharY); SetCaretPos(nCaretPosX, nCaretPosY * dwCharY); ShowCaret(hwndMain); break; case WM_KILLFOCUS: // Hide and destroy the caret when the window loses the // keyboard focus HideCaret(hwndMain); DestroyCaret(); break; case WM_CHAR: switch (wParam) { case 0x08: // backspace case 0x0A: // linefeed case 0x1B: // escape MessageBeep((UINT) -1); return 0; case 0x09: // tab Bài giảng: Lập trình C for Win .Trang 34/69 Bài 3:Các thiết bị nhập liệu 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 Trần Minh Thái // Convert tabs to four consecutive spaces for (i = 0; i < 4; i++) SendMessage(hwndMain, WM_CHAR, 0x20, 0); return 0; case 0x0D: // carriage return // Record the carriage return and position the // caret at the beginning of the new line pchInputBuf[cch++] = 0x0D; nCaretPosX = 0; nCaretPosY += 1; break; default: // displayable character ch = (TCHAR) wParam; HideCaret(hwndMain); // Retrieve the character's width and output // the character hdc = GetDC(hwndMain); GetCharWidth32(hdc, (UINT) wParam, (UINT) wParam, &nCharWidth); TextOut(hdc, nCaretPosX, nCaretPosY * dwCharY, &ch, 1); ReleaseDC(hwndMain, hdc); // Store the character in the buffer pchInputBuf[cch++] = ch; // Calculate the new horizontal position of the // caret If the position exceeds the maximum, // insert a carriage return and move the caret // to the beginning of the next line nCaretPosX += nCharWidth; if ((DWORD) nCaretPosX > dwLineLen) { nCaretPosX = 0; pchInputBuf[cch++] = 0x0D; ++nCaretPosY; } nCurChar = cch; ShowCaret(hwndMain); break; } SetCaretPos(nCaretPosX, nCaretPosY * dwCharY); break; case WM_KEYDOWN: switch (wParam) { case VK_LEFT: // LEFT ARROW // The caret can move only to the beginning of Bài giảng: Lập trình C for Win .Trang 35/69 Bài 3:Các thiết bị nhập liệu 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 Trần Minh Thái // the current line if (nCaretPosX > 0) { HideCaret(hwndMain); // Retrieve the character to the left of // the caret, calculate the character's // width, then subtract the width from the // current horizontal position of the caret // to obtain the new position ch = pchInputBuf[ nCurChar]; hdc = GetDC(hwndMain); GetCharWidth32(hdc, ch, ch, &nCharWidth); ReleaseDC(hwndMain, hdc); nCaretPosX = max(nCaretPosX - nCharWidth, 0); ShowCaret(hwndMain); } break; case VK_RIGHT: // RIGHT ARROW // Caret moves to the right or, when a carriage // return is encountered, to the beginning of // the next line if (nCurChar < cch) { HideCaret(hwndMain); // Retrieve the character to the right of // the caret If it's a carriage return, // position the caret at the beginning of // the next line ch = pchInputBuf[nCurChar]; if (ch == 0x0D) { nCaretPosX = 0; nCaretPosY++; } // If the character isn't a carriage // return, check to see whether the SHIFT // key is down If it is, invert the text // colors and output the character else { hdc = GetDC(hwndMain); nVirtKey = GetKeyState(VK_SHIFT); if (nVirtKey & SHIFTED) { crPrevText = SetTextColor(hdc, RGB(255, 255, 255)); Bài giảng: Lập trình C for Win .Trang 36/69 ...Bài 1:Giới thiệu chung 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 Trần Minh Thái TCHAR szWindowClass[MAX_LOADSTRING];//... 101 1 02 103 104 105 106 107 108 109 110 111 1 12 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 1 32 133 134 135 136 137 138 139 140 141 1 42 143 144 Trần Minh Thái LRESULT... tới cửa sổ nhận quan tâm người dùng nhấn phím hệ thống d Ví dụ 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 #define BUFSIZE 65535 #define SHIFTED 0x8000 LONG APIENTRY MainWndProc(HWND