Tóm tắt
Các ứng dụng dựa trên Windows thường hiển thị các hộp thoại nhập dữ liệu để yêu cầu thông tin từ người dùng. Những hộp thoại này có thể chứa một số điều khiển chỉnh sửa và hai nút lệnh (Push), có nhãn OK và hủy bỏ. Ví dụ về hộp thoại nhập dữ liệu là một trong những yêu cầu thông tin cá nhân, chẳng hạn như số an sinh xã hội, địa chỉ, nhận dạng (ID) số, ngày/thời gian, v.v., từ người dùng. Mỗi mục này được nhập vào một điều khiển sửa. Theo mặc định, phím TAB được dùng trong hộp thoại để thay đổi tiêu điểm giữa các điều khiển chỉnh sửa. Tuy nhiên, khi một giao diện người dùng phổ biến, bạn cũng có thể sử dụng phím ENTER (trả về) để di chuyển giữa các điều khiển chỉnh sửa (ví dụ: sau khi người dùng nhập một phần thông tin, hãy nhấn ENTER để di chuyển tiêu điểm đến trường tiếp theo). Có một số cách để cho phép sử dụng phím ENTER để di chuyển giữa các điều khiển chỉnh sửa. Một phương pháp là làm cho việc sử dụng WM_COMMAND và các thư thông báo đi kèm với nó trong hộp thoại để sửa các điều khiển và các nút. Phương pháp khác liên quan đến việc phân vị các điều khiển chỉnh sửa. Thứ ba liên quan đến việc sử dụng ứng dụng Studio và trình hướng dẫn lớp và tạo một hàm thành viên hộp thoại mới.
Thông tin Bổ sung
Phương thức I: (WM_COMMAND)
Phương pháp này dựa trên các hành vi sau đây của hộp thoại (trình quản lý hộp thoại) và việc xử lý tiêu điểm trong Windows. nếu một hộp thoại hoặc một trong các điều khiển của nó hiện có tiêu điểm nhập, sau đó nhấn phím ENTER khiến Windows có thể gửi tin nhắn WM_COMMAND với tham số idItem (wParam) được đặt thành ID của lệnh mặc định. Nếu hộp thoại không có nút lệnh mặc định, thì tham số idItem được đặt là IDOK theo mặc định. Khi một ứng dụng nhận được thông báo WM_COMMAND với idItem được đặt thành ID của lệnh mặc định, tiêu điểm vẫn giữ nguyên điều khiển có tiêu điểm trước phím ENTER đã được nhấn. Gọi GetFocus () vào thời điểm này trả về núm điều khiển có tiêu điểm trước khi nhấn phím ENTER. Ứng dụng có thể kiểm tra xử lý điều khiển này và xác định xem nó thuộc về bất kỳ điều khiển chỉnh sửa nào trong hộp thoại không. Nếu có, thì người dùng đã nhập dữ liệu vào một trong các điều khiển sửa và sau khi thực hiện thao tác đó, nhấn ENTER. Tại thời điểm này, ứng dụng có thể gửi thông báo WM_NEXTDLGCTL đến hộp thoại để di chuyển tiêu điểm đến điều khiển tiếp theo. Tuy nhiên, nếu tiêu điểm đã được với một trong các nút lệnh (hủy bỏ hoặc OK), sau đó GetFocus () trả về núm điều khiển nút, tại đó điểm ai có thể loại bỏ hộp thoại. Mã giả của lô-gic này tương tự như sau trong quy trình hộp thoại của ứng dụng:
case WM_COMMAND: if(wParam=IDOFDEFBUTTON || IDOK) { // User has hit the ENTER key. hwndTest = GetFocus() ; retVal = TesthWnd(hWndTest) ; //Where retVal is a boolean variable that indicates whether //the hwndTest is the handle of one of the edit controls. if(hwndTest) { //Focus is with an edit control, so do not close the dialog. //Move focus to the next control in the dialog. PostMessage(hDlg, WM_NEXTDLGCTL, 0, 0L) ; return TRUE ; } else { //Focus is with the default button, so close the dialog. EndDialog(hDlg, TRUE) ; return FALSE ; } } break ;
Phương pháp II
Phương pháp này liên quan đến việc phân vị/căn đều điều khiển chỉnh sửa trong hộp thoại. Sau khi chỉnh sửa các điều khiển được phân loại hoặc phân cách, tất cả các đầu vào bàn phím sẽ được gửi theo thủ tục phân lớp/cấp độ của điều khiển chỉnh sửa hiện có tiêu điểm đầu vào, bất kể hộp thoại có hay không có nút lệnh mặc định. Ứng dụng có thể làm bẫy phím xuống (hoặc Char), tìm kiếm phím ENTER, và thực hiện việc xử lý phù hợp. Sau đây là một thủ tục phân lớp mẫu trông cho phím ENTER:
//*------------------------------------------------------------------- //| Title: //| SubClassProc //| //| Parameters: //| hWnd - Handle to the message's destination window //| wMessage - Message number of the current message //| wParam - Additional info associated with the message //| lParam - Additional info associated with the message //| //| Purpose: //| This is the window procedure used to subclass the edit control. //*--------------------------------------------------------------------- long FAR PASCAL SubProc(HWND hWnd, WORD wMessage,WORD wParam,LONG lParam) { switch (wMessage) { case WM_GETDLGCODE: return (DLGC_WANTALLKEYS | CallWindowProc(lpOldProc, hWnd, wMessage, wParam, lParam)); case WM_CHAR: //Process this message to avoid message beeps. if ((wParam == VK_RETURN) || (wParam == VK_TAB)) return 0; else return (CallWindowProc(lpOldProc, hWnd, wMessage, wParam, lParam)); case WM_KEYDOWN: if ((wParam == VK_RETURN) || (wParam == VK_TAB)) { PostMessage (ghDlg, WM_NEXTDLGCTL, 0, 0L); return FALSE; } return (CallWindowProc(lpOldProc, hWnd, wMessage, wParam, lParam)); break ; default: break; } /* end switch */
Phương thức 3
Phương pháp này liên quan đến việc sử dụng ứng dụng Studio và ClassWizard và tạo một hàm thành viên hộp thoại mới. Phương pháp này sẽ cho phép người dùng nhấn phím ENTER và nâng cao tiêu điểm đến điều khiển chỉnh sửa tiếp theo. Nếu tiêu điểm hiện đang ở trong điều khiển chỉnh sửa cuối cùng trong hộp thoại, tiêu điểm sẽ chuyển đến điều khiển chỉnh sửa đầu tiên. Trước tiên, hãy sử dụng ứng dụng Studio để thay đổi ID của nút OK của hộp thoại. Hành vi mặc định của ứng dụng Studio là tạo nút OK cho IDOK ID. ID của nút OK sẽ được thay đổi thành một giá trị khác, chẳng hạn như IDC_OK. Ngoài ra, hãy thay đổi các thuộc tính của nút OK để nó không phải là nút bấm chuột mặc định. Tiếp theo, sử dụng ClassWizard để tạo ra một hộp thoại mới thành viên funciton. Đặt tên cho thành viên mới của hàm like OnClickedOK. Hàm này sẽ được gắn với thông điệp BN_CLICKED từ điều khiển IDC_OK. Sau khi hoàn thành xong, hãy viết nội dung của hàm OnClickedOK. Bạn nên đặt mã mà bạn thường được đặt trong hàm OnOK vào hàm OnClickedOK mới, bao gồm hàm OnOK của lớp. Thêm nguyên mẫu sau vào tệp tiêu đề cho hộp thoại:
protected: virtual void OnOK();
Thêm hàm OnOK vào hộp thoại và mã như thể hiện dưới đây:
void CMyDialog::OnOK() { CWnd* pwndCtrl = GetFocus(); CWnd* pwndCtrlNext = pwndCtrl; int ctrl_ID = pwndCtrl->GetDlgCtrlID(); switch (ctrl_ID) { case IDC_EDIT1: pwndCtrlNext = GetDlgItem(IDC_EDIT2); break; case IDC_EDIT2: pwndCtrlNext = GetDlgItem(IDC_EDIT3); break; case IDC_EDIT3: pwndCtrlNext = GetDlgItem(IDC_EDIT4); break; case IDC_EDIT4: pwndCtrlNext = GetDlgItem(IDC_EDIT1); break; case IDOK: CDialog::OnOK(); break; default: break; } pwndCtrlNext->SetFocus(); }