【问题标题】:mfc access to formview item from dialog boxmfc 从对话框访问 formview 项
【发布时间】:2012-10-15 09:34:30
【问题描述】:

在我的 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);
}

有人可以帮帮我吗?

【问题讨论】:

    标签: c++ mfc


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 我尝试了您的解决方案,但如果我使用 GetParent()->SendMessage(UWM_CAMPO2_SET, 0, (LPARAM)&campo),则不会发送消息。在 CDialog 类中,我创建了一个变量 CWnd *pView,并将其设置为父级。我将它用于 SendMessage 并且工作正常。对吗?
    • 其实我就是这么干的。事实上,我认为 GetParent() 解决方案是通用的解决方案(对于任何类型的控件)。但是无模式对话框通常使用 NULL 作为父级创建,它将主窗口设置为父级,而不是视图。这可能就是您没有在视图中收到消息的原因。
    【解决方案2】:

    点击确定按钮,下面的代码正在运行:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-04-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-29
      • 1970-01-01
      • 2011-03-16
      相关资源
      最近更新 更多