2012-07-19 48 views
4

我在MFC對話框中創建了一個只讀編輯框。我試圖讓它使用戶點擊編輯框,它是隻讀的,它打開一個文件對話框,然後使用UpdateData將該值放入文本框中。我正在捕獲ON_EN_SETFOCUS消息,但在文件對話框上按下「確定」重新生成它,所以我陷入了無限循環。單擊MFC編輯框

UpdateData(TRUE); 
CFileDialog fileDialog(TRUE,NULL, NULL,OFN_HIDEREADONLY|OFN_FILEMUSTEXIST, _T("Text Files(*.txt)|*.txt||")); 
if(fileDialog.DoModal() == IDOK) 
{ 
    configFile=fileDialog.GetPathName(); //Note to self, this includes filename, getPathName includes filename and path. 

} 
else 
{ 
    return; 
} 

UpdateData(FALSE); 

如果您對如何完成這件事有任何想法,我將非常感激。

+2

爲什麼不使用按鈕?一個名爲'...'的小CButton用文件對話框瀏覽是很常見的。 – AJG85 2012-07-19 16:26:50

+0

如果您希望在對話框中使用某些可用性,請使用AJG85的建議。沒有用戶會永遠點擊一個只讀的CEdit框。 – CppChris 2012-07-19 16:41:06

+0

做到了這一點,它的工作,有兩個控制似乎是無關的,並想知道是否有一個更有效的方法來做到這一點? – James 2012-07-19 16:42:55

回答

3

好的李斯特先生我想我會添加一個答案。

首先,我會在此前面介紹一下,我可能只是簡單地添加一個按鈕名稱「...」來啓動文件對話框,在編輯框右側打開文件對話框,因爲這是最簡單的解決方案,用戶會期待。

但是,另一種選擇是擴展MFC控件。當決定擴展一個控件時,你希望選擇一個主要具有所需行爲的控件,並且該控件具有一個虛擬析構函數,該虛擬析構函數可以作爲子類。既然你想按鈕行爲CButton可能是一個不錯的選擇。

你的類接口可能是這個樣子:

class CPathButton : public CButton 
{ 
public: 
    enum { ID /*= IDC_BUTTON1*/ }; 

    const CString GetPath() const; 
    const CString GetFileName() const; 
    const CString GetDirectory() const; 
    const CString GetExtension() const; 
    // other useful methods for setting file filters etc 

protected: 
    // add ON_CONTROL(BN_CLICKED, ID, &OnClick) or ON_BN_CLICKED(ID, &OnClick) 
    DECLARE_MESSAGE_MAP() 

    // CFileDialog fdlg.DoModal(), m_path = fdlg.GetPathName(), SetWindowText(fdlg.GetFileTitle()), etc 
    afx_msg void OnClick(); 

    // additional message handlers etc 

private: 
    CString m_path; // save full path for after dialog is closed 
}; 

,你依靠,如果控制將動態創建想,你可以添加任意多或儘可能少的定製,通過資源文件,或什麼的。其基本思想是在按鈕上顯示當前選定的文件名,同時將其他用途的完整路徑存儲爲成員,這樣用戶就不需要看到具有嵌套目錄的長路徑的混亂。

如果您不喜歡默認情況下的顯示方式,則可以覆蓋OnPaint並處理WM_PAINT消息,併爲長文件標題使用自定義字體,大小或添加省略號。您也可以通過使用文本指標和GetTextExtent來處理重新調整按鈕的大小以適合文件標題,以確保該名稱符合或僅當顯示CToolTipCtrl時將鼠標懸停在按鈕上方,以便他們可以看到全名。從VS2008 + MFC的功能包的CMFCButton具有內置的,所以如果你的而不是CButton繼承中顯示工具提示會是這麼簡單調用SetTooltip(m_path)

如果你想獲得真正看中的,你可以使用一些工具提示功能的uxtheme API或新的windows animation API

1

您可以在對話框類中重寫PreTranslateMessage(),並確定編輯控件被點擊的方式:

CEdit m_CEditCtrl; 
// ... 

BOOL YourDialogClass::PreTranslateMessage(MSG *pMsg) 
{ 
    if((pMsg->wParam == VK_LBUTTON) && (m_CEditCtrl.m_hWnd == pMsg->hwnd)) 
    { 
     // open your file dialog 
     return TRUE; // Return that the message was translated and doesn't need to be dispatched 
    } 
    return CDialog::PreTranslateMessage(pMsg); 
} 

更新:你也可以(並且它可能是一個更好的主意)來覆蓋你的CEdit控件的CWnd::PreTranslateMessage()函數。這需要從CEdit派生一個類。

+1

不推薦重寫PreTranslateMessage,除非你真的必須這樣做。 – AJG85 2012-07-19 16:59:23

+0

@ AJG85:爲什麼不推薦?只要遵循慣例,我就不會看到任何問題。 – 2012-07-19 17:01:18

+0

PreTranslateMessage可以在派送消息到達之前更改它們。在處理所有消息之前,處理所有消息都很誘人,但是這會導致可讀性較差的代碼容易出錯並且難以調試。任何時候你在PreTranslateMessage中檢查id或hwnds是你的提示,你應該在別處處理消息。正如你所說的源自CEdit並將其擴展到自定義行爲在這種情況下可能會更好。 – AJG85 2012-07-19 17:31:19

1

如果您使用的是VS2008 SP1或更高版本,請求路徑的最簡單方法是使用CMFCEditBrowseCtrl。它顯示一個帶有按鈕的編輯控件。使用它的步驟是:

  • 更改您的編輯控件的類CMFCEditBrowseCtrl
  • 呼叫EnableFileBrowseButton告訴它你想瀏覽的文件,而不是文件夾(你可以設置一個過濾器,默認擴展名)
  • 當用戶單擊該按鈕時,將出現一個文件對話框,並在其中單擊確定時,所選路徑將寫入編輯控件中。
+0

+1爲最佳答案。我沒有意識到該功能包中的MFC類擴展。 – AJG85 2012-07-23 16:51:43