MFC MDI 收集“应用”按钮例程的控制状态
Posted
技术标签:
【中文标题】MFC MDI 收集“应用”按钮例程的控制状态【英文标题】:MFC MDI Collecting control states for the "apply" button routine 【发布时间】:2021-05-05 19:21:29 【问题描述】:在我的应用程序的其他一些线程中提到我的代码不正确,因为存在应用按钮。我现在明白了。据说是收集控件,然后在点击应用时发送数据。
我现在知道如何解决这个问题。所以为了通识教育。我有 1 个property sheet
和 5 个property pages
。为了使用中的一般控件。在所有 5 个之间,只有 radio
控件和 buttons
,没有 edit controls
(还没有)。
假设每个页面上都有2 radios buttons
和1 button
.. 其中page 1
是radio1
、radio2
、button 1
和page 2
是radio3
、radio4
、@9876 @....等等。
我知道,当用户选择按钮或单选按钮时,需要调用 IsModified(TRUE)
以使应用按钮从灰色变为活动状态。
扫描所有控件然后应用它们的代码是什么样的?我从来没有做过,我似乎找不到一个不是已经超级忙的例子来了解如何做。
任何人都有教程或代码 sn-p 或从我上面描述的控件构建入门,可以演示如何执行此操作?
更新:
好的,我添加了 DDX 变量:
void CSettingsUserTabs::DoDataExchange(CDataExchange* pDX)
CMFCPropertyPage::DoDataExchange(pDX);
DDX_Control(pDX, STYLE_3D_USER, m_style_3d);
DDX_Control(pDX, STYLE_FLAT_USER, m_style_flat);
DDX_Control(pDX, STYLE_FLAT_SHARED_HORZ_SCROLL_USER, m_style_flat_shared_h_scroll);
DDX_Control(pDX, STYLE_3D_SCROLLED_USER, m_style_3d_scroll);
DDX_Control(pDX, STYLE_3D_ONENOTE_USER, m_style_onenote);
DDX_Control(pDX, STYLE_3D_VS2005_USER, m_style_vs2005);
DDX_Control(pDX, STYLE_3D_ROUNDED_USER, m_style_3d_rounded);
DDX_Control(pDX, STYLE_3D_ROUNDED_SCROLL_USER, m_style_3d_rounded_scroll);
我的电台选择如下:
void CSettingsUserTabs::OnBnClicked3dUser()
//AfxGetMainWnd()->SendMessage(WM_COMMAND, STYLE_3D_USER);
UpdateData(TRUE);
void CSettingsUserTabs::OnBnClickedFlatUser()
// TODO: Add your control notification handler code here
//AfxGetMainWnd()->SendMessage(WM_COMMAND, STYLE_FLAT_USER);
UpdateData(TRUE);
..... and the rest of them....
所以对我来说,当我单击任何radio button
时,我希望它会扫描该属性页上的所有控件?如果是这样,所有变量都有值..我是否调用IsModified();
来启用apply
按钮...然后执行所有单选值,即只选择一个?是流量吗?
更新 2:
这就是我在MainFrame.cpp
中的模态对话框代码:
void CMainFrame::OnSettingsTools()
SettingsSheet SettingsSheet(L"Application Settings");
CSettingsPowerUser pgePowerUser;
CSettingsToolbars pgeToolbars;
CSettingsTheme pgeTheme;
CSettingsUserTabs pgeUserTabs;
CSettingsReset pgeReset;
SettingsSheet.AddPage(&pgeToolbars);
SettingsSheet.AddPage(&pgeTheme);
SettingsSheet.AddPage(&pgeUserTabs);
SettingsSheet.AddPage(&pgePowerUser);
SettingsSheet.AddPage(&pgeReset);
INT_PTR nRet = -1;
nRet = SettingsSheet.DoModal();
// Handle the return value from DoModal
switch (nRet)
case -1:
AfxMessageBox(_T("Dialog box could not be created!"));
break;
case IDABORT:
// Do something
AfxMessageBox(_T("ABORT!"));
break;
case IDOK:
// Do something
OnUserTabStyles(1);
AfxMessageBox(_T("OK!"));
break;
case IDCANCEL:
// Do something
AfxMessageBox(_T("CANCEL"));
break;
default:
// Do something
break;
;
验证SettingsTabs.cpp
中是否有任何单选按钮更改的例程:
void CSettingsUserTabs::OnTabRadioClicked(UINT nCmdID)
BOOL IsChecked = nCmdID;
CheckRadioButton(STYLE_3D_USER, STYLE_3D_ROUNDED_SCROLL_USER, nCmdID);
UpdateData(TRUE);
m_tabCmdID = nCmdID;
SetModified();
SettingsUserTabs.cpp 中的成员变量是什么样的:
void CSettingsUserTabs::DoDataExchange(CDataExchange* pDX)
CMFCPropertyPage::DoDataExchange(pDX);
DDX_Radio(pDX, STYLE_3D_USER, m_style_3d);
DDX_Radio(pDX, STYLE_FLAT_USER, m_style_flat);
DDX_Radio(pDX, STYLE_FLAT_SHARED_HORZ_SCROLL_USER, m_style_flat_h_scroll);
DDX_Radio(pDX, STYLE_3D_SCROLLED_USER, m_style_3d_scroll);
DDX_Radio(pDX, STYLE_3D_ONENOTE_USER, m_style_3d_onenote);
DDX_Radio(pDX, STYLE_3D_VS2005_USER, m_style_vs2005);
DDX_Radio(pDX, STYLE_3D_ROUNDED_USER, m_style_3d_rounded);
DDX_Radio(pDX, STYLE_3D_ROUNDED_SCROLL_USER, m_style_3d_rounded_scroll);
SettingsUserTabs.cpp 中构造函数的样子:
CSettingsUserTabs::CSettingsUserTabs()
: CMFCPropertyPage(IDD_SETTINGS_TABS)
, m_style_3d(FALSE)
, m_style_flat(FALSE)
, m_style_flat_h_scroll(FALSE)
, m_style_3d_scroll(FALSE)
, m_style_3d_onenote(FALSE)
, m_style_vs2005(FALSE)
, m_style_3d_rounded(FALSE)
, m_style_3d_rounded_scroll(FALSE)
, m_tabCmdID(FALSE)
我现在看到的这个问题是当我尝试使用成员变量m_tabCmdID
时,它又回到了unknown identifier
,所以我不确定为什么看不到成员变量。我期待像OnUserTabStyles(m_tabCmdID);
一样使用它,以便它将所选按钮的参数传递给方法OnUserTabStyles
。现在我只是在其中转储了一个1
以查看该机制是否有效。我只是不清楚如何从IDOK
的 SettingsUserTabs.cpp 访问成员变量。我错过了什么?
编辑:resource.h
中的选项范围为 200-207,这是我所知道的,我知道很多人不喜欢范围选项,因为它们可能会损坏......这是我的代码,所以我不用担心范围被弄乱了。
更新 3:
好的,所以我终于明白了康斯坦丁在以下帮助下描述的机制:
https://helgeklein.com/blog/2009/10/radio-buttons-in-mfc-visual-studio-2008-c/
我没有设置正确的 Tab 键顺序,也没有将组的第一个控件设置为 true。
有了这个,我现在在调试时得到按钮组中提到的值 0-7,因为我根据每个单选按钮在组中的位置从 0-7 (即 8 个按钮)单击它。这是代码现在的样子。
SettingsUserTabs.cpp
:
CSettingsUserTabs::CSettingsUserTabs()
: CMFCPropertyPage(IDD_SETTINGS_TABS)
, m_style_tabs(FALSE)
void CSettingsUserTabs::DoDataExchange(CDataExchange* pDX)
CMFCPropertyPage::DoDataExchange(pDX);
DDX_Radio(pDX, STYLE_3D_USER, m_style_tabs);
void CSettingsUserTabs::OnTabRadioClicked(UINT nCmdID)
UpdateData(TRUE);
BOOL RadioValueSelected = m_style_tabs; // only here to see 0-7 value for debugging only, not needed, test only
SetModified();
上面的mainframe.cpp
(更新2):void CMainFrame::OnSettingsTools()
还是一样。
所以现在我的问题还不清楚,我从mainframe.cpp
调用domodal
,成员变量m_style_tabs
在SettingsUserTabs.cpp
中。当我尝试访问成员变量时,当我尝试执行类似after
domodal int temp = m_styles_tabs;
的操作时,它会显示未知标识符。我在mainframe.cpp
中有一个这个
void CMainFrame::DoDataExchange(CDataExchange* pDX)
// TODO: Add your specialized code here and/or call the base class
CMDIFrameWndEx::DoDataExchange(pDX);
我希望该成员会出现在 mainframe.cpp
中,所以我可以在 domodal 之后处理它,这就是我认为的全部意义所在?
如何访问成员变量,以便对它执行OnApply
?我想我差不多明白了,我只是不清楚如何执行实际应用本身的最后几个步骤。
更新 4:
我询问重启的原因是当用户选择tabs
属性页并选择8 个选项中的1 个时,该选项存储在注册表中并在Oncreate
期间读取,然后使用该样式。因为它是OnCreate
,所以除了重新启动应用程序之外,我还没有找到“重绘”或使用新的tab
设置的方法。因此,通过执行 reg save > respawn > end old ...我希望对话框在同一个选项卡属性页上重新打开,以便用户可以看到如果选择了 apply
会发生什么变化...与。一些说“重新启动”的对话框..或其他。下面是用于演示它现在如何工作的代码。
OutputWnd.cpp
int COutputWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
if (CDockablePane::OnCreate(lpCreateStruct) == -1)
return -1;
CRect rectDummy;
rectDummy.SetRectEmpty();
// Create User Define tab style:
int UserTabStyle = AfxGetApp()->GetProfileInt(_T("Settings"), _T("UserTabStyle"), 0); //Get value from registry
// If the key doesn't exist, UserTableStyle will be 0 or FALSE;
if (UserTabStyle != FALSE && UserTabStyle <= 8) // User selected tab style type
int EnumUserTabStyle = UserTabStyle - 1; // Fix enum if key doesn't exist.
if (!m_wndTabs.Create(static_cast<CMFCTabCtrl::Style>(EnumUserTabStyle), rectDummy, this, 1))
TRACE0("Failed to create output tab window\n");
return -1; // fail to create
else // Default tabs style if Reg key does not exist i.e. new install/program reset
if (!m_wndTabs.Create(CMFCTabCtrl::STYLE_FLAT, rectDummy, this, 1))
TRACE0("Failed to create output tab window\n");
return -1; // fail to create
… rest of function....
更新 5:
这是来自SettingsUserTabs.cpp
的正在使用中的应用:
BOOL CSettingsUserTabs::OnApply()
// TODO: Add your specialized code here and/or call the base class
AfxGetApp()->WriteProfileInt(_T("Settings"), _T("UserTabStyle"), m_style_tabs); // Save value to registry
return CMFCPropertyPage::OnApply();
更新 6:
到目前为止一切正常,我遇到了一个障碍,试图应用这里和这个链接中的经验教训:
MFC MDI Substituting a class member dynamically
在本主题中所做的事情是用于出色工作的 OutputWnd 窗格!我的 MDI 打开一个文件并使用 CTabView 并使用更新 6 中显示的链接允许我在启动时更改选项卡。现在我已经让 OutputWnd 使用 OnApply
执行此操作,我正在尝试在加载文件时将其应用于文档视图。当我调用我在TrainView.cpp
中创建的新函数并从UserSettingsTabs.cpp
调用它时,我遇到了access violation
。我以为是static_cast
操作,但即使我使用GetControlTabs()
做一个简单的bold
也会崩溃(在注释掉的代码中显示,正在启动,现在在OnApply
中测试理论)。很明显,我需要捕获 MDI 文档,但不确定如何完成。我认为这很简单:
GetTabControl().ModifyTabStyle(static_cast<CMFCTabCtrl::Style>(EnumUserTabStyle));
但是当它因 Cx000000005 访问冲突而崩溃时,我知道我的结果有问题。我无法修改CTabView
操作,所以我想看看我们是否可以修复我做错的事情,让OnApply
更改标签样式而不像我们刚刚修复的OutputWnd 中所做的那样重新启动。
就目前而言,OnApply
正在运行,现在经过修改以尝试集成 CTabView 功能:
SettingsUserTabs.cpp
:
BOOL CSettingsUserTabs::OnApply()
BOOL bResult = CMFCPropertyPage::OnApply();
if (bResult)
AfxGetApp()->WriteProfileInt(_T("Settings"), _T("UserTabStyle"), m_style_tabs); // Save value to registry
((CMainFrame*)AfxGetMainWnd())->m_wndOutput.m_wndTabs.ModifyTabStyle((CMFCTabCtrl::Style)m_style_tabs);
((CMainFrame*)AfxGetMainWnd())->m_wndOutput.m_wndTabs.RecalcLayout();
CTrainView* TrainTabs; // User Call from anywhere method
TrainTabs->TrainDocUpdateTabsControl();
return bResult;
我添加了函数CTrainView::TrainDocUpdateTabsControl()
来更新标签...其余代码完全可以操作,即void CTrainView::OnInitialUpdate()
TrainView.cpp
:
IMPLEMENT_DYNCREATE(CTrainView, CTabView)
void CTrainView::OnInitialUpdate()
CMainFrame* pMainFrame = (CMainFrame*)AfxGetMainWnd();
pMainFrame->m_wndOutput.AddStringDebugTab(_T("Debug: TrainView--CTrainView::OnInitialUpdate()."));
// add views // cmb
AddView(RUNTIME_CLASS(CInformationView), AfxStringID(IDS_INFORMATION));
AddView(RUNTIME_CLASS(CChaptersView), AfxStringID(IDS_CHAPTERS));
// Nicely hack to access protected member
class CMFCTabCtrlEx : public CMFCTabCtrl
public:
void SetDisableScroll() m_bScroll = FALSE;
;
// One-Liner to Disable navigation control
((CMFCTabCtrlEx*)&GetTabControl())->SetDisableScroll();
GetTabControl().EnableTabSwap(TRUE);
GetTabControl().SetLocation(CMFCBaseTabCtrl::Location::LOCATION_BOTTOM);
//GetTabControl().SetActiveTabBoldFont(TRUE);
GetTabControl().EnableAutoColor(TRUE);
// Modify User Define tab style:
int UserTabStyle = AfxGetApp()->GetProfileInt(_T("Settings"), _T("UserTabStyle"), 0); //Get value from registry
// If the key doesn't exist, UserTableStyle will be 0 or FALSE;
if (UserTabStyle != FALSE && UserTabStyle <= 8) // User selected tab style type
int EnumUserTabStyle = UserTabStyle - 1; // Fix enum if key doesn't exist.
GetTabControl().ModifyTabStyle(static_cast<CMFCTabCtrl::Style>(EnumUserTabStyle));
else // Default tabs style if Reg key does not exist i.e. new install/program reset
GetTabControl().ModifyTabStyle(CMFCTabCtrl::STYLE_FLAT);
CTabView::OnInitialUpdate();
void CTrainView::TrainDocUpdateTabsControl()
CTabView::AssertValid();
GetTabControl().SetActiveTabBoldFont(TRUE); << CAUSES Cx000000005 ACCESS ERROR CRASH WHEN CALLED.
//int EnumUserTabStyle;
//int UserTabStyle = AfxGetApp()->GetProfileInt(_T("Settings"), _T("UserTabStyle"), 0); //Get value from registry
//((CMainFrame*)AfxGetMainWnd())->GetTabControl().ModifyTabStyle(static_cast<CMFCTabCtrl::Style>(EnumUserTabStyle));
更新 6 编辑:
tabview
是从 Application.cpp
创建的,如下所示:
//Load Train Template
m_pkDocTrainTemplate = new CMultiDocTemplate(
IDR_TRAIN, // Loads TRAIN operation
RUNTIME_CLASS(CTrainDoc),
RUNTIME_CLASS(CChildFrame),
RUNTIME_CLASS(CTrainView));
AddDocTemplate(m_pkDocTrainTemplate);
我试图投射m_pkDocTrainTemplate
,因为我认为那是指针?既然是MDI,不知道是不是索引问题,因为可以同时打开多个文档?
【问题讨论】:
我建议您使用DDX/DDV
功能来读取控件的值。您可以使用向导为每个控件添加适当类型的类变量(例如,用于编辑框的字符串、用于单选按钮的整数、用于复选框的布尔值等)并调用UpdateData(TRUE)
将控件内容读入变量中。这里不需要使用 Win32 函数(尽管你实际上可以)。该向导将添加 DDX/DDV 例程调用。 OnChange()
(EN_CHANGE
) 等事件可用于启用“应用”按钮。
我试试看....谢谢指点。
我已经更新了第一个帖子,它应该是这样的吗?
不,我不是那个意思,抱歉。您应该将对话框控件绑定到“Value”而不是“Control”变量(在“Category”组合中),因此这将生成 CString、int、BOOL 等变量而不是控件类型的变量,以及像 DDX_Check()
、@ 这样的函数987654409@ 或DDV_MaxChars()
。 DDV_
函数执行验证,例如 ints 的 min/max、stings 的最大长度等。UpdateData(TRUE)
通常在 OnOK()
事件中调用,并验证和复制所有控件的内容。在OnClicked()
或OnChange()
事件中,您应该只启用“应用”按钮。
不,这不行,您有一组 8 个单选按钮、8 个布尔变量和 8 个 DDX_Radio()
调用。相反,您应该有一个 int 变量,绑定到组中的第一个按钮,以及一个 DDX_Radio()
调用。该变量将获得值 0..7(-1 表示没有选择)。
【参考方案1】:
以下是我前段时间编写的应用程序示例。这是一个简单的“设置”对话框。与您的不同,这个来自CDialogEx
。但由于CPropertyDialog
是从CDialog
派生的,因此这些也适用于您的情况。
使用向导,我将成员变量添加到对话框类,绑定到对话框控件。在向导的“类别”组合中选择“值”,而不是“控制”。这些在类定义中声明。为简单起见,我只展示了三个。有一个 CString、一个 int 和一个 BOOL 变量,分别绑定到一个编辑、一个组合框(下拉列表)和一个复选框控件。
class CSettingsDlg : public CDialogEx
.
.
public:
CString m_DBConn;
int m_DumpSQL;
BOOL m_bLineNums;
在实现中,Wizard 修改了构造函数和DoDataExchange()
成员函数:
CSettingsDlg::CSettingsDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(CSettingsDlg::IDD, pParent)
, m_DBConn(_T(""))
, m_DumpSQL(0)
, m_bLineNums(FALSE)
void CSettingsDlg::DoDataExchange(CDataExchange* pDX)
CDialogEx::DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDIT_DBCONN, m_DBConn);
DDV_MaxChars(pDX, m_DBConn, 255);
DDX_CBIndex(pDX, IDC_COMBO_DUMPSQL, m_DumpSQL);
DDV_MinMaxInt(pDX, m_DumpSQL, 0, 2);
DDX_Check(pDX, IDC_CHECK_LINENUMS, m_bLineNums);
构造函数中的值是初始(默认)值。 DoDataExchange()
函数调用DDX/DDV
例程。 DDX 例程执行数据传输(控件变量),而 DDV 则执行验证 - 它们是可选的。 DoDataExchange()
函数由UpdateData()
调用。此外,OnOK()
的默认实现调用UpdateData(TRUE)
,如果成功则关闭对话框。
如果某些内容已被修改,您将需要启用“应用”按钮。您可以捕获通知消息,如EN_CHANGE
、EN_UPDATE
、BN_CLICKED
等(在属性编辑器中添加一个事件)并调用SetModified()
函数 - 这可能很乏味,但我看不到任何其他方式去做吧。
这样的对话框类可以在应用程序中使用,如下所示:
void CChildView::OnSetoptions()
// Create a Settings-dialog class instance
CSettingsDlg sd; // Main application window as parent - will block every UI item in the application
// Set initial values for the member variables
sd.m_DBConn = szDBconn;
sd.m_DumpSQL = nDumpSQL;
sd.m_bLineNums = bDumpLineNums;
if (sd.DoModal() == IDOK)
// Store the values entered by the user
lstrcpyn(szDBconn, sd.m_DBConn, MAX_PATH);
nDumpSQL = sd.m_DumpSQL;
bDumpLineNums = sd.m_bLineNums;
编辑:
我在上面的代码部分中有一个使用示例。该过程是创建对话框类的实例,设置成员变量的值(初始值,例如从注册表中读取),调用DoModal()
,如果成功将变量存储(复制)到其他地方(如果不丢弃它们)。这应该在某些事件处理程序中完成,例如 Update2 中的CMainFrame::OnSettingsTools()
。 CMainFrame::DoDataExchange()
覆盖没有意义。
您无法访问m_style_tabs
变量,这很奇怪。它不是CSettingsUserTabs
类的非静态公共成员吗?它应该在 SettingsUserTabs.h 中声明。如果您以pgeUserTabs.m_style_tabs
的身份访问它,它不会起作用吗?在CSettingsUserTabs
类函数中,它可以简单地作为m_style_tabs
访问。我还看到它在构造函数中被初始化为FALSE
。是BOOL
而不是int
? (顺便说一句,在 Win32 中 BOOL 被定义为 int,因此编译器不会抱怨)但是向导会为单选按钮生成一个 int 变量,还可以选择进行范围验证。
另外一点,您通常不需要在CSettingsUserTabs::OnTabRadioClicked()
中调用UpdateData(TRUE)
。请只留下SetModified()
电话。 UpdateData(TRUE)
通常在 OnOK()
函数中调用。而且通常你不需要覆盖这些,因为默认实现就足够了。 CPropertyPage documentation btw 提到 OnApply
的默认实现调用 OnOK
。
编辑 2:
在OnApply()
中,您应该首先检查验证是否成功。此外,OnCreate()
不是可以直接调用的“方法”。它应该被视为一个“事件”。它在创建窗口时由框架调用。你应该打电话给Create()
。在您的情况下,您可以销毁输出窗口并重新创建它(使用新样式)。但是,我看到CMFCTabCtrl
类有一个ModifyTabStyle()
函数,您可以尝试调用它(无需破坏窗口并再次创建它)。因此,您的代码将变为:
BOOL CSettingsUserTabs::OnApply()
BOOL bResult = CMFCPropertyPage::OnApply();
if (bResult)
AfxGetApp()->WriteProfileInt(_T("Settings"), _T("UserTabStyle"), m_style_tabs); // Save value to registry
((CMainFraime*)AfxGetMainWnd())->m_wndOutput.m_wndTabs.ModifyTabStyle((CMFCTabCtrl::Style)m_style_tabs);
return bResult;
上面的代码不会编译,因为m_wndOutput
和m_wndTabs
成员是受保护的。您必须将它们公开。
【讨论】:
感谢详细的例子,好在你之前提到的我能够申请并拥有与你的.h
3 项非常接近的东西。我有一些类似于constructor variables
(使用我的)的东西,而ddx data exchange
..all 看起来很相似(我会在进一步深入时发布)。我有一个case
结构来捕获我的radio buttons
。唯一的问题是,我没有IDOK()
或IDAPPLY()
,我假设我创建了它.. 其他事情,UpdateData()
在哪里被调用,在IDOK/IDAPPLY
之前......因为它不是t 显示在您的 sn-p 上。
对于单选按钮,WinAPI 确实没有提供任何特殊功能,只是获取每个按钮的检查状态。但是单选按钮组是一个“多选”类型的 UI 项(就像下拉列表组合一样),因此最好使用 int“状态”。 MFC 使用DDX_Radio()
例程为您执行此操作。它是向导生成的。您可以将一个 int 成员变量绑定到第一个单选按钮;它必须具有组样式集(其他不是)。跳位顺序也必须正确。测试您的对话框资源(Format->Test Dialog 或 Ctrl+T)以确保它工作正常。
一些澄清,没有IDOK()
函数。对话框通常有一个“确定”按钮,通常带有“默认”(BS_DEFPUSHBUTTON
) 样式集(捕获 ENTER 键),控件 ID 为IDOK
。单击此按钮将调用对话框的OnOK()
事件。默认(CDialog::OnOK()
)实现,正如我在帖子中描述的那样,调用UpdateData(TRUE)
,如果成功则关闭对话框。在我的情况下没关系,不需要覆盖。你可以在 MFC 源代码中找到这些东西,去 Edit->Find and Replace->Find in Files,你的文本,然后在“Look In”中选择 Visual C++ Source Directories
我在原帖中创建了更新 2,我认为我这样做的方式满足了您的关注。实际代码现在就在那里,因此您可以确切地看到我在做什么,我希望我正确地遵循了您的指导。
我得到了它的工作.. pgeUserTabs.m_style_tabs
是我的解决办法,我不清楚如何去做,这澄清了它。我有 apply
和 ok
函数工作。我将BOOL
转换为int
,从main 中转储ddx 交换并调整UpdateData(FALSE)
以在对话框打开并选择选项卡时更新控件。我确实有最后一个问题,选项卡更改需要重新启动应用程序,我很容易,在发送菜单命令以从菜单打开设置对话框后,如何激活“选项卡”列表链接?想对您的所有帮助表示感谢!以上是关于MFC MDI 收集“应用”按钮例程的控制状态的主要内容,如果未能解决你的问题,请参考以下文章