C++ 在MFC编辑框中单击

C++ 在MFC编辑框中单击,c++,windows,mfc,C++,Windows,Mfc,我在MFC对话框中创建了一个只读编辑框。我试图让它这样一个用户点击编辑框,这是只读的,它打开一个文件对话框,然后把这个值到文本框使用UpdateData。我正在捕获设置焦点上的消息,但在文件对话框上按OK会使其重新启动,因此我陷入无限循环 UpdateData(TRUE); CFileDialog fileDialog(TRUE,NULL, NULL,OFN_HIDEREADONLY|OFN_FILEMUSTEXIST, _T("Text Files(*.txt)|*.txt||")); if(

我在MFC对话框中创建了一个只读编辑框。我试图让它这样一个用户点击编辑框,这是只读的,它打开一个文件对话框,然后把这个值到文本框使用UpdateData。我正在捕获设置焦点上的
消息,但在文件对话框上按OK会使其重新启动,因此我陷入无限循环

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

如果您对如何执行此操作有任何想法,我将不胜感激。

您可以在dialog类中重写
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派生一个类

好的,李斯特先生,我想我会补充一个答案

首先,我会在前面加上一个按钮名“…”来启动编辑框右侧的文件对话框,以打开文件对话框,因为这是最简单的解决方案,也是大多数windows用户所期望的

然而,另一个选择是扩展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
来调整按钮大小以适应文件标题,以确保名称合适,或者在他们将鼠标悬停在按钮上时只显示
CTOLTIPCTRL
,以便他们可以看到全名。VS2008+中MFC功能包中的
CMFCButton
内置了工具提示功能,因此如果从该功能继承而不是
CButton
显示工具提示,只需调用
设置工具提示(m_路径)


如果您想真正喜欢,可以使用一些或新的。

如果您使用的是VS2008 SP1或更高版本,请求路径的最简单方法是使用。它显示一个带有按钮的编辑控件。使用它的步骤如下:

  • 将编辑控件的类更改为CMFCEditBrowseCtrl
  • 调用EnableFileBrowseButton告诉它您想浏览文件,而不是文件夹(您可以设置过滤器和默认扩展名)
  • 当用户单击按钮时,将显示一个文件对话框,当您在其中单击“确定”时,所选路径将写入编辑控件

为什么不使用按钮?一个名为
..
的小
CButton
按钮可以通过文件对话框进行浏览,这是非常常见的。如果您想在对话框中获得一些可用性,请使用AJG85的建议。没有用户会点击只读的CEdit框。这样做了,而且它工作了,只是有两个控件似乎是无关的,并且想知道是否有更有效的方法这样做?这取决于你所说的有效。需要更多的消息处理程序和一些if语句检查,GUI用户实现当前设计的直观性会降低。@James-Windows应用程序的用户希望看到“…”按钮,他们知道如何使用它(以前多次看到过)。他们不希望单击该框会弹出“文件打开”对话框。除非您确实必须这样做,否则不建议覆盖预翻译消息,但这会起作用。@AJG85:为什么不建议这样做?只要遵循约定,我看不出有任何问题。PreTranslateMessage可以在发送消息到达之前更改它们。在那里处理一切都很诱人,因为在处理之前可以检查每一条消息,但这可能会导致可读性较差的代码更容易出错,更难调试。任何时候,当您在预翻译消息中检查ID或HWND时,这就是您的提示,您应该在其他地方处理该消息。正如您所说,在这种情况下,从CEdit派生并使用自定义行为扩展它可能会更好。@AJG85:我明白您的观点,但是从CEdit派生时,
PreTranslateMessage
的实现方式不会与从CEdit派生时相同吗?i、 例如,CEdit控件没有OnClick通知/消息,因此需要覆盖
PreTranslateMessage
。我不想干预与我无关的事情,但@AJG85听起来您想添加自己的答案。+1是最佳答案。我不知道功能包中有这个MFC类扩展。