簡體   English   中英

MFC:子對話框行為

[英]MFC: child dialog behavior

我試圖將我的子對話框創建為主應用程序類的成員,如下所示:

class ParentWindow : public CWinApp
{
public:
    // Other MFC and user-implemented classes before this line
    MiscSettings    activeMiscSettings;

public:
    ParentWindow();
    ~ParentWindow();

// Overrides
    virtual BOOL InitInstance();

// Implementation
    afx_msg void OnAppAbout();
    afx_msg void OnMiscSettingsPrompt();
    DECLARE_MESSAGE_MAP()
};

我想讓MiscSettings描述的對話框在程序啟動時實例化,在程序退出時銷毀,並根據用戶選擇特定菜單選項還是用戶單擊“確定”或顯示/隱藏來顯示/隱藏對話框的“取消”按鈕。 但是,當我實現OnMiscSettingsPrompt()處理函數時,如下所示:

void ParentWindow::OnMiscSettingsPrompt()
{
    float temp;
    INT_PTR status = activeMiscSettings.DoModal();
    switch(status)
    {
    case IDOK:
        temp = activeMiscSettings.GetSpeed();
        break;
    case IDCANCEL:
    default:
        break;
    }
}

我無法訪問activeMiscSettings.GetSpeed()方法b / c,在調用DoModal()之后,該句柄無效。 在顯示子對話框時,我使用了與其他示例類似的方法。 但是,activeMiscSettings的內容不能由ParentWindow類訪問。 我知道我可以將處理程序放在MiscSettings類中,以將內容正確地轉移到編輯控件和其他用戶控件設置的“確定”按鈕處理程序中,並傳遞到應用程序其余部分的適當類內容。 此時,我不確定將子彈出對話框上的設置轉移到應用程序其余部分的最干凈的方法是什么。

我正在嘗試實現的另一個規范是雜項。 設置彈出對話框,用於在用戶首次選擇菜單選項時首次顯示預配置的設置。 更改某些設置並按OK后,如果用戶再次打開設置窗口,我希望在用戶控件中顯示當前設置,而不是顯示以前在第一個實例中看到的預先配置的設置。 這是一個容易實現的目標嗎?

預先感謝您的評論。

盡管有點奇怪,但是您可以通過無模式對話框實現所需的功能:-在ParentWindow.OnCreate調用對話框Create 將ParentWindow作為父級傳遞-需要隱式創建對話框,IIRC需要重寫CMyDialog::PreCreateWindow打開對話框,請使用dlg.ShowWindow(SW_SHOW)parent.EnableWindow(false) -要關閉,請使用dlg.ShowWindow(SW_HIDE)parent.EnableWindow(true)

但是,我建議不要這樣做。

  • 它甚至沒有嘗試將視圖與控制器分開,但這可能是可以原諒的。
  • 它將對話框綁定到一個父對話框,即無法從另一窗口顯示它。
  • 不允許正確實施“取消”
  • 最后一點,它感覺很奇怪-可能是代碼氣味或味道問題。

這就是我認為的“正常”情況:

我所有的設置對話框都與Settings類相關聯,並最終遵循以下大致界面:

class CSettings
{
   double speed;
   EDirection direction;
   bool hasSpeedStripes;

   bool IsValid(CString & diagnostics);
};

class CSettingsDialog
{
   CSettings m_currentSettings;
public:
   // that's the method to call!
   bool Edit(CWnd * parent, CSettings & settings)
   {
      m_currentSettings = settings; // create copy for modification
      if (DoModal(parent) != IDOK)
        return false;
      settings = m_currentSettings;
      return true;
   }

   OnInitDialog()
   {
     // copy m_cuirrentSettings to user controls
   }

   OnOK()
   {
     // copy user controls to m_currentSettings
     CString diagnostics;
     if (!m_currentSettings.IsValid(diagnostics))
     {
       MessageBox(diagnostics); // or rather, a non-modal error display
       return;
     }
     EndDialog(IDOK);
   }
};

該副本是驗證所必需的。 我再次將設置類用於“ currentSettings”,因為我不太喜歡MFC的DDX / UpdateData()機制,並且經常手動進行傳輸。

但是,如果您遵循MFC的想法,您將

  • 使用類向導將控件映射到數據成員,您可以在其中進行基本范圍驗證
  • 在OnInitDialog中,將設置復制到數據成員並調用UpdateData(false)
  • 在OnOK中,調用UpdateData(true),然后“返回”數據成員。

您甚至可以手動編輯DoDataExchange以將控件直接映射到m_currentSettings成員,但這並不總是有效。


由於用戶可能會更改值,請檢查副本中的值是否不正確,然后再按“取消”鍵,並希望保留原始值,因此應該在副本上進行相互依賴性驗證。 例:

if (speed < 17 && hasSpeedStripes)
{
   diagnsotics = "You are to slow to wear speed stripes!";
   return false;
}

驗證應該與對話框類分開(盡管可能會爭辯說,生成診斷也不屬於設置類,在這種情況下,您確實需要第三個“控制器”實體。盡管我通常不這樣做)

至於在DoModal調用之后句柄無效,可能是GetSpeed方法正在嘗試訪問控制變量。 這不是關閉對話框本身的無效句柄,而是包含速度值的子控件。

如果將“速度”值復制到OnOK中的非控制成員,則在關閉模式對話框后,您的代碼即可訪問其值。

您應該放棄在啟動時創建對話框並隱藏/顯示對話框的想法。 這僅適用於無模式對話框。 您可以無模式地創建它,然后模擬模態行為,但這是繁瑣的工作。

我假設您要顯示/隱藏對話框,因為那樣會在整個應用程序中保留設置,並且您想使用該對話框將設置存儲在其中。您應該將對話框與設置本身分開。 創建一個僅包含設置而不從CDialog派生的類。 然后,使對話框填充該類的字段。 將設置對象存儲在CWinApp派生類中,並在每次要顯示它時創建一個Now對話框(使用.DoModal)。

(再次閱讀其他答案,這可能是彼得興所說的話)

從它的聲音來看,您需要一個無模式對話框,您可以通過從對話框派生來創建該對話框。

您可以像上面一樣在應用中聲明它,並在閑暇時創建/銷毀。 如果您將其稱為模式對話框,則將阻止應用程序的其余部分,盡管在描述您的需求時聽起來像不是您想要的模式行為,例如

並根據用戶是否選擇特定菜單選項顯示/隱藏

我最終決定創建一個結構,該結構包含要在父對話框類的子對話框中配置的設置,在調用構造函數時傳遞指向該結構的指針,並讓子對話框的OK按鈕處理程序將其內容修改為它是一個指針。 我認為這很干凈,因為我現在可以執行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM