使用对象方法作为WinApi WndProc回调 [英] Use object method as WinApi WndProc callback

查看:143
本文介绍了使用对象方法作为WinApi WndProc回调的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图做一个小类,在父窗口中显示控制台窗口。 (你可以想象聊天或调试信息显示在那里)

现在,由于不同的instanes有不同的私有变量(如消息数组或父窗口),我需要使用非静态方法作为回调

我想到了一些方法,其中我将实际的类实例传递给静态回调函数,然后调用适当的方法,但在winAPI中,一切都是使用 TranslateMessage DispatchMessage 给我没有机会使用我自己的参数。

我在这里找到了一些代码: 类方法作为winAPI回调,但我不明白它,我认为不是我需要的。如果是,请给我进一步解释提供的代码。

错误,我得到:


错误:类型LRESULT( WindowConsole :: )的参数(HWND __ *,UINT,WPARAM,LPARAM)'不匹配'LRESULT c> * )(HWND __ *,UINT,
WPARAM,LPARAM)'


不知道括号中的星号是什么意思,但这是什么不匹配。

和代码:

  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父){
HINSTANCE inst = GetModuleHandle(0);
WNDCLASSEX wincl;

/ *窗口结构* /
wincl.hInstance = inst;
wincl.lpszClassName =ConsoleClass;
wincl.lpfnWndProc = this-> WndProc; / *此函数由windows调用* /
/ *更多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)/ *处理消息* /
{
/ * EVENT crap * /
}

return 0;
}


解决方案

订单:

  #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实例){
WNDCLASS window_class = {0};
HWND window;
HMENU my_menu;

window_class.lpfnWndProc =(WNDPROC)internal_WndProc;
/ *填写window_class这里* /
RegisterClass(& window_class);

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

//将类的地址保存为Window的USERDATA。
SetWindowLong(window,GWLP_USERDATA,(long)this);
}
};

这样,就可以从BaseWindow派生一个类。在你的派生类中,你提供一个WindowProc,覆盖BaseWindow中的(纯虚拟)。这里的技巧是相当简单的:因为你不能直接传递一个参数,你存储的类的地址在窗口的GWLP_USERDATA,然后在窗口proc(尝试)检索,并使用它来调用派生类'虚拟窗口proc。



注意,这是一个草图,不是一个完成的工作(可以这么说)。虽然它应该按原样编译,但是结果将不会实际工作,除非您填入不在这里的相当数量的片段(例如,WNDCLASS结构的其他字段只是最明显的一个)。


I'm trying to make a little class that displays console window in parent window. (you can imagine chat or debug info being displayed there)
Now, since diferent instanes do have different private variables (such as message array or parent window), I need to use non-static method as callback for the Windows events.
I have thought of ways, where I'd pass the actual class instance to static callback function and then called the proper method on it, but in winAPI, everything is done using TranslateMessage and DispatchMessage giving me no chance to use arguments of my own.
I found some code here: Class method as winAPI callback, but I don't understand it, and I think it is not exactly what I need. If it is, then please give me further explanation of code provided.
Error I get:

error: argument of type 'LRESULT (WindowConsole::)(HWND__*, UINT, WPARAM, LPARAM)' does not match 'LRESULT (*)(HWND__*, UINT, WPARAM, LPARAM)'

I don't know what that star in brackets means, but this is what does not match.
And the code:

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;
}

解决方案

The usual is something on this order:

#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);
    }
};

With this, you derive a class from BaseWindow. In your derived class, you provide a "WindowProc" that overrides the (pure virtual) one in BaseWindow. The trick here is fairly simple: since you can't pass a parameter directly, you store the address of the class in the window's GWLP_USERDATA, then in the window proc (try to) retrieve that and use it to call the derived class' virtual window proc.

As an aside, note that this is a sketch, not a finished work (so to speak). Though it should compile as-is, the result won't actually work unless you fill in a fair number of pieces that aren't here (e.g., the other fields of the WNDCLASS structure being only one of the most obvious).

这篇关于使用对象方法作为WinApi WndProc回调的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