简体   繁体   English

MFC从对话框访问FormView项目

[英]mfc access to formview item from dialog box

In my SDI application i need to get this behawiour. 在我的SDI应用程序中,我需要了解这种行为。 After I click on a button on the FormView, a CDialog opens. 单击FormView上的按钮后,将打开一个CDialog。 When I press the OK button on the CDialog, I call a function of the FormView. 当我按下CDialog上的OK按钮时,我调用FormView的函数。 I don't want to close the CDialog. 我不想关闭CDialog。 I try to do it with modeless dialog, but when i call formview function from dialog, i can't access to formview's control, like it's lost hwnd; 我尝试使用无模式对话框来做到这一点,但是当我从对话框调用formview函数时,我无法访问formview的控件,就像它丢失了hwnd一样。 the error is can't read memory of m_hwnd, the hwnd is ???. 错误是无法读取m_hwnd的内存,而hwnd是???。 This is my code: Open modeless dialog: 这是我的代码:打开无模式对话框:

CCampiDlg *m_pDialog = NULL;
HWND hCampi = NULL;

// Invoking the Dialog
m_pDialog = new CCampiDlg;

if (m_pDialog != NULL)
{
    BOOL ret = m_pDialog->Create(m_pDialog->IDD, this);
    if (!ret)   //Create failed.
    {
        AfxMessageBox(_T("Error creating Dialog"));
    }
    m_pDialog->ShowWindow(SW_SHOW);
}

when i press the ok button in the dialog i do: 当我在对话框中按确定按钮时,我会执行以下操作:

CEditorTxView pView;
box2 = (CEdit*)(GetDlgItem(IDC_CAMPI_BOX2));
box2->GetWindowTextW(campo);
pView.inserisciCampo(1, campo);

In inserisciCampo function in CEditorTxView (CFormView) i have to do operation with my control txtCtrl, but it's lost hwnd. 在CEditorTxView(CFormView)的inserisciCampo函数中,我必须使用控件txtCtrl进行操作,但是丢失了hwnd。 The declaration of txtCtrl is in the CEditorTxView.h txtCtrl的声明在CEditorTxView.h中

CTx1 txtCtrl;

And initialize it in DoDataExchange function: 并在DoDataExchange函数中对其进行初始化:

void CEditorTxView::DoDataExchange(CDataExchange* pDX)
{
    CFormView::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_TX1, txtCtrl);
}

Someone can help me plz? 有人可以帮助我吗?

I can give you two answers here: 我可以在这里给您两个答案:

  1. How to do what you are asking (get access to a control of the CFormView from a modeless dialog) 如何执行您要问的事情(从无模式对话框访问CFormView控件)
  2. How to solve your underlying problem (communicate changes in a modeless dialog to the owner view) 如何解决您的基本问题(将无模式对话框中的更改传达给所有者视图)

For the first one, you have to declare a pointer to the view in the dialog class and initialize it in the constructor of the view: 对于第一个,您必须在对话框类中声明一个指向视图的指针,并在视图的构造函数中对其进行初始化:

class CCampiDlg : public CDialog
{
public:
    CCampiDlg(CEditorTxView* pView,  CWnd*pParent = NULL) // Change declaration to add pointer to view
    : m_pView(pView)
    {
    }
// ... Whatever
private:
    CEditorTxView* m_pView;
}

Now in your button handler: 现在在您的按钮处理程序中:

CEdit* box2 = (CEdit*)(GetDlgItem(IDC_CAMPI_BOX2)); // Why not use a control variable?
box2->GetWindowTextW(campo);
m_pView->inserisciCampo(1, campo);

This should do what you are asking for. 这应该可以满足您的要求。 However, it is the wrong way to do it . 但是, 这是错误的方法

The problem with this approach is that the dialog knows way too much about its parent. 这种方法的问题在于对话框对父级的了解太多。 It knows it is of type CEditorTxView and that it has a member called inserisciCampo , that takes a number and some text. 它知道它的类型为CEditorTxView ,并且有一个名为inserisciCampo的成员,该成员需要一个数字和一些文本。

It shouldn't know that much. 它不应该那么了解。 In fact, knowing anything about it, other than it is of type CView or even CWnd, is too much. 实际上,除了了解CView甚至CWnd类型之外,对此一无所知。

If the dialog knows about the view, you can't reuse the dialog with other views, and anytime the view changes its representation (what now is a textbox may be a combobox in the future, for example) the dialog must change accordingly. 如果对话框了解该视图,则不能将该对话框与其他视图一起使用,并且该视图每次更改其表示方式(例如,现在的文本框将来可能是组合框)时,对话框都必须进行相应的更改。

The solution would be to send a message to the parent, explaining what's happened. 解决方案是向父母发送消息,说明发生了什么。 Then the parent (the view) should know haw to handle that event. 然后,父级(视图)应该知道如何处理该事件。 For example: 例如:

class CCampiDlg : public CDialog
{
public:
    CCampiDlg(CWnd*pParent = NULL) {}
protected:
    OnOk()
    {
        CString campo;
        c_CampiBox2.GetWindowText(campo);
        GetParent()->SendMessage(UWM_CAMPO2_SET, 0, (LPARAM)&campo);
    }
}

In the view: 在视图中:

// It can be ON_REGISTERED_MESSAGE:
ON_MESSAGE(UWM_CAMPO2_SET, OnCampo2Set)

//...    

LRESULT CEditorTxView::OnCampo2Set(WPARAM, LPARAM lParam)
{
    CString* s = (CString*) lParam;
    inserisciCampo(1, *campo);
    return 0;
}

Now, you have decoupled the view and the dialog. 现在,您已经将视图和对话框解耦了。 The dialog knows nothing about the view. 对话框对视图一无所知。 You can change its type, change the representation, even make it a dialog, and you don't have to change anything in the dialog. 您可以更改其类型,更改表示形式,甚至使其成为对话框,而不必在对话框中进行任何更改。 And if you need that same modeless dialog somewhere else, you just drop it there, create a message handler in the parent, and voilà! 如果您在其他地方需要相同的无模式对话框,只需将其放到那里,在父级中创建一个消息处理程序,然后瞧瞧!

For further explanations and better examples, check these articles: 有关更多说明和更好的示例,请查看以下文章:

On Ok button click the below code is running: 在确定按钮上,单击下面的代码正在运行:

   CEditorTxView pView;
   box2 = (CEdit*)(GetDlgItem(IDC_CAMPI_BOX2));
   box2->GetWindowTextW(campo);
   pView.inserisciCampo(1, campo);

Note that, you are creating the new pView in stack and it does't attach with any window. 请注意,您正在堆栈中创建新的pView,它不与任何窗口连接。 You are not actually referring the view that already created and launched your dialog acting a parent. 您实际上并不是在引用已经创建并启动了充当父级对话框的视图。 Revisit the above code and try the get the view: 重新查看上面的代码并尝试获取视图:

Try the below code, if it is not working (Google it) 如果无法使用,请尝试以下代码(Google可以)

  CFrameWnd * pFrame = (CFrameWnd *)(AfxGetApp()->m_pMainWnd);
  CView * pView = pFrame->GetActiveView();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM