紧凑的文件名编辑控件






4.57/5 (11投票s)
封装文件名压缩的编辑控件。
引言
在应用程序中,经常需要显示文件名,例如在只读编辑控件中。然而,文件名可能比编辑控件所能容纳的要长。许多微软应用程序会“压缩”文件名,用省略号(“...”)替换部分路径。我当前开发的一个应用程序需要实现相同的功能。下面我将介绍我的解决方案,我创建了一个基于MFC CEdit
控件的自定义类来适当地处理文件名。
路径压缩
经过短暂的研究,我找到了 PathCompactPath()
函数。该函数属于 shlwapi.dll,这意味着它在运行 Windows 95 或 Windows NT 的系统上不可用,*除非* 安装了 Internet Explorer 4.0 或更高版本。幸运的是,这覆盖了我们系统的所有用户,并且我认为它也覆盖了绝大多数 32 位 Windows 操作系统的用户。
使用该函数非常简单。它接受三个参数:一个 HDC、要压缩的文件名以及文本需要适应的空间大小。因此,为了充分压缩路径以适应编辑控件,我们只需使用以下代码:
CString CFilenameEdit::GetDisplayName() { // Get the DC for the control, and the rectangle into which we draw text CDC * pDC = GetDC(); CRect rectClient; GetRect(&rectClient); // Select the correct font into the DC CFont * pFontOld = pDC->SelectObject(GetFont()); // Get the display name, and truncate it to fit into the control // Note that we make the buffer larger than max path // in case we have some bizarre // situation where a load of ellipsis are inserted // and it overruns the buffer // Member variable containing filename; set by caller CString strDisplayName = m_strFilename; PathCompactPath(pDC->GetSafeHdc(), strDisplayName.GetBuffer(_MAX_PATH + 1 + BUFFER_EXTRA), rectClient.Width()); strDisplayName.ReleaseBuffer(); // Clean up! pDC->SelectObject(pFontOld); ReleaseDC(pDC); return strDisplayName; }
请注意,在使用该函数之前,我们必须将正确的字体(通过调用 CEdit::GetFont()
获取)选择到 DC 中,否则在确定文本长度时将使用错误的字体。
一个担忧是,该函数可能会返回一个比 _MAX_PATH
字符长的字符串,在这种情况下,我们将面临缓冲区溢出。这可能发生的情况是,省略号(本质上是三个句点字符)的文本宽度比两个字符短,因此字符串中的两个字符被替换为三个。因此,调用 CString::GetBuffer()
时请求一个稍大的缓冲区,以防万一!
使用控件
CFilenameEdit
类继承自 CEdit
,设计为只读。其理念是文件名可以由父应用程序设置,例如当用户从 CFileDialog
中选择一个文件时。
该控件只有两个公共函数:SetFilename()
和 GetFilename
,分别用于设置和检索要显示的文件名。调用 SetFilename()
会维护一个完整文件名的内部副本,并使用上述代码获取的压缩文件名来设置控件文本。GetFilename
返回完整文件名,而不管它在控件中是如何被压缩显示的。
由于控件文本将与要显示的文件名不同,因此普通的 DDX_Text
例程不适用。当文本加载到控件时,完整的文件名将被放入控件中。同样,如果控件中显示的是压缩后的文件名,那么在保存控件内容时,DDX_Text
例程就会返回这个压缩后的文件名。因此,除了控件本身,还有一个 DDX_???
例程,即 DDX_Filename
,它会相应地调用 SetFilename()
和 GetFilename()
函数。
为了给用户提供视觉辅助,创建了一个工具提示控件。当鼠标悬停在控件上时,工具提示将显示完整路径。
演示项目
演示项目有两个编辑控件,其中一个已经过子类化以提供 CFilenameEdit
功能。另一个是标准的编辑控件,用于在文件名放入其中时比较两个控件的内容。
“浏览”按钮允许选择一个文件,该文件的名称将显示在两个编辑控件中。“获取内容”按钮将显示文件名编辑控件中显示的文件名,这证明了 DDX_Filename
例程工作正常。
结论
该控件目前的状态正是我当前开发应用程序所需的。它可以添加很多功能,也许以后有时间我会添加更多。这里有其他文章展示了如何让控件接受拖放到上面的文件,以及如何在控件中构建一个“浏览”按钮——这些想法都可以被整合进来以增强这个控件。
此时,我真的应该感谢 Roger Allen,他关于在调用 PathCompactPath
之前设置 DC 中字体的代码片段,使得结果更加准确!