在 MFC 编辑框中单击

Posted

技术标签:

【中文标题】在 MFC 编辑框中单击【英文标题】:Clicking in an MFC edit box 【发布时间】:2012-07-19 16:21:47 【问题描述】:

我在 MFC 对话框中创建了一个只读编辑框。我试图让用户点击编辑框,它是只读的,它打开一个文件对话框,然后使用 UpdateData 将此值放入文本框中。我收到了 ON_EN_SETFOCUS 消息,但在文件对话框上按 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);

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

【问题讨论】:

为什么不使用按钮?一个名为... 的小CButton 用于通过文件对话框进行浏览非常常见。 如果您希望对话有一些可用性,请使用 AJG85 的建议。没有用户会点击只读的 CEdit 框。 完成了,它工作了,只是有两个控件似乎无关紧要,想知道是否有更有效的方法? 这取决于您所说的高效。这将需要更多的消息处理程序和一些 if 语句检查,并且对 GUI 用户来说不太直观来实现您当前的设计。 @James - Windows 应用程序的用户希望看到那个“...”按钮,他们知道如何处理它(之前已经看过很多次了)。他们不会期望单击该框会弹出文件打开对话框。 【参考方案1】:

好的,Lister 先生,我想我会添加一个答案。

首先,我可能会简单地添加一个按钮名称“...”以在编辑框右侧启动文件对话框以打开文件对话框,因为这是最简单的解决方案,也是大多数 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 来调整按钮大小以适应文件标题以确保名称适合,或者当他们将鼠标悬停在按钮上时仅显示CToolTipCtrl 以便他们可以看到全名。 VS2008+ 中的 MFC 功能包中的 CMFCButton 具有内置的工具提示功能,因此如果您从该功能继承而不是 CButton 显示工具提示将像调用 SetTooltip(m_path) 一样简单

如果你想变得更花哨,你可以使用一些uxtheme API 或新的windows animation API。

【讨论】:

【参考方案2】:

您可以在对话框类中覆盖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 派生一个类。

【讨论】:

不建议覆盖 PreTranslateMessage,除非你真的必须这样做,但这会起作用。 @AJG85:为什么不推荐?只要遵守约定,我看不出有什么问题。 PreTranslateMessage 可以在调度消息到达之前更改它们。在那里处理所有内容很诱人,因为您可以在处理之前检查每条和所有消息,但这会导致代码可读性降低,容易出错且更难调试。任何时候您在 PreTranslateMessage 中检查 ids 或 hwnds 都是您的提示,您应该在其他地方处理该消息。正如您所说,在这种情况下,从 CEdit 派生并使用自定义行为对其进行扩展可能会更好。 @AJG85:我明白你的意思,但是PreTranslateMessage 在从 CEdit 派生时不会以同样的方式实现吗?即,CEdit 控件没有 OnClick 通知/消息,因此需要覆盖 PreTranslateMessage 我不想干涉与我无关的事情,但@AJG85 你听起来像是想添加自己的答案。【参考方案3】:

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

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

【讨论】:

+1 以获得最佳答案。我不知道功能包中有这个 MFC 类扩展。

以上是关于在 MFC 编辑框中单击的主要内容,如果未能解决你的问题,请参考以下文章

mfc如何将一个编辑框中的数字追加到另一个编辑框,不是覆盖,而是接在原来的后面显示?

MFC编辑框关联的变量怎么用UpdateData(FALSE)无法直接写到编辑框中啊,而是需要手动点编辑框

MFC 在编辑控件框中显示多行文本

MFC中如何给编辑框设置文本内容?

MFC编辑框-每次击键多个字符?

怎么用MFC,将复选框选中的文字在编辑框中显示出来,例如下面的图片,就是说将选中的课程在编辑框中显示出