0

在我的 SDI 应用程序中,我需要获得这种行为。单击 FormView 上的按钮后,将打开一个 CDialog。当我按下 CDialog 上的 OK 按钮时,我调用了 FormView 的一个函数。我不想关闭 CDialog。我尝试用无模式对话框来做,但是当我从对话框中调用 formview 函数时,我无法访问 formview 的控件,就像它丢失了 hwnd 一样;错误是无法读取 m_hwnd 的内存,hwnd 是???。这是我的代码:打开无模式对话框:

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);
}

当我在对话框中按下确定按钮时,我会:

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

在 CEditorTxView (CFormView) 的 inserisciCampo 函数中,我必须使用我的控件 txtCtrl 进行操作,但它丢失了 hwnd。txtCtrl 的声明在 CEditorTxView.h

CTx1 txtCtrl;

并在 DoDataExchange 函数中对其进行初始化:

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

有人可以帮助我吗?

4

2 回答 2

3

我可以在这里给你两个答案:

  1. 如何做你所问的(从无模式对话框中访问 CFormView 的控件)
  2. 如何解决您的潜在问题(在无模式对话框中将更改传达给所有者视图)

对于第一个,您必须在对话框类中声明一个指向视图的指针,并在视图的构造函数中对其进行初始化:

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;
}

现在在您的按钮处理程序中:

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

这应该可以满足您的要求。但是,这样做是错误的

这种方法的问题是对话框对其父级了解太多。它知道它是类型CEditorTxView,并且它有一个名为 的成员inserisciCampo,它接受一个数字和一些文本。

它不应该知道那么多。事实上,除了它是 CView 甚至 CWnd 类型之外,对它的任何了解都太多了。

如果对话框知道视图,则不能将对话框与其他视图重用,并且任何时候视图更改其表示形式(例如,现在是文本框可能是将来的组合框)对话框都必须相应更改。

解决方案是向父母发送一条消息,解释发生了什么。然后父级(视图)应该知道如何处理该事件。例如:

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);
    }
}

在视图中:

// 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;
}

现在,您已经解耦了视图和对话框。对话框对视图一无所知。您可以更改其类型、更改表示形式,甚至将其设为对话框,而无需更改对话框中的任何内容。如果你在其他地方需要同样的无模式对话框,你只需把它放在那里,在父级中创建一个消息处理程序,瞧!

有关进一步的解释和更好的示例,请查看以下文章:

于 2012-10-15T10:17:40.843 回答
0

在 Ok 按钮上单击以下代码正在运行:

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

请注意,您正在堆栈中创建新的 pView 并且它不附加任何窗口。您实际上并没有指代已经创建并启动您的对话框作为父级的视图。重新访问上面的代码并尝试获取视图:

试试下面的代码,如果它不起作用(谷歌它)

  CFrameWnd * pFrame = (CFrameWnd *)(AfxGetApp()->m_pMainWnd);
  CView * pView = pFrame->GetActiveView();
于 2012-10-15T10:09:59.963 回答