gpt4 book ai didi

c++ - MDI 面向对象的方法,从 MDICREATESTRUCT 检索 this 指针

转载 作者:太空宇宙 更新时间:2023-11-04 12:37:57 25 4
gpt4 key购买 nike

我正在尝试根据 to this reference 实现 MDI 子窗口基类备注详情说

When the MDI client window creates an MDI child window by calling CreateWindow, the system sends a WM_CREATE message to the created window. The lParam member of the WM_CREATE message contains a pointer to a CREATESTRUCT structure. The lpCreateParams member of this structure contains a pointer to the MDICREATESTRUCT structure passed with the WM_MDICREATE message that created the MDI child window.

我正在使用以下简单的基本模板类来创建 MDI 子窗口,实现上述语句来检索此指针。 (添加了一些评论)

basemdi.h

#pragma once
#include <Windows.h>

template <typename DERIVED_TYPE>
class BaseMDI
{
public:
inline HWND GetHandle() const;
BOOL Initialize(
PCTSTR szWindowName,
HWND hParent,
DWORD dwExStyle = WS_EX_MDICHILD, // THIS IS MDI WINDOW
DWORD dwStyle = 0,
int x = CW_USEDEFAULT,
int y = CW_USEDEFAULT,
int width = CW_USEDEFAULT,
int height = CW_USEDEFAULT,
HMENU hMenu = nullptr,
HINSTANCE hInstance = GetModuleHandle(nullptr),
LPVOID lpCreate = nullptr
);

protected:
virtual PCTSTR ClassName() const = 0;
static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) = 0;

HWND m_hwnd = nullptr;
};

template<typename DERIVED_TYPE>
BOOL BaseMDI<DERIVED_TYPE>::Initialize(
PCTSTR szWindowName,
HWND hParent,
DWORD dwExStyle,
DWORD dwStyle,
int x,
int y,
int width,
int height,
HMENU hMenu,
HINSTANCE hInstance,
LPVOID lpCreate)
{
UNREFERENCED_PARAMETER(lpCreate);

WNDCLASSEX wc = { };

wc.cbClsExtra = 0;
wc.cbSize = sizeof(WNDCLASSEX);
wc.cbWndExtra = 0;
wc.hbrBackground = reinterpret_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
wc.hIcon = nullptr;
wc.hInstance = hInstance;
wc.lpfnWndProc = WindowProc;
wc.lpszClassName = ClassName();
wc.lpszMenuName = nullptr;
wc.style = CS_VREDRAW | CS_HREDRAW;

RegisterClassEx(&wc);

MDICREATESTRUCT mdicreate;

// ASSIGN POINTER TO THIS SO THAT WE LATER RETRIEVE IT
mdicreate.lParam = (LPARAM) this;

mdicreate.szClass = ClassName();
mdicreate.szTitle = TEXT("Hello");
mdicreate.hOwner = hInstance;
mdicreate.x = CW_USEDEFAULT;
mdicreate.y = CW_USEDEFAULT;
mdicreate.cx = CW_USEDEFAULT;
mdicreate.cy = CW_USEDEFAULT;
mdicreate.style = dwStyle;

m_hwnd = CreateWindowEx(
dwExStyle,
ClassName(),
szWindowName,
dwStyle,
x, y,
width,
height,
hParent,
hMenu,
hInstance,
&mdicreate // PASS ADDRESS OF MDICREATESTRUCT
);

return m_hwnd ? TRUE : FALSE;
}
// following base class WndProc calls derived class procedure,
// I retrive this pointer here to call correct procedure, but pThis is read acess vioalaiton
template<typename DERIVED_TYPE>
inline LRESULT BaseMDI<DERIVED_TYPE>::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
DERIVED_TYPE* pThis = nullptr;

if (uMsg == WM_CREATE)
{
// RETRIEVE POINTER TO THIS
CREATESTRUCT* pCreate = reinterpret_cast<CREATESTRUCT*>(lParam);
MDICREATESTRUCT* pMdi = reinterpret_cast<MDICREATESTRUCT*>(pCreate->lpCreateParams);
pThis = reinterpret_cast<DERIVED_TYPE*>(pMdi->lParam);
SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pThis));

pThis->m_hwnd = hWnd;
}
else
{
pThis = reinterpret_cast<DERIVED_TYPE*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
}

if (pThis)
{
// EXCEPTION IS THROWN HERE
return pThis->HandleMessage(uMsg, wParam, lParam);
}
else
{
return DefMDIChildProc(hWnd, uMsg, wParam, lParam);
}
}

template <typename DERIVED_TYPE>
HWND BaseMDI<DERIVED_TYPE>::GetHandle() const
{
return m_hwnd;
}

下面是我如何创建 MDI 子窗口对象的实际实例,该类继承了上面的模板化基类

mdiwindow.h

#pragma once
#include "mdibase.h"

class MDI : public BaseMDI<MDI>
{
public:
virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) override;

private:
inline virtual PCTSTR ClassName() const override;
};

PCTSTR MDI::ClassName() const
{
return TEXT("MDIWindow");
}

mdiwindow.cpp

 #include "mdiwindow.h"


LRESULT MDI::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
default:
return DefMDIChildProc(m_hwnd, uMsg, wParam, lParam);
}
}

创建 MDI 子项时,我在 basemdi.h 中遇到异常,显示 pThis 指针的读取访问冲突

我正在按照有关如何检索指向 MDICREATESTRUCT 的指针的 msdn 说明进行操作传递给 CreateWindowEx , 它持有指向 this 的指针在 lpCreateParams但由于某种原因,检索到的指针不起作用。

你知道这可能是什么原因吗?

最佳答案

我设法解决了这个问题。

问题是 MSDN 正在谈论使用 CreateWindowCreateWindowEx 的可能性,这对子 MDI 窗口不起作用,需要使用 CreateMDIWindow 代替!

这是上面示例中的有效 Initialize 函数,上面的其余代码没问题:

template<typename DERIVED_TYPE>
BOOL BaseMDI<DERIVED_TYPE>::Initialize(
PCTSTR szWindowName,
HWND hParent,
DWORD dwExStyle,
DWORD dwStyle,
int x,
int y,
int width,
int height,
HMENU hMenu,
HINSTANCE hInstance,
LPVOID lpCreate)
{
UNREFERENCED_PARAMETER(lpCreate);

WNDCLASSEX wc = { };

wc.cbClsExtra = 0;
wc.cbSize = sizeof(WNDCLASSEX);
wc.cbWndExtra = 0;
wc.hbrBackground = reinterpret_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
wc.hIcon = nullptr;
wc.hInstance = hInstance;
wc.lpfnWndProc = WindowProc;
wc.lpszClassName = ClassName();
wc.lpszMenuName = nullptr;
wc.style = CS_VREDRAW | CS_HREDRAW;

if (!RegisterClassEx(&wc)) abort();

m_hwnd = CreateMDIWindow(
ClassName(),
szWindowName,
dwStyle,
x, y,
width,
height,
hParent,
hInstance,
(LPARAM)this);

if (!m_hwnd) abort();

return m_hwnd ? TRUE : FALSE;
}

关于c++ - MDI 面向对象的方法,从 MDICREATESTRUCT 检索 this 指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55547616/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com