新手:Visual C++ MFC 应用程序中 show/hide STATIC TEXT 对象的代码
newbie: Code to show/hide a STATIC TEXT object in Visual C++ MFC app
我 运行 在我的第一个 VC++ MFC 应用程序中遇到了一个新手问题 (实际上,我 运行 遇到了很多问题,但是 RTFM 和 DuckDuckGo 帮助了我解决它们而不用在这里求救。除了这个!)。请记住,我将此作为自己的教程来玩,有点像 通过示例学习 项目,并且我在 Deplhi/Lazarus 中有几年的 Win GUI 应用程序编程经验],现在我正试图将 运行sition 转换为 VC++,只是出于我自己的好奇心。虽然我也擅长 C 语言 编程,但我对 C++ 的经验要少得多。所以新的编程环境和鲜为人知的语言共同构成了我的障碍。
这是我所做的:
在最近安装的 Visual Studio 2019 Community 中,仅选择 Windows App development in C++ 组件,开始一个新项目, 选择 C++ MFC App (构建具有复杂用户界面的应用程序 运行 on Windows。)。将应用程序类型设置为 Dialog based,关闭所有用户界面功能,因此仅选中 Thick frame (未选中系统菜单,未选中关于框),关闭所有高级功能,因此仅选中 Common Control Manifest (unck 打印和打印预览,unck Activex 控件,unck支持重启管理器),点击完成。
这为我准备了一个应用程序,其中包含一个小主 window、右下角的“确定”和“取消”按钮,中间有一个 STATIC TEXT 项目,内容类似于 “TODO:添加您的在这里拥有物品。项目名称是 TutMFC01p.
我的目标是在我单击其中一个按钮时隐藏该静态文本,并在我再次单击同一按钮时使其再次可见。
我花了一些时间才意识到我不应该 fiddle 使用 OK 和 Cancel 按钮为它们添加此功能,单击这两个按钮中的任何一个也会退出我的应用程序 (因此,没有机会再次点击)。所以我在对话框上放置了一个新按钮并使用它来代替。在我的应用 运行ning 时单击我的按钮绝对没有任何作用 - 这正是我想要的。
在 Dialog Editor 中双击我的按钮,使我进入 Source Editor,并在 [=] 底部自动生成一个新函数102=].
void CTutMFC01pDlg::OnBnClickedButton1()
{
// TODO: Add your control notification handler code here
}
好的,我将在此处添加按钮的功能代码。
它还向 MESSAGE MAP 注入了一个 ON_BN_CLICKED 行,现在看起来像这样。
BEGIN_MESSAGE_MAP(CTutMFC01pDlg, CDialogEx)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON1, &CTutMFC01pDlg::OnBnClickedButton1)
END_MESSAGE_MAP()
好的。所以这是告诉系统点击我的按钮应该 运行 CTutMFC01pDlg::OnBnClickedButton1().
中给出的代码的方法
我第一次尝试完成我的目标的方法是在单击我的按钮时在 VISIBILE 属性 的 TRUE 和 FALSE 值之间交替 STATIC TEXT 对象。 Delphi/Lazarus 的方法是像 mainform.mystatictext.visible := not mainform.mystatictext.visible
这样的单行代码,但我无法找到直接引用对象的 属性 并用简单的方法更改其值的方法赋值操作。相反,我发现隐藏对象的方法是使用 ShowWindow()
方法。我也 运行 遇到困难试图将此 (或任何其他) 方法指向 STATIC TEXT 对象,因为显然它的 ID 为 IDC_STATIC,其中,显然,不能引用,因为所有静态对象都具有相同的 ID。为了简化前面的任务,我没有隐藏 STATIC TEXT,而是隐藏了按钮本身,并以这段代码结束:
void CTutMFC01pDlg::OnBnClickedButton1()
{
// TODO: Add your control notification handler code here
CWnd* pMyButtonObj = GetDlgItem(IDC_BUTTON1);
pMyButtonObj->ShowWindow(SW_HIDE); //or SW_SHOW
}
这可以编译并且运行良好。显然,一旦按钮被按下并从 window 中消失,就没有什么可以再次按下以取消隐藏隐藏的内容。所以我试图从这个已经工作的代码继续前进并修改它以作用于 STATIC TEXT 而不是按钮本身。逻辑建议 (无论如何,我的逻辑),为了获得引用静态文本 ID 的能力,我需要为静态文本分配一个不同的 ID。我可以参考的东西。除了不可引用 IDC_STATIC 以外的东西。因此,我在对话框编辑器上选择了 STATIC TEXT 对象,并在其 属性 调色板中将 ID 属性 的值从 IDC_STATIC 更改为 IDC_STATIC1。这个st运行gely也把对象的NAME属性改成了IDC_STATIC11。之前的名称是 IDC_STATIC1。然后在 OnBnClickedButton1() 的代码中,我用 IDC_STATIC1 替换了 IDC_BUTTON1,但是编译失败,抱怨没有这样的对象。尝试使用 IDC_STATIC11.
时也会发生同样的情况
一些小实验揭示了另一种我无法解释的现象(或理解)。与我更改静态文本 ID 的方式类似,在 属性 编辑器中选择我的按钮,我将其 ID 从 IDC_BUTTON1 更改为 IDC_HideBtn。这也改变了它的名字 属性.
全部保存,重建项目,然后单击我的按钮仍然使它消失,就像以前一样。 然而,OnBnClickedButton1() 的源代码和 MESSAGE MAP 没有更新以引用新 ID,IDC_HideBtn,它们仍然引用 IDC_BUTTON1,和以前一样。
void CTutMFC01pDlg::OnBnClickedButton1()
{
//TODO: Add your control notification handler code here
CWnd* pMyButtonObj = GetDlgItem(IDC_BUTTON1);
pMyButtonObj->ShowWindow(SW_HIDE);
}
但此时,IDC_BUTTON1应该是一个不存在的ID。编译应该会失败。然而它编译得很好,而且工作正常。
问题:
- 为什么按钮的 ID 现在是 IDC_HideBtn,而代码在源代码中编译并使用 IDC_BUTTON1?
- 我该怎么做才能像处理 IDC_BUTTON1 一样将 STATIC TEXT 项目作为 GetDlgItem() 的参数进行处理?
- 如果不应以编程方式更改 STATIC TEXT 项目,那么我可以使用其他什么类型的项目来代替?在Delphi/Lazarus 中有一个类似于STATIC TEXT 的LABEL 对象,但旨在在程序运行 中多次获取不同的Caption 或其他值。在对话框编辑器的工具箱中,我看不到类似的东西,只有静态文本。或者我应该改用输入字段来在对话框中显示文本 window?
- 有没有办法像我最初尝试的Delphi/Lazarus那样实现按钮点击方法?将目标对象从隐藏变为可见,从可见变为隐藏。最好是单线。
- 有没有办法直接引用对象的 属性 并通过赋值操作更改其值?还是只有我没找到怎么办?
感谢我的问题收到的评论,我可以改进我的网络搜索方向,还可以检查我的项目文件夹中的其他文件以确定问题的来源,并了解我的 MFC 应用程序的各个部分如何组合在一起。此外,有时 Visual Studio 2019 的内部工作需要一些手动编辑帮助。
答案 1)
我可以在其 属性 调色板中分配给对象的所有这些 IDC_xyzwq 标识符 (值 select 可以来自列表)是指向它们各自数值的预定义宏。这些位于项目的 resource.h 文件中。不幸的是,VS2019 从来不允许我将这个文件作为可读文本打开——它总是抱怨文件已经打开并问我是否要关闭它。为了研究内容,我实际上不得不关闭我的 VS2019 解决方案,然后在文本编辑器中打开 resource.h 文件。这是我在那里找到的内容:
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by TutMFC01p.rc
//
#define IDD_TUTMFC01P_DIALOG 102
#define IDR_MAINFRAME 128
#define IDC_BUTTON1 1002
#define IDC_ButtHide 1002
#define IDC_HideBtn 1002
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 130
#define _APS_NEXT_COMMAND_VALUE 32771
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
所以似乎每次我为我的按钮发明一个新的ID并将其输入属性面板时,VS2019都会将一个新的宏定义注入到资源文件中,并将其分配给相同的数值1002. 但除了自动创建此类条目外,Visual Studio 不对它们执行任何维护,程序员有责任在那里保持秩序。这要求程序员了解什么是什么,以及它在项目文件中的存储位置。
因此,即使我的按钮对象在其 属性 调色板中已经具有 IDC_HideBtn 的 ID 值,但 IDC_ButtHide 和 IDC_BUTTON1 的早期 ID 仍然有效并且引用相同数值为 1002,因此使用旧 ID 编译的源代码,按钮工作正常。
请注意,在 Visual Studio 可以重新打开我的 solution/project.也请参阅我的答案的下一部分。
答案 2)
IDC_STATIC 是一个经过特殊处理的特殊 ID,我不能随便发明一个新名称并将其输入到我的 STATIC TEXT 项目的 ID 属性 字段中。更准确地说,我实际上可以发明任何新 ID 并将其输入 属性 字段,但 Visual Studio 不会自动在 resources.h 中生成相应的新宏定义,很可能是因为它不会知道分配给一个应该没有数值的对象的数值(因为它应该有特殊值-1)。因此,程序员不应在 ID 属性 字段中输入新名称,而应关闭解决方案,并在文本编辑器中手动编辑 resources.h 文件。是的,在 Microsoft 文档中和经验丰富的开发人员的所有警告和劝阻下,在这种特殊情况下,必须手动完成。 (或者至少,我不知道比直接将资源文件编辑为文本更好的方法。) 这是我通过删除两个过时和不需要的按钮将宏定义更改为的内容值为 1002 的标识符,并手动添加用于我的 STATIC TEXT 项目的新定义条目 - 其数值未被任何其他条目使用。在我的例子中,1001 还没有被使用,所以这是我分配给我发明的 ID IDC_MidTextObj.
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by TutMFC01p.rc
//
#define IDD_TUTMFC01P_DIALOG 102
#define IDR_MAINFRAME 128
#define IDC_HideBtn 1002
#define IDC_MidTextObj 1001
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 130
#define _APS_NEXT_COMMAND_VALUE 32771
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
在 resource.h 中保存这些更改后,我可以关闭我的文本编辑器并在 Visual Studio 中重新打开 solution/project。然后我可以 select UI 编辑器中的 STATIC TEXT 项,在它的 属性 调色板中,在 ID 属性 的字段中,我可以下拉列表值和 select 我准备的值 IDC_MidTextObj。请注意,还有另一种方法,即手动编辑对话框的 .rc 文件。无论如何,您可能出于其他原因需要这样做。请参阅我的回答的下一部分。
答案 3)
这是我的 TutMFC01p.rc 文件的相关部分。
IDD_TUTMFC01P_DIALOG DIALOGEX 0, 0, 320, 199
STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_THICKFRAME
EXSTYLE WS_EX_CLIENTEDGE | WS_EX_APPWINDOW
CAPTION "My VisualC++ Tutorial App 01"
FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,209,178,50,14
PUSHBUTTON "Cancel",IDCANCEL,263,178,50,14
CTEXT "TODO: Place dialog controls here.",IDC_STATIC,13,96,300,8
LTEXT "Hello MFC!",IDC_STATIC,22,33,86,8,WS_DISABLED
PUSHBUTTON "Hide object",IDC_HideBtn,135,106,50,14
END
我可以更改以 CTEXT 开头的行并将 IDC_STATIC 替换为 IDC_MidTextObj 以确保 STATIC TEXT 项目使用我预先创建的值。
此外,如果仔细观察,您会发现下一行定义了另一个 STATIC TEXT 项 (我在对话框编辑器中添加到 window 的新静态文本项)。但这是 LTEXT 而不是 CTEXT。如果不以文本形式查看这段代码,我就不会知道有这两种不同的类型。也许 LTEXT 就是我所追求的。我会在文档中看到关于此的内容。
答案 4)
不是单线。有关详细信息,另请参阅我的答案的下一部分。但是可以用多行代码来完成,调用方法先查询对象当前的可见状态,可见则隐藏,隐藏则显示。
答案 5)
不,在 VC++ 中无法做到这一点。它适用于其他语言,但在 C++ 中你必须调用 functions/methods。请参阅 similar issue.
底部 Mark Ransom 的回答
我有一些小的更正(如我所想),我想将它们作为评论发布,但根据 comment policy 最好是 post 一个答案尽管已经给出了答案。
问题二:
奇怪的是,VS 没有在重命名 CStatic
组件时为 IDC_STATIC1 添加新定义 resource.h
(毕竟 VS 为新按钮创建了新 ID)。
但是,当然,手动编辑 resource.h
是使用 MFC 编程期间非常频繁的过程,但有必要更新 _APS_NEXT_CONTROL_VALUE
(更不用说 _APS_NEXT_COMMAND_VALUE
)定义,使其指向一个新的正确值(不等于以前的定义)。
问题三:
但是你可以在 .rc
文件中这样写:
BEGIN
DEFPUSHBUTTON "OK",IDOK,209,178,50,14
PUSHBUTTON "Cancel",IDCANCEL,263,178,50,14
CTEXT "TODO: Place dialog controls here.",IDC_MidTextObj,13,96,300,8
PUSHBUTTON "Hide object",IDC_HideBtn,135,106,50,14
END
然后在CTutMFC01pDlg.cpp:
void CTutMFC01pDlg::OnBnClickedHidebtn()
{
if (CWnd * pMyStaticObj = GetDlgItem(IDC_MidTextObj))
pMyStaticObj->ShowWindow(!pMyStaticObj->IsWindowVisible());
}
问题四:
您还可以为 CStatic、CEdit 等组件使用 getting/setting 文本的 DoDataExchange
机制,并且可以为 enabling/disabling 组件使用 ON_UPDATE_COMMAND_UI
宏。
但基本的方法是将组件作为 CWnd class:
CWnd * pMyStaticObj = GetDlgItem(IDC_MidTextObj)
或明确获取组件:
CStatic* pMyStaticObj = static_cast<CStatic*>(GetDlgItem(IDC_STATIC1));
(这里不要用dynamic_cast
)
然后调用这个获取的实例的方法。
我 运行 在我的第一个 VC++ MFC 应用程序中遇到了一个新手问题 (实际上,我 运行 遇到了很多问题,但是 RTFM 和 DuckDuckGo 帮助了我解决它们而不用在这里求救。除了这个!)。请记住,我将此作为自己的教程来玩,有点像 通过示例学习 项目,并且我在 Deplhi/Lazarus 中有几年的 Win GUI 应用程序编程经验],现在我正试图将 运行sition 转换为 VC++,只是出于我自己的好奇心。虽然我也擅长 C 语言 编程,但我对 C++ 的经验要少得多。所以新的编程环境和鲜为人知的语言共同构成了我的障碍。
这是我所做的:
在最近安装的 Visual Studio 2019 Community 中,仅选择 Windows App development in C++ 组件,开始一个新项目, 选择 C++ MFC App (构建具有复杂用户界面的应用程序 运行 on Windows。)。将应用程序类型设置为 Dialog based,关闭所有用户界面功能,因此仅选中 Thick frame (未选中系统菜单,未选中关于框),关闭所有高级功能,因此仅选中 Common Control Manifest (unck 打印和打印预览,unck Activex 控件,unck支持重启管理器),点击完成。
这为我准备了一个应用程序,其中包含一个小主 window、右下角的“确定”和“取消”按钮,中间有一个 STATIC TEXT 项目,内容类似于 “TODO:添加您的在这里拥有物品。项目名称是 TutMFC01p.
我的目标是在我单击其中一个按钮时隐藏该静态文本,并在我再次单击同一按钮时使其再次可见。
我花了一些时间才意识到我不应该 fiddle 使用 OK 和 Cancel 按钮为它们添加此功能,单击这两个按钮中的任何一个也会退出我的应用程序 (因此,没有机会再次点击)。所以我在对话框上放置了一个新按钮并使用它来代替。在我的应用 运行ning 时单击我的按钮绝对没有任何作用 - 这正是我想要的。
在 Dialog Editor 中双击我的按钮,使我进入 Source Editor,并在 [=] 底部自动生成一个新函数102=].
void CTutMFC01pDlg::OnBnClickedButton1()
{
// TODO: Add your control notification handler code here
}
好的,我将在此处添加按钮的功能代码。
它还向 MESSAGE MAP 注入了一个 ON_BN_CLICKED 行,现在看起来像这样。
BEGIN_MESSAGE_MAP(CTutMFC01pDlg, CDialogEx)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON1, &CTutMFC01pDlg::OnBnClickedButton1)
END_MESSAGE_MAP()
好的。所以这是告诉系统点击我的按钮应该 运行 CTutMFC01pDlg::OnBnClickedButton1().
中给出的代码的方法
我第一次尝试完成我的目标的方法是在单击我的按钮时在 VISIBILE 属性 的 TRUE 和 FALSE 值之间交替 STATIC TEXT 对象。 Delphi/Lazarus 的方法是像 mainform.mystatictext.visible := not mainform.mystatictext.visible
这样的单行代码,但我无法找到直接引用对象的 属性 并用简单的方法更改其值的方法赋值操作。相反,我发现隐藏对象的方法是使用 ShowWindow()
方法。我也 运行 遇到困难试图将此 (或任何其他) 方法指向 STATIC TEXT 对象,因为显然它的 ID 为 IDC_STATIC,其中,显然,不能引用,因为所有静态对象都具有相同的 ID。为了简化前面的任务,我没有隐藏 STATIC TEXT,而是隐藏了按钮本身,并以这段代码结束:
void CTutMFC01pDlg::OnBnClickedButton1()
{
// TODO: Add your control notification handler code here
CWnd* pMyButtonObj = GetDlgItem(IDC_BUTTON1);
pMyButtonObj->ShowWindow(SW_HIDE); //or SW_SHOW
}
这可以编译并且运行良好。显然,一旦按钮被按下并从 window 中消失,就没有什么可以再次按下以取消隐藏隐藏的内容。所以我试图从这个已经工作的代码继续前进并修改它以作用于 STATIC TEXT 而不是按钮本身。逻辑建议 (无论如何,我的逻辑),为了获得引用静态文本 ID 的能力,我需要为静态文本分配一个不同的 ID。我可以参考的东西。除了不可引用 IDC_STATIC 以外的东西。因此,我在对话框编辑器上选择了 STATIC TEXT 对象,并在其 属性 调色板中将 ID 属性 的值从 IDC_STATIC 更改为 IDC_STATIC1。这个st运行gely也把对象的NAME属性改成了IDC_STATIC11。之前的名称是 IDC_STATIC1。然后在 OnBnClickedButton1() 的代码中,我用 IDC_STATIC1 替换了 IDC_BUTTON1,但是编译失败,抱怨没有这样的对象。尝试使用 IDC_STATIC11.
时也会发生同样的情况
一些小实验揭示了另一种我无法解释的现象(或理解)。与我更改静态文本 ID 的方式类似,在 属性 编辑器中选择我的按钮,我将其 ID 从 IDC_BUTTON1 更改为 IDC_HideBtn。这也改变了它的名字 属性.
全部保存,重建项目,然后单击我的按钮仍然使它消失,就像以前一样。 然而,OnBnClickedButton1() 的源代码和 MESSAGE MAP 没有更新以引用新 ID,IDC_HideBtn,它们仍然引用 IDC_BUTTON1,和以前一样。
void CTutMFC01pDlg::OnBnClickedButton1()
{
//TODO: Add your control notification handler code here
CWnd* pMyButtonObj = GetDlgItem(IDC_BUTTON1);
pMyButtonObj->ShowWindow(SW_HIDE);
}
但此时,IDC_BUTTON1应该是一个不存在的ID。编译应该会失败。然而它编译得很好,而且工作正常。
问题:
- 为什么按钮的 ID 现在是 IDC_HideBtn,而代码在源代码中编译并使用 IDC_BUTTON1?
- 我该怎么做才能像处理 IDC_BUTTON1 一样将 STATIC TEXT 项目作为 GetDlgItem() 的参数进行处理?
- 如果不应以编程方式更改 STATIC TEXT 项目,那么我可以使用其他什么类型的项目来代替?在Delphi/Lazarus 中有一个类似于STATIC TEXT 的LABEL 对象,但旨在在程序运行 中多次获取不同的Caption 或其他值。在对话框编辑器的工具箱中,我看不到类似的东西,只有静态文本。或者我应该改用输入字段来在对话框中显示文本 window?
- 有没有办法像我最初尝试的Delphi/Lazarus那样实现按钮点击方法?将目标对象从隐藏变为可见,从可见变为隐藏。最好是单线。
- 有没有办法直接引用对象的 属性 并通过赋值操作更改其值?还是只有我没找到怎么办?
感谢我的问题收到的评论,我可以改进我的网络搜索方向,还可以检查我的项目文件夹中的其他文件以确定问题的来源,并了解我的 MFC 应用程序的各个部分如何组合在一起。此外,有时 Visual Studio 2019 的内部工作需要一些手动编辑帮助。
答案 1)
我可以在其 属性 调色板中分配给对象的所有这些 IDC_xyzwq 标识符 (值 select 可以来自列表)是指向它们各自数值的预定义宏。这些位于项目的 resource.h 文件中。不幸的是,VS2019 从来不允许我将这个文件作为可读文本打开——它总是抱怨文件已经打开并问我是否要关闭它。为了研究内容,我实际上不得不关闭我的 VS2019 解决方案,然后在文本编辑器中打开 resource.h 文件。这是我在那里找到的内容:
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by TutMFC01p.rc
//
#define IDD_TUTMFC01P_DIALOG 102
#define IDR_MAINFRAME 128
#define IDC_BUTTON1 1002
#define IDC_ButtHide 1002
#define IDC_HideBtn 1002
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 130
#define _APS_NEXT_COMMAND_VALUE 32771
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
所以似乎每次我为我的按钮发明一个新的ID并将其输入属性面板时,VS2019都会将一个新的宏定义注入到资源文件中,并将其分配给相同的数值1002. 但除了自动创建此类条目外,Visual Studio 不对它们执行任何维护,程序员有责任在那里保持秩序。这要求程序员了解什么是什么,以及它在项目文件中的存储位置。
因此,即使我的按钮对象在其 属性 调色板中已经具有 IDC_HideBtn 的 ID 值,但 IDC_ButtHide 和 IDC_BUTTON1 的早期 ID 仍然有效并且引用相同数值为 1002,因此使用旧 ID 编译的源代码,按钮工作正常。
请注意,在 Visual Studio 可以重新打开我的 solution/project.也请参阅我的答案的下一部分。
答案 2)
IDC_STATIC 是一个经过特殊处理的特殊 ID,我不能随便发明一个新名称并将其输入到我的 STATIC TEXT 项目的 ID 属性 字段中。更准确地说,我实际上可以发明任何新 ID 并将其输入 属性 字段,但 Visual Studio 不会自动在 resources.h 中生成相应的新宏定义,很可能是因为它不会知道分配给一个应该没有数值的对象的数值(因为它应该有特殊值-1)。因此,程序员不应在 ID 属性 字段中输入新名称,而应关闭解决方案,并在文本编辑器中手动编辑 resources.h 文件。是的,在 Microsoft 文档中和经验丰富的开发人员的所有警告和劝阻下,在这种特殊情况下,必须手动完成。 (或者至少,我不知道比直接将资源文件编辑为文本更好的方法。) 这是我通过删除两个过时和不需要的按钮将宏定义更改为的内容值为 1002 的标识符,并手动添加用于我的 STATIC TEXT 项目的新定义条目 - 其数值未被任何其他条目使用。在我的例子中,1001 还没有被使用,所以这是我分配给我发明的 ID IDC_MidTextObj.
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by TutMFC01p.rc
//
#define IDD_TUTMFC01P_DIALOG 102
#define IDR_MAINFRAME 128
#define IDC_HideBtn 1002
#define IDC_MidTextObj 1001
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 130
#define _APS_NEXT_COMMAND_VALUE 32771
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
在 resource.h 中保存这些更改后,我可以关闭我的文本编辑器并在 Visual Studio 中重新打开 solution/project。然后我可以 select UI 编辑器中的 STATIC TEXT 项,在它的 属性 调色板中,在 ID 属性 的字段中,我可以下拉列表值和 select 我准备的值 IDC_MidTextObj。请注意,还有另一种方法,即手动编辑对话框的 .rc 文件。无论如何,您可能出于其他原因需要这样做。请参阅我的回答的下一部分。
答案 3)
这是我的 TutMFC01p.rc 文件的相关部分。
IDD_TUTMFC01P_DIALOG DIALOGEX 0, 0, 320, 199
STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_THICKFRAME
EXSTYLE WS_EX_CLIENTEDGE | WS_EX_APPWINDOW
CAPTION "My VisualC++ Tutorial App 01"
FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,209,178,50,14
PUSHBUTTON "Cancel",IDCANCEL,263,178,50,14
CTEXT "TODO: Place dialog controls here.",IDC_STATIC,13,96,300,8
LTEXT "Hello MFC!",IDC_STATIC,22,33,86,8,WS_DISABLED
PUSHBUTTON "Hide object",IDC_HideBtn,135,106,50,14
END
我可以更改以 CTEXT 开头的行并将 IDC_STATIC 替换为 IDC_MidTextObj 以确保 STATIC TEXT 项目使用我预先创建的值。
此外,如果仔细观察,您会发现下一行定义了另一个 STATIC TEXT 项 (我在对话框编辑器中添加到 window 的新静态文本项)。但这是 LTEXT 而不是 CTEXT。如果不以文本形式查看这段代码,我就不会知道有这两种不同的类型。也许 LTEXT 就是我所追求的。我会在文档中看到关于此的内容。
答案 4)
不是单线。有关详细信息,另请参阅我的答案的下一部分。但是可以用多行代码来完成,调用方法先查询对象当前的可见状态,可见则隐藏,隐藏则显示。
答案 5)
不,在 VC++ 中无法做到这一点。它适用于其他语言,但在 C++ 中你必须调用 functions/methods。请参阅 similar issue.
底部 Mark Ransom 的回答我有一些小的更正(如我所想),我想将它们作为评论发布,但根据 comment policy 最好是 post 一个答案尽管已经给出了答案。
问题二:
奇怪的是,VS 没有在重命名 CStatic
组件时为 IDC_STATIC1 添加新定义 resource.h
(毕竟 VS 为新按钮创建了新 ID)。
但是,当然,手动编辑 resource.h
是使用 MFC 编程期间非常频繁的过程,但有必要更新 _APS_NEXT_CONTROL_VALUE
(更不用说 _APS_NEXT_COMMAND_VALUE
)定义,使其指向一个新的正确值(不等于以前的定义)。
问题三:
但是你可以在 .rc
文件中这样写:
BEGIN
DEFPUSHBUTTON "OK",IDOK,209,178,50,14
PUSHBUTTON "Cancel",IDCANCEL,263,178,50,14
CTEXT "TODO: Place dialog controls here.",IDC_MidTextObj,13,96,300,8
PUSHBUTTON "Hide object",IDC_HideBtn,135,106,50,14
END
然后在CTutMFC01pDlg.cpp:
void CTutMFC01pDlg::OnBnClickedHidebtn()
{
if (CWnd * pMyStaticObj = GetDlgItem(IDC_MidTextObj))
pMyStaticObj->ShowWindow(!pMyStaticObj->IsWindowVisible());
}
问题四:
您还可以为 CStatic、CEdit 等组件使用 getting/setting 文本的 DoDataExchange
机制,并且可以为 enabling/disabling 组件使用 ON_UPDATE_COMMAND_UI
宏。
但基本的方法是将组件作为 CWnd class:
CWnd * pMyStaticObj = GetDlgItem(IDC_MidTextObj)
或明确获取组件:
CStatic* pMyStaticObj = static_cast<CStatic*>(GetDlgItem(IDC_STATIC1));
(这里不要用dynamic_cast
)
然后调用这个获取的实例的方法。