- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在尝试根据 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 正在谈论使用 CreateWindow
或 CreateWindowEx
的可能性,这对子 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/
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我正在开发一个 .NET C# 应用程序,它有一个主窗体,它是 MDI 容器。当用户最大化 MDI 子项时,Windows 会在容器窗体的标题栏下方绘制一个控制条,其中包含子项的图标和右侧的系统按钮。
我有一个用 Delphi 2006 编写的 MDI 应用程序,它以默认主题运行 XP。 有没有办法控制 MDI 子项的外观以避免每个窗口上出现 XP 风格的大标题栏? 我尝试将 MDIChildren
我有一个包含面板的 MDI 父窗体。该面板包括图表和一些其他用户信息。当我从菜单中打开一个窗体时,新打开的窗体显示在 MDI 父面板下。如何显示所有 MDI 父控件上方的子窗体。我正在使用以下代码打开
我有一个 MDI 父窗体,它在运行时创建许多 MDI 子窗体。有没有一种聪明的方法可以在父级内部平均分配这些表格?有什么想法吗? 提前致谢! 最佳答案 **ArrangeIcons** chi
我想知道如何加载子表单,使其大小覆盖整个 MDI 父级的 MDI 容器空间(深灰色的东西)?将子窗体的 WindowState 设置为最大化不是一个选项,因为它也会最大化任何其他窗体。有建议吗? 最佳
我已经创建了一个父表单并为此引发了 ControlAdded 事件。并且还将此父窗体的属性 IsMdiContainer 设置为 true。然后,如果我创建一个名为 ChildForm1 和 Chil
我希望 MDI 父级自动调整子窗体的大小,使其在没有滚动条的情况下适合内部。有人可以提供一些代码吗? 我用它来区分父项和子项的大小,并将其添加到父项的大小,这样我就可以合身了。但它太手动了,制作时间太
我正在打开另一个 MDI 子窗体的 MDI 子窗体,它正在工作,但现在我必须以相同的方式关闭它,但没有任何反应。 这是我正在使用的代码示例: private void checkbox1_Checke
是否可以这样做,如果可以,怎么做? 我的应用程序的屏幕截图 最佳答案 您需要设置 AllowMerge property MenuStrip 的 false。 这将使子窗体上的 MenuStrip 保
我有一个带有多个子项的 MDI 表单,当我最大化一个 MDI 子项时,它会自动最大化所有子项。 我不想使用设置最大大小或设置最小大小属性。有什么办法可以防止mdi child 的这种行为吗? 最佳答案
我正在制作一个小型企业应用程序,我想知道最好的界面是什么。该应用程序本身就是您的普通服务票务跟踪器。将有用于搜索工单(带有结果网格)、创建新的勾选和查看现有工单、管理一些管理内容(用户、一些分类器等)
您好,我想打开来自 MDI Parent 的表格。 如果 For 已经打开,那么它应该被激活或打开新表格..现在我正在使用 foreach 循环。但我不想使用循环。 foreach (Form frm
我有一个 MDI 主窗体,一个显示子窗体的菜单项(我们称它为 frmEmployees),在这个窗体中有一个 Button (btnNew...) , 我如何从这里打开一个对话框 (frmNewEmp
我试图在 MDI 父级上检测我的 MDI 子级窗体何时关闭,并做出相应的 react 。在 MDI 子级关闭之前,MDI 父级不应执行任何操作。这是我的代码,我不确定我做错了什么,但是我添加的表单关闭
如何在正常创建的 MDI 窗口窗体中显示 WPF 窗体。 我们将表单创建为 MDI。增加菜单栏点击菜单会在主容器MDi窗体中显示wpf窗体。 private void newStudentToolS
我在子表单中有一个值(let CompanyId)。我想在 MDI 父窗体的级别中传递此值。 在子窗体中,我在数据 GridView 中从数据库中检索数据。现在我从数据 GridView 中选择一个值
我有一个带有此 FormClosing 事件处理程序的 MDI 父级: private void FrmMdiParent_FormClosing(object sender, FormClosing
有没有办法从用 Delphi 5 编写的 ActiveX dll 创建 MDI 子窗口,并将其嵌入到从 Delphi XE Windows 客户端应用程序创建的 MDI 父窗口中?如果没有,有没有办法
这个问题之前已经发布过,但我找不到一个好的答案。 我想在我的 WPF 应用程序中使用 MDI 子级。我希望这些 child 完全符合 WPF。 .Net WPF 不再有 MDI 子项(主窗口中的窗口)
我是一名优秀的程序员,十分优秀!