Trang 1 trên tổng số 2 12 Cuối cùngCuối cùng
Từ 1 tới 10 trên tổng số 11 kết quả

Đề tài: Sao tui 0 xử lý phím được ?

  1. #1
    Ngày gia nhập
    08 2006
    Bài viết
    60

    Mặc định Sao tui 0 xử lý phím được ?

    Tui có tạo một SDI. Tui đã bắt sự kiện wm_char, wm_key up, down nhưng hình như nó 0 gọi hàm của tui. Không biết có ai như tui 0 ?

  2. #2
    Ngày gia nhập
    07 2006
    Bài viết
    166

    Cậu bắt ở lớp lớp? Frm? View?Doc?

  3. #3
    Ngày gia nhập
    08 2006
    Bài viết
    60

    ở lớp dialog á!

  4. #4
    Ngày gia nhập
    11 2006
    Bài viết
    75

    Bác thử post cái đoạn source code đó lên xem nào.
    Our dreams are young and we both know they take us where we want to go...

  5. #5
    Ngày gia nhập
    08 2006
    Bài viết
    60

    NÈ! mã của nó đây!
    http://www.box.net/shared/3go0mq1cm5
    Về cái bàn phím thì tui có thử tạo bảng phím nhưng tới hồi xử lý chả được. Khi lấy nguyên bảng trạng thái bàn phím thì làm được. Thiết nghĩ, có lẽ, các phần mềm thường làm bằng cái này


    Ở trường và ở tiệm, chức năng đính kèm file của diễn đàn đều 0 được. "Việc upload file bị thất bại". file rar chỉ cỡ 40kb nhưng 0 sao upload được. Dùng IE ở trường, dùng FF ở tiệm

  6. #6
    Ngày gia nhập
    11 2006
    Bài viết
    75

    Mặc định Sao tui 0 xử lý phím được ?

    Chương trình của bác nó không chịu xử lý phím là đúng rồi, bởi vì khi bác chạy một chương trình bất kỳ, cửa sổ (window) nhận các message là cửa sổ có "input focus" (tại một thời điểm, đối với một ct cụ thể, chỉ có đúng một thằng là có input focus).

    Program này có tất cả là 4 cửa sổ : cửa sổ ứng dụng chính (dialog window), 2 button (Ok và Cancel) và một static text. Static text thì đương nhiên không thể nhận input focus nên một trong 3 thằng còn lại sẽ có. Và bác thử đoán xem là thằng nào ? Chính là Button Ok và đây là nguyên nhân khiến cho các thông điệp bàn phím không tài nào "bò" đến được cửa sổ chính.

    Bác có thể kiểm tra điều này rất dễ bằng cách thêm vào code sau (trong file hoptoai1Dlg.cpp):

    Code:
    WNDPROC OldButtonOkProc;
    LRESULT CALLBACK NewButtonOkProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    	switch (message)
    	{
    		/*case WM_KEYDOWN:
    			::MessageBox (NULL, TEXT ("Where are you, WM_KEYDOWN ?"), TEXT ("Thuongsoo"), MB_OK);
    			::MessageBox (NULL, TEXT ("I'm here, thuongsoo"), TEXT ("WM_KEYDOWN"), MB_OK);
    			break;*/
    		
    		case WM_KEYUP:
    			::MessageBox (NULL, TEXT ("Where are you, WM_KEYUP ?"), TEXT ("Thuongsoo"), MB_OK);
    			::MessageBox (NULL, TEXT ("I'm sorry I can contact you, thuongsoo."), TEXT ("WM_KEYUP"), MB_OK);
    			break;
    
    		default:
    			break;		
    	}
    	return ::CallWindowProc (OldButtonOkProc, hwnd, message, wParam, lParam);
    }
    Sửa lại OnInitDialog:
    Code:
    BOOL CHoptoai1Dlg::OnInitDialog()
    {
    	CDialog::OnInitDialog();
    
    	// Set the icon for this dialog.  The framework does this automatically
    	//  when the application's main window is not a dialog
    	SetIcon(m_hIcon, TRUE);			// Set big icon
    	SetIcon(m_hIcon, FALSE);		// Set small icon
    	
    	// TODO: Add extra initialization here
    	OldButtonOkProc = (WNDPROC) SetWindowLong (HWND (m_ButtonOk.m_hWnd), GWL_WNDPROC, LONG (NewButtonOkProc));
    	return TRUE;  // return TRUE  unless you set the focus to a control
    }
    Bây giờ bác thử ấn các phím xem sẽ thấy "khác" ngay.

    Giải pháp: Dùng accelerator (bảng phím ?).
    Our dreams are young and we both know they take us where we want to go...

  7. #7
    Ngày gia nhập
    08 2006
    Bài viết
    60

    Xin lỗi mọi người vì quá lâu mà 0 vô đây! thiệt tình thì có vô nhưng 0 có máy ở gần nên 0 thể kiểm tra được

    @ilovecplusplus: Tui đang viết MFC nên đâu có xài winproc được ? Tui 0 truy cập được m_buttonOk, tui cũng 0 biết làm sao để truy cập nút này trong lớp CDialog.

  8. #8
    Ngày gia nhập
    11 2006
    Bài viết
    75

    Bác sửa :
    Code:
    OldButtonOkProc = (WNDPROC) SetWindowLong (HWND (m_ButtonOk.m_hWnd), GWL_WNDPROC, LONG (NewButtonOkProc));
    thành :
    Code:
    OldButtonOkProc = (WNDPROC) SetWindowLong (HWND (*GetDlgItem (IDOK)), GWL_WNDPROC, LONG (NewButtonOkProc));
    Thuongsoo viết:
    Tui đang viết MFC nên đâu có xài winproc được ? Tui 0 truy cập được m_buttonOk, tui cũng 0 biết làm sao để truy cập nút này trong lớp CDialog.

    1. MFC thực chất là Win32API Wrapper. Hơn nữa, nếu bác viết ct trên Win thì bất cứ control nào cũng có hwnd và một winproc tương ứng (cho dù ct đó có viết bằng language không phải là C++). Tóm lại, MFC or không thì cũng đều có winproc và đoạn code trên của tui đơn giản là "nối" thêm một ít lệnh vào cái winproc có sẵn của Button Ok sau khi đã biết cái hwnd của nó.

    2. Chắc bác mới dùng MFC ? Nếu vậy, ráng lên mạng tìm tài liệu (codeproject rất tuyệt) về nó. Khuyến nghị nên dùng tài liệu tiếng Anh vì tài liệu tiếng Việt đều chỉ dịch lại thôi mà nhiều khi dịch đến "lởm" (chưa kể nhiều khi còn không thèm ghi tên sách + tác giả của bản gốc tiếng Anh). Một trong số những ebook tương đối tốt về MFC mà bác có thể tìm là Programming Windows with MFC (Author: Jeff Prosise, Publisher: Microsoft Press).

    Gook luck!
    Our dreams are young and we both know they take us where we want to go...

  9. #9
    Ngày gia nhập
    08 2006
    Bài viết
    60

    Cảm ơn ilovecplusplus rất nhiều!
    tui vẫn chưa hiểu về đoạn mã sẽ thêm vô
    Code:
    WNDPROC OldButtonOkProc;
    LRESULT CALLBACK NewButtonOkProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    	switch (message)
    	{
    		/*case WM_KEYDOWN:
    			::MessageBox (NULL, TEXT ("Where are you, WM_KEYDOWN ?"), TEXT ("Thuongsoo"), MB_OK);
    			::MessageBox (NULL, TEXT ("I'm here, thuongsoo"), TEXT ("WM_KEYDOWN"), MB_OK);
    			break;*/
    		
    		case WM_KEYUP:
    			::MessageBox (NULL, TEXT ("Where are you, WM_KEYUP ?"), TEXT ("Thuongsoo"), MB_OK);
    			::MessageBox (NULL, TEXT ("I'm sorry I can contact you, thuongsoo."), TEXT ("WM_KEYUP"), MB_OK);
    			break;
    
    		default:
    			break;		
    	}
    	return ::CallWindowProc (OldButtonOkProc, hwnd, message, wParam, lParam);
    }
    Sửa lại OnInitDialog:

    Code:
    BOOL CHoptoai1Dlg::OnInitDialog()
    {
    	CDialog::OnInitDialog();
    
    	// Set the icon for this dialog.  The framework does this automatically
    	//  when the application's main window is not a dialog
    	SetIcon(m_hIcon, TRUE);			// Set big icon
    	SetIcon(m_hIcon, FALSE);		// Set small icon
    	
    	// TODO: Add extra initialization here
    	OldButtonOkProc = (WNDPROC) SetWindowLong (HWND (*GetDlgItem (IDOK)), GWL_WNDPROC, LONG (NewButtonOkProc));
    	return TRUE;  // return TRUE  unless you set the focus to a control
    }
    Hình như làm vậy thì cái window procedure của button OK vẫn chưa được sửa đúng hôn ? Vì tui thấy đâu có chỗ nào gọi hàm OldButtonOkProc? và hàm NewButtonOkProc?
    Làm sao gán lại hàm xử lý mới lại cho button OK?

  10. #10
    Ngày gia nhập
    11 2006
    Bài viết
    75

    1. Window Procedure mới của button Ok không làm gì cả. Tất cả những gì nó làm gọi lại Window Procedure cũ của button Ok (thông qua câu lệnh CallWindowProc). Việc "nối" mã lệnh chỉ được thực hiện trong trường hợp message là WM_KEYUP (or WM_KEYDOWN).

    2. Hàm SetWindowLong dùng để thay thế một giá trị "LONG" nào đó thuộc sở hữu của một cửa sổ bất kỳ. Giá trị trả về từ SetWindowLong chính là giá trị "LONG" cũ. Trong tình huống trên, tui đã dùng SetWindowLong để thay window procedure của nút Ok nhưng bản chất là thay địa chỉ của Window Procedure (địa chỉ của một hàm trong Win32 App cũng là một số LONG (32 bit)). Vì thế, giá trị trả về từ SetWindowLong sẽ là địa chỉ của Window Procedure cũ. Nhờ vậy, việc "nối" mã lệnh mới có thể thực hiện được.

    3. Prototype của một Window Procedure luôn có dạng:
    Code:
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
    CALLBACK có nghĩa là Window Procedure sẽ không được gọi bởi chương trình mà chính hệ điều hành sẽ gọi Window Procedure khi thích hợp (chẳng hạn khi cần vẽ lại một cửa sổ bị che bởi cửa số khác).

    4. Để gán một user-defined Window Procedure cho một cửa sổ bất kỳ, bác cần biết HWND tương ứng của cửa số đó. Sau đó, dùng hàm SetWindowLong để "connect" cửa sổ đó với địa chỉ của user-defined winproc.

    5. Cuối cùng, bác hãy viết code, dịch thành chương trình để chạy thử. Em đảm bảo bác sẽ "thấy" ngay.
    Our dreams are young and we both know they take us where we want to go...

Quyền hạn của bạn

  • Bạn không thể gửi đề tài mới
  • Bạn không thể gửi bài trả lời
  • Bạn không thể gửi các đính kèm
  • Bạn không thể chỉnh sửa bài viết của bạn