在 SDI mfc 应用程序中从视图访问模式对话框

Posted

技术标签:

【中文标题】在 SDI mfc 应用程序中从视图访问模式对话框【英文标题】:Access from View to modal dialog in SDI mfc application 【发布时间】:2020-05-04 22:59:44 【问题描述】:

我是编程初学者,我应该为我的期末论文创建一个应用程序。我的应用程序在 MFC 中创建为 SDI。我制作了一个从 View 打开的模态对话框。在对话框中,按下按钮后,测量设备应连接到应用程序并应注册多个事件。对话框关闭后,来自连接设备的坐标应显示在 Static Text 中的视图中

我可以从设备接收坐标,但如果我想更改 静态文本 以使用 ShowWindowTextW() 显示这些坐标,则会出现问题。如果我理解,当调用 DoModal() 时,对话框关闭,并且我无法从对话框中接收任何值或函数(因此,我无法更改视图中的 静态文本)。

我找到了一些使用指针的例子,但我不知道如何让它工作。我在这里停留了一段时间,并遇到了几种试图解决它们的错误。我的代码:

MainWindow.cpp - 查看

void CMainWindow::OnFileConnect()

    CConnect dlgConnect;
    dlgConnect.DoModal();




// Displays measurement
void CMainWindow::UpdatePosition() 
    if (ManagedWrapper::LMFTracker) 
        LMF::Tracker::MeasurementResults::SingleShotMeasurement3D^ position = ManagedWrapper::newPosition;
        m_dro_x.SetWindowTextW((CString)position->Position->Coordinate1->ToString());
        m_dro_y.SetWindowTextW((CString)position->Position->Coordinate2->ToString());
        m_dro_z.SetWindowTextW((CString)position->Position->Coordinate3->ToString());
    

Connect.cpp - 对话框

// CConnect dialog

IMPLEMENT_DYNAMIC(CConnect, CDialogEx)

CConnect::CConnect(CWnd* pParent /*=nullptr*/)
    : CDialogEx(IDD_CONNECTION, pParent)




CConnect::~CConnect()



void CConnect::DoDataExchange(CDataExchange* pDX)

    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_SIMULATOR, m_Simulator);
    DDX_Control(pDX, IDC_CONNECT, m_Connect);
    DDX_Control(pDX, IDC_IPADRESS, m_IPAdress);
 


BEGIN_MESSAGE_MAP(CConnect, CDialogEx)
    ON_BN_CLICKED(IDC_CONNECT, &CConnect::OnBnClickedButtonConnect)
    ON_BN_CLICKED(IDC_SIMULATOR, &CConnect::OnBnClickedButtonConnectsimulator)
    END_MESSAGE_MAP()



void CConnect::OnBnClickedButtonConnect()

    CString ipAdressString;
    m_IPAdress.GetWindowText(ipAdressString);
    ConnectTo(ipAdressString);


void CConnect::OnBnClickedButtonConnectsimulator()

    ConnectTo(_T("Simulator"));


void CConnect::ConnectTo(CString ipAddress)

    if (ManagedWrapper::LMFTracker)
    
        ManagedWrapper::LMFTracker->Disconnect();
    

    Connection^ con = gcnew Connection();
    if (ipAddress != "0.0.0.0") 
        ManagedWrapper::LMFTracker = con->Connect(gcnew System::String(ipAddress));


            // Register some Events...

    

在 CMainWindow.cpp 中的变量 position 是正确的值,所以这部分应该没问题。 如果我尝试调试代码,我会在 winocc.cpp 中得到错误:m_hWnd Unable to read memory

void CWnd::SetWindowText(LPCTSTR lpszString)

    ENSURE(this);
    ENSURE(::IsWindow(m_hWnd) || (m_pCtrlSite != NULL)); // exception thrown in this line

    if (m_pCtrlSite == NULL)
        ::SetWindowText(m_hWnd, lpszString);
    else
        m_pCtrlSite->SetWindowText(lpszString);

