MDI 面向对象方法,从 MDICREATESTRUCT 中检索此指针 [英] MDI object oriented approach, retrieving this pointer from MDICREATESTRUCT

查看:31
本文介绍了MDI 面向对象方法,从 MDICREATESTRUCT 中检索此指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试实现 MDI 子窗口基类,根据 到此参考 备注的详细信息说

I'm trying to implement MDI Child window base class, according to this reference details on remarks say

当 MDI 客户端窗口通过调用创建 MDI 子窗口时CreateWindow,系统向创建的窗口发送 WM_CREATE 消息窗户.WM_CREATE 消息的 lParam 成员包含一个指针到 CREATESTRUCT 结构.这个 lpCreateParams 成员结构包含指向传递的 MDICREATESTRUCT 结构的指针使用创建 MDI 子窗口的 WM_MDICREATE 消息.

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 子窗口,实现上述语句来检索此指针.(添加了一些评论)

I'm using following simple base template class to create MDI child window, implementing above statements to retrieve this pointer. (added few comments)

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 子窗口对象的实际实例的方法,该类继承上述模板化基类

Here is how I create an actual instance of the MDI child window object, the class inherits above templated base class

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 指针读取访问冲突.

When the MDI child is created I got exception in basemdi.h saying read access violation for pThis pointer.

我正在遵循 msdn 说明,了解如何检索指向 MDICREATESTRUCT 的指针,该指针传递给 CreateWindowEx,该指针在 this 中保存了指向 this 的指针code>lpCreateParams 但由于某种原因检索到的指针不起作用.

I'm folowing msdn instructions on how to retrieve pointer to MDICREATESTRUCT that is passed to CreateWindowEx, which holds pointer to this in lpCreateParams but for some reason the retrieved pointer doesn't work.

你知道这是什么原因吗?

Do you see what could be cause for this?

推荐答案

我最近在使用带有 OOP 方法的 MDI 来获得乐趣,这对我有用:

I was recently using MDI with an OOP approach for fun and this works for me:

    MDICREATESTRUCT mcs;
    mcs.szTitle = WindowText();
    mcs.szClass = ClassName();
    mcs.hOwner = GetModuleHandle( nullptr );
    mcs.x = x;
    mcs.y = y;
    mcs.cx = width;
    mcs.cy = height;
    mcs.style = dwStyle;
    mcs.lParam = reinterpret_cast< LPARAM >( this );

    mSubWnd = reinterpret_cast< HWND >( SendMessage( hParent, WM_MDICREATE, 0, reinterpret_cast< LONG >( &mcs ) ) );

这篇关于MDI 面向对象方法,从 MDICREATESTRUCT 中检索此指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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