2013-02-02 25 views
6

Tôi đang cố gắng tạo một lớp nhỏ hiển thị cửa sổ bảng điều khiển trong cửa sổ chính. Bây giờ, vì các instane khác nhau có các biến riêng tư khác nhau (như mảng tin nhắn hoặc cửa sổ cha), tôi cần sử dụng phương thức không tĩnh làm gọi lại cho các sự kiện Windows.
Tôi đã nghĩ về các cách, ở đây tôi chuyển thể hiện lớp thực tế đến hàm gọi lại tĩnh và sau đó gọi phương thức thích hợp trên đó, nhưng trong winAPI, mọi thứ được thực hiện bằng cách sử dụng TranslateMessageDispatchMessage. sở hữu.
Tôi tìm thấy một số mã ở đây: Class method as winAPI callback, nhưng tôi không hiểu nó, và tôi nghĩ rằng nó không phải là chính xác những gì tôi cần. Nếu có, xin vui lòng cho tôi giải thích thêm về mã được cung cấp.
Lỗi tôi nhận được:Sử dụng phương thức đối tượng như gọi lại WinApi WndProc

lỗi: đối số kiểu 'LRESULT (WindowConsole::) (HWND__ , UINT, WPARAM, LPARAM)' không phù hợp 'LRESULT (*) (HWND__, UINT, WPARAM, LPARAM) '

Tôi không biết ngôi sao đó trong ngoặc có nghĩa là gì, nhưng đây là những gì không khớp.
Và mã:

class WindowConsole { 
    char messages[255][255]; 
    HWND mainWindow; 
    public: 
    int width; 
    int height; 
    inline HWND create(HWND parent); 
    inline bool update(); 
    inline LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); 
}; 

HWND WindowConsole::create(HWND parent) { 
    HINSTANCE inst = GetModuleHandle (0); 
    WNDCLASSEX wincl; 

    /* The Window structure */ 
    wincl.hInstance = inst; 
    wincl.lpszClassName = "ConsoleClass"; 
    wincl.lpfnWndProc = this->WndProc;  /* This function is called by windows */ 
    /* more WNDCLASSEX crap...*/ 

    mainWindow = CreateWindow (
      /*PARAMS*/ 
    ); 
    ShowWindow(mainWindow,1); 
    return mainWindow; 

} 
bool WindowConsole::update() { 
    return true; 
} 
LRESULT CALLBACK WindowConsole::WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { 
    switch (message)     /* handle the messages */ 
    { 
      /*EVENT crap*/ 
    } 

    return 0; 
} 
+0

999999999 dupes – Puppy

+0

Vâng, không ai trong số họ đã giúp tôi. Tôi đã tìm kiếm một thời gian dài và tìm thấy khá nhiều chủ đề về vấn đề này, nhưng tôi chỉ đơn giản là không hiểu. –

+0

có xem xét câu trả lời của user16100 ... và liên kết đến bài viết msdn ... – Incubbus

Trả lời

9

Trường hợp phổ biến là một cái gì đó đơn đặt hàng này:

#include <windows.h> 

class BaseWindow { 

    static LRESULT CALLBACK internal_WndProc(HWND hWnd, int msg, WORD wParam, LONG lParam) { 
     BaseWindow *c = (BaseWindow *)GetWindowLong(hWnd,GWLP_USERDATA); 

     if (c == NULL) 
      return DefWindowProc(hWnd, msg, wParam, lParam); 

     return c->WindowProc(hWnd, msg, wParam, lParam); 
    } 

public: 
    virtual int WindowProc(HWND hWnd, int msg, WPARAM wParam, LPARAM lParam) = 0; 

    BaseWindow(HINSTANCE instance) { 
     WNDCLASS window_class = {0}; 
     HWND window; 
     HMENU my_menu; 

     window_class.lpfnWndProc = (WNDPROC)internal_WndProc; 
     /* fill in window_class here */ 
     RegisterClass(&window_class); 

     window = CreateWindow(
      "My Application", "Stupidity", 
      WS_OVERLAPPEDWINDOW, 
      CW_USEDEFAULT, CW_USEDEFAULT, 
      CW_USEDEFAULT, CW_USEDEFAULT, 
      NULL, my_menu, instance, NULL); 

     // save the address of the class as the Window's USERDATA. 
     SetWindowLong(window, GWLP_USERDATA, (long)this); 
    } 
}; 

Với điều này, bạn lấy được một lớp từ BaseWindow. Trong lớp dẫn xuất của bạn, bạn cung cấp một "WindowProc" ghi đè (ảo ảo) trong BaseWindow. Bí quyết ở đây khá đơn giản: vì bạn không thể chuyển trực tiếp tham số, bạn lưu trữ địa chỉ của lớp trong cửa sổ GWLP_USERDATA, sau đó trong cửa sổ proc (cố gắng) truy xuất và sử dụng nó để gọi lớp dẫn xuất 'ảo cửa sổ proc.

Như một sang một bên, lưu ý rằng đây là một phác thảo, không phải là một công việc đã hoàn thành (để nói). Mặc dù nó phải biên dịch như là, kết quả sẽ không thực sự hoạt động trừ khi bạn điền vào một số lượng hợp lý các phần không có ở đây (ví dụ, các trường khác của cấu trúc WNDCLASS chỉ là một trong những rõ ràng nhất).

+0

Cảm ơn bạn, với ví dụ của bạn, tôi đã tạo ra một thứ gì đó, ít nhất, biên dịch mà không có lỗi. Bây giờ có câu hỏi obvions: nơi nào tôi đặt vòng lặp để nắm bắt các sự kiện cửa sổ và gửi chúng? Tôi có phải làm cho chương trình của mình không đồng bộ (thêm một chuỗi khác không?)? –

+0

@ TomášZato: Vòng lặp thông điệp (về cơ bản) luôn luôn trong WinMain, thường sẽ chỉ tạo ra một thể hiện của cửa sổ, sau đó đi vào một vòng lặp tin nhắn. Không, bạn thường không muốn chạy nó trong một chủ đề riêng biệt. –

+0

Vâng, nhưng lớp học của tôi có thể tạo nhiều cửa sổ vì tôi có thể tạo nhiều phiên bản. Vì vậy, tôi nên giữ các trình xử lý cửa sổ (HWND) trong một số biến toàn cầu, để gửi các sự kiện cho mỗi biến trong WinMain()? –

4

Câu hỏi khác mà bạn có liên quan đến chỉ áp dụng cho một phần.

Phương pháp WindowProc cần phải tĩnh. Sau đó, ngay sau khi cuộc gọi đến CreateWindowEx, hãy gọi SetWindowLongPtr với GWLP_USERDATA làm tham số thứ hai và số này làm số thứ ba. Điều đó liên kết HWND với cá thể lớp. Sau đó, trong phương thức WindowProc tĩnh gọi GetWindowLongPtr (một lần nữa với GWLP_USERDATA) để lấy cá thể WindowConsole nhận được sự kiện UI.

Đó là tất cả các giải thích chi tiết ở đây:

http://msdn.microsoft.com/en-us/library/windows/desktop/ff381400(v=vs.85).aspx

1

Tôi sử dụng một giải pháp đơn giản. Hàm winproc là một hàm mẫu. Bộ nhận tin nhắn nằm trong setwindowptr.

Nếu người nhận có chức năng với tên tin nhắn, ví dụ, onpaint, thì wm_paint được bao gồm trong công tắc tin nhắn.

http://www.thradams.com/codeblog/wndproc.htm

Các vấn đề liên quan