情况很简单,但我不太明白。
我有一个WinMFC应用程序,这也是解决方案项目的名称。我想将应用程序主对话框中的数据(WinMFCDialog.cpp + WinMFCDialog.h)传递到无模式自定义对话框(CustomDialog.cpp + CustomDialog.h)
Modeless 意味着 CustomDialog 作为一个单独的窗口运行,而不将焦点集中在自身上,因此我可以单独与 WinMFCDialog 交互。
以下是代码:
#pragma once
class CWinMFCDlg : public CDialogEx
{
public:
CWinMFCDlg(CWnd* pParent = NULL);
enum { IDD = IDD_WINMFC_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX);
protected:
HICON m_hIcon;
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnBnClickedButton1();
};
#include "stdafx.h"
#include "WinMFC.h"
#include "WinMFCDlg.h"
#include "afxdialogex.h"
#include "CustomDialog.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
class CAboutDlg : public CDialogEx
{
public:
CAboutDlg();
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX);
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()
CWinMFCDlg::CWinMFCDlg(CWnd* pParent /*=NULL*/):
CDialogEx(CWinMFCDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CWinMFCDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CWinMFCDlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON1, &CWinMFCDlg::OnBnClickedButton1)
END_MESSAGE_MAP()
BOOL CWinMFCDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
SetIcon(m_hIcon, TRUE);
SetIcon(m_hIcon, FALSE);
return TRUE;
}
void CWinMFCDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialogEx::OnSysCommand(nID, lParam);
}
}
void CWinMFCDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this);
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Нарисуйте значок
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
HCURSOR CWinMFCDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CWinMFCDlg::OnBnClickedButton1()
{
// Modeless dialog, in which I want to pass the data
CustomDialog *pDlg = new CustomDialog();
pDlg->Create(IDD_CUSTOM_DIALOG, this);
pDlg->ShowWindow(SW_SHOW);
}
#pragma once
class CustomDialog : public CDialog
{
DECLARE_DYNAMIC(CustomDialog)
public:
CustomDialog(CWnd* pParent = NULL);
virtual ~CustomDialog();
enum { IDD = IDD_CUSTOM_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX);
DECLARE_MESSAGE_MAP()
};
#include "stdafx.h"
#include "WinMFC.h"
#include "CustomDialog.h"
#include "afxdialogex.h"
IMPLEMENT_DYNAMIC(CustomDialog, CDialog)
CustomDialog::CustomDialog(CWnd* pParent /*=NULL*/)
: CDialog(CustomDialog::IDD, pParent)
{
}
CustomDialog::~CustomDialog()
{
}
void CustomDialog::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CustomDialog, CDialog)
END_MESSAGE_MAP()
#pragma once
#ifndef __AFXWIN_H__
#error "включить stdafx.h до включения этого файла в PCH"
#endif
#include "resource.h"
class CWinMFCApp : public CWinApp
{
public:
CWinMFCApp();
public:
virtual BOOL InitInstance();
DECLARE_MESSAGE_MAP()
};
extern CWinMFCApp theApp;
#include "stdafx.h"
#include "WinMFC.h"
#include "WinMFCDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CWinMFCApp
BEGIN_MESSAGE_MAP(CWinMFCApp, CWinApp)
ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
END_MESSAGE_MAP()
// Craetion of CWinMFCApp
CWinMFCApp::CWinMFCApp()
{
m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART;
}
// Single object CWinMFCApp
CWinMFCApp theApp;
// Initialization of CWinMFCApp
BOOL CWinMFCApp::InitInstance()
{
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwSize = sizeof(InitCtrls);
InitCtrls.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&InitCtrls);
CWinApp::InitInstance();
AfxEnableControlContainer();
CShellManager *pShellManager = new CShellManager;
SetRegistryKey(_T("Test MFC APP"));
CWinMFCDlg dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
}
else if (nResponse == IDCANCEL)
{
}
if (pShellManager != NULL)
{
delete pShellManager;
}
return FALSE;
}
我将数据输入到在 WinMFCDlg 中创建的编辑框中:
数据应显示在 CustomDialog 之后的静态字段元素中:
因此,我尝试使用 DDX/DDV 函数将 WinMFC 对话框的编辑文本中的数据传递到自定义对话框的静态文本字段中。
这就是我尝试做的:
void DDX_TextNotEmpty (CDataExchange* pDX, int nIDC, CString& value);
class CWinMFCApp : public CWinApp
{
// Class definition
}
void DDX_TextNotEmpty (CDataExchange* pDX, int nIDC, CString& value)
{
HWND hWndCtrl = pDX->PrepareEditCtrl(nIDC);
if (pDX->m_bSaveAndValidate)
{
int nLen = ::GetWindowTextLength(hWndCtrl);
::GetWindowText(hWndCtrl, value.GetBufferSetLength(nLen), nLen+1);
value.ReleaseBuffer();
if (value.IsEmpty ())
{
AfxMessageBox (_T("Enter something in the text field."), MB_ICONSTOP);
pDX->Fail (); //Fail () sets the focus on to the edit control
}
}
else { ::SetWindowText(hWndCtrl, value); }
}
class CustomDialog : public CDialog
{
DECLARE_DYNAMIC(CustomDialog)
public:
CString m_string;
CustomDialog(CWnd* pParent = NULL);
// ... Default stuff created by VS2010 ...
}
CustomDialog::CustomDialog(CWnd* pParent /*=NULL*/)
: CDialog(CustomDialog::IDD, pParent), m_string(_T("default value"))
{
}
void CustomDialog::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_TextNotEmpty(pDX, IDC_EDIT_DATA, m_string);
}
最后我收到一个错误:
好吧,我不知道我到底做错了什么,所以我希望我的问题不是太愚蠢或问起来很烦人,我只是想学习如何使用这个古老但有趣的东西😔。
很高兴获得任何帮助。
将数据传递到 MFC 对话框的最简单方法是作为数据成员,在构造函数调用之后设置,当然在
Create()
或 DoModal()
调用之前设置。您可以选择将数据副本或对父对话框、文档或应用程序维护的数据的引用(例如指针)传递给父对话框、文档或应用程序。关闭时(在 OnOK()
或 OnCancel()
调用之后),您可以将成员变量中的数据复制回父级(在析构函数调用之前)。大多数 DDX/DDV 示例都是这样做的。例如:
COptionsDialog dlg; // Constructor
dlg.m_DataDir = m_Options.sDataDir; // Pass Data to the dialog class
if (dlg.DoModal()==IDOK) // Display the dialog
{
m_Options.sDataDir = dlg.m_DataDir; // Copy modified data back to the parent
}
您面临的问题可能与为不可编辑的控件(静态文本)调用
PrepareEditCtrl()
有关。尝试使用 PrepareCtrl()
代替。或者将 DDX_TextNotEmpty()
调用替换为简单的 DDX_Text()
调用,无需验证 (DDV_()
);系统如何“验证”来自不允许用户输入的控件的输入?
附注,在完成后,您应该销毁
CustomDialog
类的实例(您使用 new
创建了它)。
...好吧,这就是我想出来的...
问题是我在对话框中调用 DDX_TextNotEmpty(pDX, IDC_EDIT_DATA, m_string) ,该对话框尚未创建(在我的例子中是在 CustomDialog 中)。另外,我也用错了😄。这个函数就像Android开发中的绑定。我的意思是,当 UI 中变量 (m_string) 发生更改时,它会更新变量 (m_string)。但是,感谢 Constantine Georgiou, 有一个内置的 DDX_Text,所以不需要在 WinMFCDlg.cpp 中使用该函数。 所以现在看起来像这样:
void CWinMFCDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDIT_DATA, m_string);
}
因此,为了将数据传递到模式中,我需要将字符串放入模式对话框中的静态文本元素内,这是通过按下 WinMFCDlg 中的按钮来完成的,同时也从 UI 更新它。为了保留唯一的一个模式对话框而不是多次打开它,我将 CustomDialog 添加为 WinMFCDlg 类中的一个字段:
class CWinMFCDlg : public CDialogEx
{
public:
CustomDialog* m_ptrDialog;
// Don't forget to delete it
virtual ~CWinMFCDlg(){ delete m_ptrDialog; }
// Other stuff...
}
在 WinMFCDlg.cpp 中的 BOOL CWinMFCDlg::OnInitDialog() 中初始化指针后,如下所示:
m_ptrDialog = new CustomDialog();
m_ptrDialog->Create(IDD_CUSTOM_DIALOG, this);
最后,为了将我的数据放入模式对话框中,我只需按 WinMFCDlg 中的按钮即可:
void CWinMFCDlg::OnBnClickedButton1()
{
UpdateData(TRUE);
// Modeless dialog
m_ptrDialog->SetDlgItemTextW(IDC_STATIC, m_string);
m_ptrDialog->ShowWindow(SW_SHOW);
}
...并查看结果:这就是我想要的! 但不是以我想要的方式...好吧,如果我想出这个“自动更新我想要得到”,我会在这里添加解决方案😊。
感谢您的精神支持和建议。