65.9K
CodeProject 正在变化。 阅读更多。
Home

紧凑的文件名编辑控件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.57/5 (11投票s)

2003年2月5日

CPOL

4分钟阅读

viewsIcon

78735

downloadIcon

1752

封装文件名压缩的编辑控件。

Sample Image - CompactFilename.gif

引言

在应用程序中,经常需要显示文件名,例如在只读编辑控件中。然而,文件名可能比编辑控件所能容纳的要长。许多微软应用程序会“压缩”文件名,用省略号(“...”)替换部分路径。我当前开发的一个应用程序需要实现相同的功能。下面我将介绍我的解决方案,我创建了一个基于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 中字体的代码片段,使得结果更加准确!

© . All rights reserved.