0

私の SDI アプリケーションでは、この動作を取得する必要があります。FormView のボタンをクリックすると、CDialog が開きます。CDialog の [OK] ボタンを押すと、FormView の関数が呼び出されます。CDialog を閉じたくありません。モードレス ダイアログで実行しようとしましたが、ダイアログから formview 関数を呼び出すと、hwnd が失われたように、formview のコントロールにアクセスできません。エラーは 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);
}

ダイアログで[OK]ボタンを押すと、次のようになります。

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

ここで2つの答えをあげることができます:

  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 を作成していて、どのウィンドウにもアタッチされていないことに注意してください。親として機能するダイアログを既に作成して起動したビューを実際に参照しているわけではありません。上記のコードに戻って、ビューを取得してみてください。

機能しない場合は、以下のコードを試してください(Google it)

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