MFC MDI 函数调用与 SendMessage。 C 程序员试图理解一个基本概念

问题描述 投票:0回答:2

作为一名高级硬件 EE,我的大部分编程时间都根据需要使用 C 来进行固件和内联汇编。我一直在开发 MFC MDI,你们中的一些人很好地帮助了我。我正在创建一个设置对话框,并从菜单项写入注册表以存储和检索应用程序

user settings
。我已经在周日用谷歌搜索了六种方法来尝试理解基本的
"Calling a function from another .cpp file class"
和许多其他变体以获得我的答案......失败了(主要是因为我可能不明白他们的答案)。

我有一个主程序重置,可以破坏我的应用程序创建的 HKEY_CURRENT_USER 键。效果很好,没有任何问题。现在,我不再将其作为

"Settings"
菜单中带有
"Reset App"
的项目,而是将其移至
button press
之一中的
property sheet/page dialogs

我可以使用它,但我不清楚为什么我最初的想法如何执行它会失败。

因此,在我的应用程序中,我触发了此功能:

void CApplication::OnResetProgramSettings() //Truncated function for StackOF clarity
{    
    // ask the user
    int DisableUserWarnings = FALSE;       
    if (DisableUserWarnings == FALSE) {

        if (IDNO == AfxMessageBox(IDS_WARNING_RESET_APP, MB_ICONQUESTION | MB_YESNO))
            return;
    }

    LSTATUS status = SHDeleteKey(HKEY_CURRENT_USER, _T("SOFTWARE\\Trains"));    
}

这是从以下地方调用的:

BEGIN_MESSAGE_MAP(CApplication, CWinAppEx)
   ...other commands
    ON_COMMAND(ID_SETTINGS_RESET_REGISTRY, OnResetProgramSettings)
    ...other commands
    ON_UPDATE_COMMAND_UI(ID_SETTINGS_RESET_REGISTRY, OnUpdateOnResetProgramSettings)
END_MESSAGE_MAP()

为了在我的新

Dialog Settings
部分中完成这项工作,我实现了以下内容:

void CSettingsReset::OnBnClickedButtonReset()
{
    // Global reset
    AfxGetMainWnd()->SendMessage(WM_COMMAND, ID_SETTINGS_RESET_REGISTRY);

    //CApplication::OnResetProgramSettings();
    //&CApplication::OnResetProgramSettings();
}

它的工作原理就像我选择了上面提到的菜单项

"Reset App"
一样。

属性页称为

SettingsReset.cpp
,上面的内容位于
Application.cpp

从 C 语言中,我通常会使用

application.h
文件中包含的
SettingsReset.h
调用该函数,如下所示:

OnResetProgramSettings();

我意识到这在 C++ 中的工作方式不同。您可以看到上面代码中注释掉的两个行项目并在下面取消注释:

    CApplication::OnResetProgramSettings(); //Doesn't get called, static error if memory serves
    &CApplication::OnResetProgramSettings(); //Doesn't get called
    CApplication OnResetProgramSettings; //Creates an object I don't want/need... or do I?
    

所以我将 AFX 消息发送到

"achieve"
相同的操作结果。我的最终问题是 Application.cpp 文件中的
"call"
OnResetProgramSettings()
FROM
文件中的
SettingsReset.cpp
的正确方法是什么?我读过有关制作函数
"Static"
的信息,但我不清楚如何做到这一点和/或为什么......现在每个函数都有两个单独的处理程序......即
OnResetProgramSettings()
OnResetProgramSettings1()
....正确吗?

有没有一种方法可以做到这一点,而无需使用 AFX 消息传递来触发该功能?

c++ visual-studio class mfc calling-convention
2个回答
2
投票

有两种简单的方法可以从应用程序类的“外部”调用该类的“非静态”成员函数。但它们本质上是相同的,因为您只需要通过实际的应用程序对象(实例)调用该成员函数。 首先,您可以使用该对象本身。在代码中的某个位置,您将有一个如下所示的应用程序变量:

CApplication MyApp;

如果您的项目是使用 Visual Studio 向导创建的,那么它“可能”位于“CApplication.cpp”文件中,并且“CApplication.h”标头中会有一个“声明”。任何包含该标头的源文件都可以简单地调用
public
成员

函数,如下所示: MyApp.OnResetProgramSettings(); 或者,您可以使用 MFC 标头中定义的 AfxGetApp() 调用获取指向当前应用程序实例的 pointer

(几乎可以从任何地方);但请注意,这必须转换为指向派生类的指针:
static_cast<CApplication*>(AfxGetApp())->OnResetProgramSettings();

但是,像这样调用成员有一个非常重要的警告:您不能对采用框架提供的参数的函数执行此操作,而在“正常”调用方法中,这些参数是由框架提供的。因此,例如,它根本不适用于 ON_UPDATE_COMMAND_UI

 消息处理程序(需要框架提供的 
CCmdUI*

参数)。

请注意,使用类向导创建时,消息处理程序被声明为
protected
,因此您必须稍微更改您的

CApplication
类,以使您需要以上述方式访问的内容公开。但这是微不足道的。

问题是 ON_UPDATE_COMMAND_UI

 宏创建了一个私有(或受保护?)成员函数,在您的情况下是 
CApplication::OnResetProgramSettings

。这意味着您不能直接从另一个类调用它(在您的情况下

0
投票
)。

一种方法是像您一样通过 
PostMessage
 触发命令(除非您依赖 
AfxGetMainWnd()
 而不是在对话框构造函数中获取指向应用程序类的指针 - 如果您稍后更改主窗口或使用系统通知图标等)。

另一种方法是将功能移至您

可以

直接调用的公共类中,并让
CApplication::OnResetProgramSettings
简单地调用该新函数。这样就避免了发送到消息队列的中间步骤。

当然,整个设计都被破坏了,所有这些实用程序的东西都应该从任何特定的窗口类移到一个专用的服务类,该服务类封装与注册表功能相关的所有内容,并且您的窗口接收并使用指向该服务的指针班级。将其视为过时的、糟糕的 MVVM 版本,因为您使用的是过时的技术 (MFC)。

© www.soinside.com 2019 - 2024. All rights reserved.