我有“抛出异常:读取访问冲突。 这是 0x250。”在上面评论的行中。 在调用堆栈中有:> mfc140ud.dll!CWnd::SetWindowTextW(const wchar_t * lpszString=0x00e5b200) 第 242 行 C++

下一个是:Aplikacia.exe!CMainWindow::UpdatePosition() Line 95 C++

即 MainWindow.cpp 中 m_dro_x 所在的行(m_dro_x 的值 hWnd=???)。

另一个:Aplikacia.exe!ManagedWrapper::OnTargetPostionChanged(LMF::Tracker::Tracker^ sender=LMF::Tracker::AT960Tracker^, LMF::Tracker::MeasurementResults::SingleShotMeasurement3D^ position= LMF::Tracker::MeasurementResults::SingleShotMeasurement3D^) 第 66 行 C++

这是来自 Aplikacia.h 文件 - 这是代码:

    class CAplikaciaApp : public CWinApp
    
    public:
        CAplikaciaApp() noexcept;


    // Overrides
    public:
        virtual BOOL InitInstance();
        virtual int ExitInstance();

    // Implementation
        afx_msg void OnAppAbout();
        DECLARE_MESSAGE_MAP()
    ;

    extern CAplikaciaApp theApp;


    ref class ManagedWrapper 
    public:
        static CMainWindow* pMainWindow = nullptr;

        static LMF::Tracker::Tracker^ LMFTracker = nullptr;
        static LMF::Tracker::MeasurementResults::SingleShotMeasurement3D^ newPosition = nullptr;



        static void OnTargetPostionChanged(LMF::Tracker::Tracker^ sender, LMF::Tracker::MeasurementResults::SingleShotMeasurement3D^ position) 

            newPosition = position;
            pMainWindow->UpdatePosition();
        

;

我找到了解决问题的方法,这篇文章很有帮助: static Pointer to Custom Type stays nullptr after initialization with static not-null pointer of same Type

我在 MainWindow.h 中添加了这一行:

extern CMainWindow* pMainWindow;

不知道这是否是最好的方法,但它有效。

【问题讨论】:

“调用 DoModal() 时,对话框关闭” - 这不是 DoModal() 所做的。相反,它会显示一个对话框,并且在对话框关闭之前不会返回。在显示对话框的同时,系统仍会为您发送消息,因此您可以向系统中的其他窗口发送消息,触发它们重绘等。在这里很难看出您真正要解决什么问题。 抱歉我的解释不好。问题是,我在 MainWindow.cpp 中的变量“位置”中有一些值,当我尝试将它传递给 m_dro_x.SetWindowText() 时,它显示了上述错误。我认为它与模态对话框有关。 如果您遇到错误,请发布 full 错误消息,以及导致该错误的调用堆栈。 我添加了调用堆栈中写入的内容并引发了异常。感谢您的努力。 访问冲突的最常见原因是取消引用无效指针时。触发 AV 异常的代码行中唯一的指针是隐式的this 指针。要了解为什么要访问不存在的 CWnd(-derived) 类实例,您将不得不查看调用堆栈。调用堆栈由更多条目组成,而不仅仅是顶部。我们已经知道,此代码中出现了错误。调用堆栈包含错误安装位置的信息。 【参考方案1】:

我找到了解决问题的方法,这篇文章很有帮助:static Pointer to Custom Type stays nullptr after initialization with static not-null pointer of same Type

我在 MainWindow.h 中添加了这一行:

extern CMainWindow* pMainWindow;

不知道这是否是最好的方法,但它有效

【讨论】:

以上是关于在 SDI mfc 应用程序中从视图访问模式对话框的主要内容,如果未能解决你的问题,请参考以下文章

MFC SDI 和对话框

如何在 SDI 中使用 MFC CListCtrl

在 MFC 中从文档类创建无模式对话框

MFC, SDI app, 为啥视图的布局不能通过代码改变?

MFC SDI程序,可停靠窗口嵌入对话框,对话框的初始化怎么做

MFC SDI中 如何为动态创建的按钮添加消息处理函数