我正在尝试绕过WINAPI来实现无模式Dialog窗口的过程作为自定义类的成员。我不确定这是可能的,但我希望有人知道。目标是让一个过程可以访问自定义类
的成员变量我知道可以使用普通的窗户。 示例:
//MyClass.h
class MyClass
{
public:
bool init( ... )
static LRESULT CALLBACK redirect(HWND hWnd, UINT msg,
LPARAM lParam, WPARAM wParam);
LRESULT myWndProc(HWND hWnd, UINT msg,
LPARAM lParam, WPARAM wParam);
private:
HWND m_MainHwnd;
}
通过定义将指针重定向到非静态实际过程处理的静态成员函数,该过程可以是成员函数:
//MyClass.cpp
MyClass::init( ... )
{
//Create the window class for the main Window//
m_windowed = windowed;
WNDCLASSEX wc; //Create a new extended windows class
wc.cbSize = sizeof(WNDCLASSEX); //Size of our windows class
wc.style = CS_HREDRAW | CS_VREDRAW; //class styles
wc.lpfnWndProc = MyClass::redirect; //Default windows procedure function
wc.cbClsExtra = NULL; //Extra bytes after our wc structure
wc.cbWndExtra = NULL; //Extra bytes after our windows instance
wc.hInstance = hInstance; //Instance to current application
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); //Title bar Icon
wc.hCursor = LoadCursor(NULL, IDC_ARROW); //Default mouse Icon
wc.hbrBackground = CreateSolidBrush(0xFFFFFF); //Window bg color
wc.lpszMenuName = NULL; //Name of the menu attached to our window
wc.lpszClassName = m_windowName; //Name of our windows class
wc.hIconSm = LoadIcon(NULL, IDI_WINLOGO); //Icon in your taskbar
if (!RegisterClassEx(&wc)) //Register our windows class
{
//if registration failed, display error
MessageBox(NULL, "Error registering Main Window class",
"Error", MB_OK | MB_ICONERROR);
return false;
}
m_MainHwnd = CreateWindowEx( //Create our Extended Window
NULL, //Extended style
m_windowName, //Name of our windows class
m_windowName, //Name in the title bar of our window
WS_OVERLAPPEDWINDOW | WS_VISIBLE, //style of our window | Make it visible on showWindow cmd
30, 30, //Top left corner of window
width, //Width of our window
height, //Height of our window
NULL, //Handle to parent window
NULL, //Handle to a Menu
hInstance, //Specifies instance of current program
this //used for an MDI client window
);
}
请参阅WNDCLASSEX设置中的行: wc.lpfnWndProc = MyClass :: redirect; ?这是有效的,因为以下实现了重定向静态函数:
MyClass::redirect(HWND hwnd, UINT msg, LPARAM lParam, WPARAM wParam)
{
if (msg == WM_CREATE) SetWindowLongPtr(hwnd, GWL_USERDATA, (LONG_PTR)((CREATESTRUCT FAR *)lParam)->lpCreateParams);
MyClass * pObject = (MyClass*)((LONG_PTR)GetWindowLongPtr(hwnd, GWL_USERDATA));
if (pObject) return pObject->MyWndProc(hwnd, msg, wParam, lParam);
//return the message for windows to handle it
return DefWindowProc(hwnd,
msg,
wParam,
lParam);
};
这使您可以像任何其他成员方法一样实现MyWndProc(...)。
现在!我真的希望能够对我的无模式对话框执行相同的操作 - 因为它知道“MyClass”的成员变量非常重要。另外 - 我喜欢我可以设计它并按照我的喜好重新设计它(如果我必须使用普通的窗口 - 在代码中设计它是很乏味的。)
有可能吗?
提前谢谢!
答案 0 :(得分:2)
是的,可以在对话框中使用此方法,方式大致相同。
而不是使用WM_CREATE
存储this
指针,而是使用WM_INITDIALOG
。请注意,用户数据会传递到WM_INITDIALOG
本身的lParam
- 没有与WM_CREATE
一样的解除引用结构。
您可以将指针存储在DWLP_USER
中,这是对话框所有者可用的指针大小窗口数据槽。
如果数据指针尚未分配,则最终的差异只是返回FALSE
- 您不会从对话程序中调用DefWindowProc
。
class MyClass
{
public:
static INT_PTR CALLBACK dlgRedirect(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT myDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
}
//...
HWND hwndDlg = DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_MYDIALOG), hwndParent,
MyClass::dlgRedirect, reinterpret_cast<LPARAM>(this));
//...
INT_PTR CALLBACK MyClass::dlgRedirect(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (uMsg == WM_INITDIALOG) SetWindowLongPtr(hWnd, DWLP_USER, lParam);
MyClass* pThis = reinterpret_class<MyClass*>(GetWindowLongPtr(hWnd, DWLP_USER));
if (pThis) return pThis->myDlgProc(hWnd, uMsg, wParam, lParam);
return FALSE;
}
INT_PTR MyClass::myDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
// real dialog procedure here
}