Toj*_*oji 2 c++ winapi functor subclassing
快速健全性检查:是否可以使用仿函数对窗口进行子类化?我遇到了想要在win proc中获得一些数据的情况,但是GWLP_USERDATA已经被使用了.仿函数似乎是一个很好的选择,但我无法让它工作.
这是基础知识:
class MyWinProc { // Win Proc Functor
public:
MyWinProc(ExternalClass* obj, HWND window) :
obj(obj), window(window) {
oldWinProc = SubclassWindow(window, this); // Apply Subclass
}
virtual ~MyWinProc() {
SubclassWindow(window, oldWinProc); // Remove Subclass
}
LRESULT CALLBACK operator()(HWND, UINT, WPARAM, LPARAM) {
switch( uMsg ) {
case WM_MOUSEMOVE: {
obj->onMouseMove(/*etc*/);
break;
}
}
return CallWindowProc(oldWinProc, hWnd, uMsg, wParam, lParam);
}
private:
ExternalClass* obj;
HWND window;
WNDPROC oldWinProc;
};
Run Code Online (Sandbox Code Playgroud)
好像很好,但当我在消息泵中点击DispatchMessage()时,我"访问违规写入位置0x00000000",显然不是一个好兆头.删除对上述代码的调用,生活再次开心.:(所以这甚至可能,或者我完全以错误的方式去做?
CALLBACK函数必须是静态成员函数或其他直接的C风格函数.Windows API并不真正了解C++对象.
有些事情应该有效:
class MyWinProc {
public:
MyWinProc(ExternalClass* obj, HWND window) :
obj(obj), window(window) {
pContext = this;
oldWinProc = SubclassWindow(window, &MyWinProc::wndproc); // Apply Subclass
}
virtual ~MyWinProc() {
SubclassWindow(window, oldWinProc); // Remove Subclass
}
private:
static MyWinProc* pContext;
static
LRESULT CALLBACK wndproc( HWND, UINT, WPARAM, LPARAM) {
MyWndProc& me = *pContext;
// do your WndProc work...
}
ExternalClass* obj;
HWND window;
WNDPROC oldWinProc;
};
Run Code Online (Sandbox Code Playgroud)
使用仿函数的问题是调用约定:Windows期望地址是静态函数的地址,并且将使用/调用该地址; 而你传递的'this'不是静态函数的地址.
Windows将使用这样的地址(伪编码程序集):
; push the necessary parameters
push [hWnd]
push etc...
; invoke the specified address (of the static function)
call [callback]
Run Code Online (Sandbox Code Playgroud)
要调用仿函数,Windows代码必须是这样的
; push the necessary parameters
push [hWnd]
push etc...
; invoke the specified address (of the functor object)
; ... first, put the 'this' pointer as a hidden parameter into the ecx register
mov ecx,[callback]
; ... next, invoke the address (where is it?) of the class' functor method
call MyWinProc::operator()
Run Code Online (Sandbox Code Playgroud)
...或者代替最后两个语句,如果运算符是虚拟的,则以下语句...
; ... first, put the 'this' pointer as a hidden parameter into the ecx register
mov ecx,[callback]
; ... next, invoke the address of the operator via an (which?) entry
; in the class' vtable
call [ecx+8]
Run Code Online (Sandbox Code Playgroud)
这些都不可能,因为O/S不知道非静态C++方法的调用约定,尤其包括:
归档时间: |
|
查看次数: |
2326 次 |
最近记录: |