You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Windows C++中如何高亮搜索到的匹配字符串

Windows C++ GDI 搜索文本高亮实现方案

核心思路

你拿到的匹配起始下标是字符级的位置,只需要通过GDI提供的字符串尺寸计算接口,把「匹配位置之前的所有字符的像素总宽度」算出来,叠加到你原本的文本绘制起始X坐标上,就能得到高亮片段的绘制坐标,再分三段绘制文本即可:

  • 匹配位置前的普通文本:用默认样式绘制
  • 匹配到的目标文本:用高亮样式绘制
  • 匹配位置后的普通文本:切回默认样式绘制

具体实现步骤

  1. 修正原搜索函数的冗余逻辑:你代码里的searchForx没有定义,且const_cast属于不必要的危险操作,直接调用searchFor.c_str()即可传参给API。
  2. 调用GetTextExtentPoint32计算字符串像素尺寸:这个API会基于当前DC选中的字体,返回给定字符串的像素宽高,是字符下标转像素坐标的核心接口。
  3. 拆分文本分段绘制:将原搜索字符串拆为前缀、匹配段、后缀三部分,按顺序调整绘制坐标和颜色即可完成高亮。

完整示例代码

#include <windows.h>
#include <string>

// 搜索函数,返回匹配起始位置,std::string::npos代表未匹配
std::size_t SearchText(const std::string& searchString, const std::string& searchFor)
{
    return searchString.find(searchFor);
}

// 高亮绘制文本的函数
void DrawHighlightedText(HWND hWnd, int baseX, int baseY, const std::string& fullText, std::size_t matchPos, std::size_t matchLen)
{
    HDC hDC = GetDC(hWnd);
    // 先把你要用的字体选入DC,这里用默认系统字体也可以,自行替换
    HFONT hOldFont = (HFONT)SelectObject(hDC, GetStockObject(DEFAULT_GUI_FONT));
    SetBkMode(hDC, OPAQUE);

    SIZE sz;
    int currentX = baseX;

    // 1. 绘制匹配前的前缀文本(默认样式)
    if (matchPos > 0 && matchPos != std::string::npos)
    {
        std::string prefix = fullText.substr(0, matchPos);
        // 计算前缀宽度
        GetTextExtentPoint32A(hDC, prefix.c_str(), prefix.size(), &sz);
        // 默认颜色,可自行修改
        SetBkColor(hDC, GetSysColor(COLOR_WINDOW));
        SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
        TextOutA(hDC, currentX, baseY, prefix.c_str(), prefix.size());
        currentX += sz.cx;
    }

    // 2. 绘制匹配的高亮文本
    if (matchPos != std::string::npos && matchLen > 0 && (matchPos + matchLen) <= fullText.size())
    {
        std::string matchStr = fullText.substr(matchPos, matchLen);
        GetTextExtentPoint32A(hDC, matchStr.c_str(), matchStr.size(), &sz);
        // 高亮颜色:绿底紫字,和你给的示例一致
        SetBkColor(hDC, RGB(0, 255, 0));
        SetTextColor(hDC, RGB(255, 0, 255));
        TextOutA(hDC, currentX, baseY, matchStr.c_str(), matchStr.size());
        currentX += sz.cx;
    }

    // 3. 绘制匹配后的后缀文本(切回默认样式)
    std::string suffix;
    if (matchPos != std::string::npos)
    {
        suffix = fullText.substr(matchPos + matchLen);
    }
    else
    {
        suffix = fullText;
    }
    SetBkColor(hDC, GetSysColor(COLOR_WINDOW));
    SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
    TextOutA(hDC, currentX, baseY, suffix.c_str(), suffix.size());

    // 资源释放
    SelectObject(hDC, hOldFont);
    ReleaseDC(hWnd, hDC);
}

// 调用示例
void TestHighlight(HWND hWnd)
{
    std::string fullText = "这是一段测试文本,测试高亮功能";
    std::string searchFor = "测试高亮";
    std::size_t foundPos = SearchText(fullText, searchFor);
    
    if (foundPos != std::string::npos)
    {
        MessageBoxA(NULL, searchFor.c_str(), "字符串找到", MB_OK);
    }
    else
    {
        MessageBoxA(NULL, searchFor.c_str(), "未找到字符串", MB_OK);
    }

    // 绘制高亮文本,起始坐标(10,10)和你给的示例一致
    DrawHighlightedText(hWnd, 10, 10, fullText, foundPos, searchFor.size());
}

注意事项

  • 计算字符串尺寸必须和绘制使用同一个DC、同一种字体,否则宽度计算会出现偏差,导致高亮位置错位。
  • 如果需要匹配多个结果,只需要循环调用searchString.find(searchFor, lastPos + matchLen)遍历所有匹配位置,依次绘制多个高亮段即可。
  • 如果是多行文本场景,你需要先自行对文本做换行排版,记录每行的起始字符索引和Y坐标,匹配到字符后先判断属于哪一行,再计算该行内的X偏移即可。

内容的提问来源于stack exchange,提问作者LoneWarrior ForgottenTrails

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 08:45:05