获取文本写入的像素宽度

https://opensource.apple.com/source/WebCore/WebCore-955.66/platform/wx/wxcode/win/fontprops.cpp.auto.html

Windows的方案:

FunctionDescription
AddFontMemResourceExAdds an embedded font to the system font table.
AddFontResourceAdds a font resource to the system font table.
AddFontResourceExAdds a private or non-enumerable font to the system font table.
CreateFontCreates a logical font.
CreateFontIndirectCreates a logical font from a structure.
CreateFontIndirectExCreates a logical font from a structure.
DrawTextDraws formatted text in a rectangle.
DrawTextExDraws formatted text in rectangle.
EnumFontFamExProcAn application definedcallback function used with EnumFontFamiliesEx to process fonts.
EnumFontFamiliesExEnumerates all fonts in the system with certain characteristics.
ExtTextOutDraws a character string.
GetAspectRatioFilterExGets the setting for the aspect-ratio filter.
GetCharABCWidthsGets the widths of consecutive characters from the TrueType font.
GetCharABCWidthsFloatGets the widths of consecutive characters from the current font.
GetCharABCWidthsIGets the widths of consecutive glyph indices or from an array of glyph indices from the TrueType font.
GetCharacterPlacementGets information about a character string.
GetCharWidth32Gets the widths of consecutive characters from the current font.
GetCharWidthFloatGets the fractional widths of consecutive characters from the current font.
GetCharWidthIGets the widths of consecutive glyph indices or an array of glyph indices from the current font.
GetFontDataGets metric data for a TrueType font.
GetFontLanguageInfoReturns information about the selected font for a display context.
GetFontUnicodeRangesTells which Unicode characters are supported by a font.
GetGlyphIndicesTranslates a string into an array of glyph indices.
GetGlyphOutlineGets the outline or bitmap for a character in the TrueType font.
GetKerningPairsGets the character-kerning pairs for a font.
GetOutlineTextMetricsGets text metrics for TrueType fonts.
GetRasterizerCapsTells whether TrueType fonts are installed.
GetTabbedTextExtentComputes the width and height of a character string, including tabs.
GetTextAlignGets the text-alignment setting for a device context.
GetTextCharacterExtraGets the current intercharacter spacing for a device context.
GetTextColorGets the text color for a device context.
GetTextExtentExPointGets the number of characters in a string that will fit within a space.
GetTextExtentExPointIGets the number of glyph indices that will fit within a space.
GetTextExtentPoint32Computes the width and height of a string of text.
GetTextExtentPointIComputes the width and height of an array of glyph indices.
GetTextFaceGets the name of the font that is selected into a device context.
GetTextMetricsFills a buffer with the metrics for a font.
PolyTextOutDraws several strings using the font and text colors in a device context.
RemoveFontMemResourceExRemoves a font whose source was embedded in a document from the system font table.
RemoveFontResourceRemoves the fonts in a file from the system font table.
RemoveFontResourceExRemoves a private or non-enumerable font from the system font table.
SetMapperFlagsAlters the algorithm used to map logical fonts to physical fonts.
SetTextAlignSets the text-alignment flags for a device context.
SetTextCharacterExtraSets the intercharacter spacing.
SetTextColorSets the text color for a device context.
SetTextJustificationSpecifies the amount of space the system should add to the break characters in a string.
TabbedTextOutWrites a character string at a location, expanding tabs to specified values.
TextOutWrites a character string at a location.
GetTextExtentPoint32
GetTextExtentPoint
GetTextExtentExPoint
DrawText
DrawTextEx
GetTextExtent
GetTextMetrics
GetCharWidth: 不能用于Truetype或Opentype
LpkUseGDIWidthCache
GetTabbedTextExtent
LpkGetTextExtentExPoint
GetTextExtentExPointWPri
GetCharABCWidths:只能用于Truetype或Opentype
GetCharABCWidthsFloat : 支持所有字体,但是系统必须是win2k以上。
GetOutlineTextMetrics

void GetTextExtent( const wxFont& font, const wxString& str, wxCoord *width, wxCoord *height,
                            wxCoord *descent, wxCoord *externalLeading )
{
    HDC dc = GetDC(0);
    WXHFONT hFont = font.GetHFONT();
    ::SelectObject(dc, hFont);

    HFONT hfontOld;
    if ( font != wxNullFont )
    {
        wxASSERT_MSG( font.Ok(), _T("invalid font in wxDC::GetTextExtent") );

        hfontOld = (HFONT)::SelectObject(dc, hFont);
    }
    else // don't change the font
    {
        hfontOld = 0;
    }

    SIZE sizeRect;
    const size_t len = str.length();
    if ( !::GetTextExtentPoint32(dc, str, len, &sizeRect) )
    {
        wxLogLastError(_T("GetTextExtentPoint32()"));
    }

#if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400)
    // the result computed by GetTextExtentPoint32() may be too small as it
    // accounts for under/overhang of the first/last character while we want
    // just the bounding rect for this string so adjust the width as needed
    // (using API not available in 2002 SDKs of WinCE)
    if ( len > 1 )
    {
        ABC width;
        const wxChar chFirst = *str.begin();
        if ( ::GetCharABCWidths(dc, chFirst, chFirst, &width) )
        {
            if ( width.abcA < 0 )
                sizeRect.cx -= width.abcA;

            if ( len > 1 )
            {
                const wxChar chLast = *str.rbegin();
                ::GetCharABCWidths(dc, chLast, chLast, &width);
            }
            //else: we already have the width of the last character

            if ( width.abcC < 0 )
                sizeRect.cx -= width.abcC;
        }
        //else: GetCharABCWidths() failed, not a TrueType font?
    }
#endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 400)

    TEXTMETRIC tm;
    ::GetTextMetrics(dc, &tm);

    if (width)
        *width = sizeRect.cx;
    if (height)
        *height = sizeRect.cy;
    if (descent)
        *descent = tm.tmDescent;
    if (externalLeading)
        *externalLeading = tm.tmExternalLeading;

    if ( hfontOld )
    {
        ::SelectObject(dc, hfontOld);
    }
    
    ReleaseDC(0, dc);
}

https://opensource.apple.com/source/WebCore/WebCore-955.66/platform/wx/wxcode/mac/carbon/fontprops.mm.auto.html

Mac平台使用了wxWidgets方案

void GetTextExtent( const wxFont& font, const wxString& str, wxCoord *width, wxCoord *height,
                            wxCoord *descent, wxCoord *externalLeading )
{
    wxGraphicsContext * const gc = wxGraphicsContext::Create();
    
    gc->SetFont(font, *wxBLACK); // colour doesn't matter but must be specified
    struct GCTextExtent
    {
        wxDouble width, height, descent, externalLeading;
    } e;
    gc->GetTextExtent(str, &e.width, &e.height, &e.descent, &e.externalLeading);
    if ( width )
        *width = wxCoord(e.width + .5);
    if ( height )
        *height = wxCoord(e.height + .5);
    if ( descent )
        *descent = wxCoord(e.descent + .5);
    if ( externalLeading )
        *externalLeading = wxCoord(e.externalLeading + .5);

    delete gc;
}
void wxMacCoreGraphicsContext::GetTextExtent( const wxString &str, wxDouble *width, wxDouble *height,
                            wxDouble *descent, wxDouble *externalLeading ) const
{
    wxCHECK_RET( !m_font.IsNull(), wxT("wxMacCoreGraphicsContext::GetTextExtent - no valid font set") );

    if ( width )
        *width = 0;
    if ( height )
        *height = 0;
    if ( descent )
        *descent = 0;
    if ( externalLeading )
        *externalLeading = 0;

    // In wxWidgets (MSW-inspired) API it is possible to call GetTextExtent()
    // with an empty string to get just the descent and the leading of the
    // font, so support this (mis)use.
    wxString strToMeasure(str);
    if (str.empty())
        strToMeasure = wxS(" ");

    wxMacCoreGraphicsFontData* fref = (wxMacCoreGraphicsFontData*)m_font.GetRefData();

    wxCFStringRef text(strToMeasure, wxLocale::GetSystemEncoding() );
    
    wxCFRef<CFAttributedStringRef> attrtext( CFAttributedStringCreate(kCFAllocatorDefault, text, fref->OSXGetCTFontAttributes() ) );
    wxCFRef<CTLineRef> line( CTLineCreateWithAttributedString(attrtext) );

    CGFloat a, d, l, w;
    w = CTLineGetTypographicBounds(line, &a, &d, &l);

    if ( !str.empty() )
    {
        if ( width )
            *width = w;
        if ( height )
            *height = a+d+l;
    }
    if ( descent )
        *descent = d;
    if ( externalLeading )
        *externalLeading = l;

    CheckInvariants();    
}

void wxMacCoreGraphicsContext::GetPartialTextExtents(const wxString& text, wxArrayDouble& widths) const
{
    widths.clear();

    wxCHECK_RET( !m_font.IsNull(), wxT("wxMacCoreGraphicsContext::DrawText - no valid font set") );

    if (text.empty())
        return;

    wxMacCoreGraphicsFontData* fref = (wxMacCoreGraphicsFontData*)m_font.GetRefData();

    wxCFStringRef t(text, wxLocale::GetSystemEncoding() );
    wxCFRef<CFAttributedStringRef> attrtext( CFAttributedStringCreate(kCFAllocatorDefault, t, fref->OSXGetCTFontAttributes()) );
    wxCFRef<CTLineRef> line( CTLineCreateWithAttributedString(attrtext) );

    widths.reserve(text.length());
    CFIndex u16index = 1;
    for ( wxString::const_iterator iter = text.begin(); iter != text.end(); ++iter, ++u16index )
    {
        // Take care of surrogate pairs: they take two, not one, of UTF-16 code
        // units used by CoreText.
        if ( *iter >= 0x10000 )
        {
            ++u16index;
        }
        widths.push_back( CTLineGetOffsetForStringIndex( line, u16index, NULL ) );
    }

    CheckInvariants();
}
 

因为wxWidgets也是跨平台的:


https://opensource.apple.com/source/WebCore/WebCore-955.66/platform/wx/wxcode/gtk/fontprops.cpp.auto.html

Linux平台使用了Pango:

void GetTextExtent( const wxFont& font, const wxString& str, wxCoord *width, wxCoord *height,
                            wxCoord *descent, wxCoord *externalLeading )
{
    if ( width )
        *width = 0;
    if ( height )
        *height = 0;
    if ( descent )
        *descent = 0;
    if ( externalLeading )
        *externalLeading = 0;

    if (str.empty())
        return;

// FIXME: Doesn't support height, descent or external leading, though we don't need this for WebKit
// it will need to be implemented before merging into wx unless we craft a new API.
#if USE(WXGC)
    PangoFont* pangoFont = WebCore::createPangoFontForFont(&font);
    PangoContext* pangoContext = pango_cairo_font_map_create_context(PANGO_CAIRO_FONT_MAP(WebCore::pangoFontMap()));
    PangoGlyph pangoGlyph = WebCore::pango_font_get_glyph(pangoFont, pangoContext, (gunichar)g_utf8_get_char(str.ToUTF8()));
    cairo_glyph_t cglyph = { pangoGlyph, 0, 0 };
    cairo_text_extents_t extents;
    cairo_scaled_font_t* scaled_font = WebCore::createScaledFontForFont(&font);
    cairo_scaled_font_glyph_extents(scaled_font, &cglyph, 1, &extents);

    if (cairo_scaled_font_status(scaled_font) == CAIRO_STATUS_SUCCESS && extents.x_advance != 0)
        *width = (wxCoord)extents.x_advance;

    cairo_scaled_font_destroy(scaled_font);
    g_object_unref(pangoContext);
    g_object_unref(pangoFont);
#else
    PangoContext* context = gdk_pango_context_get_for_screen( gdk_screen_get_default() );
    PangoLayout* m_layout = pango_layout_new(context);
    // and use it if it's valid
    if ( font && font->IsOk() )
    {
        pango_layout_set_font_description
        (
            m_layout,
            font->GetNativeFontInfo()->description
        );
    }

    // Set layout's text
    const wxCharBuffer dataUTF8 = wxConvUTF8.cWX2MB(str);
    if ( !dataUTF8 )
    {
        // hardly ideal, but what else can we do if conversion failed?
        return;
    }

    pango_layout_set_text( m_layout, dataUTF8, strlen(dataUTF8) );

    int h = 0;
    pango_layout_get_pixel_size( m_layout, width, &h );

    if (descent)
    {
        PangoLayoutIter *iter = pango_layout_get_iter(m_layout);
        int baseline = pango_layout_iter_get_baseline(iter);
        pango_layout_iter_free(iter);
        *descent = h - PANGO_PIXELS(baseline);
    }

    if (height)
        *height = (wxCoord) h;
#endif
}


<think> 我们正在讨论在C#的Panel控件中指定位置写入文本的方法。根据用户提供的引用,主要涉及在Panel中嵌入窗体或设置控件位置,但没有直接提到写入文本。不过,我们可以借鉴这些引用中关于位置设置的思想。 写入文本通常有两种方式: 1. 使用Label控件:在指定位置添加一个Label控件,设置其Text属性和Location属性。 2. 重写Panel的OnPaint方法,使用Graphics.DrawString方法在指定位置绘制文本。 用户要求“指定位置”,因此我们需要明确位置坐标。下面分别介绍这两种方法: 方法一:使用Label控件(适用于动态文本较少的情况) 步骤: a. 创建一个Label控件。 b. 设置Label的Text属性为所需文本。 c. 设置Label的Location属性为指定位置(相对于Panel的左上角)。 d. 将Label添加到Panel的Controls集合中。 示例代码: Label lbl = new Label(); lbl.Text = "要显示的文本"; lbl.Location = new Point(x, y); // x和y是相对于Panel左上角的坐标 panel1.Controls.Add(lbl); 方法二:使用绘图方法(适用于需要复杂绘制或频繁重绘的情况) 步骤: a. 重写Panel的OnPaint事件(或订阅Paint事件)。 b. 在事件处理函数中使用Graphics.DrawString方法在指定位置绘制文本。 示例代码: 在窗体的构造函数中(或设计时)订阅Panel的Paint事件: panel1.Paint += new PaintEventHandler(panel1_Paint); 事件处理函数: private void panel1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; // 设置字体和画刷 Font font = new Font("宋体", 12); SolidBrush brush = new SolidBrush(Color.Black); // 指定位置绘制文本(坐标相对于Panel的左上角) g.DrawString("要显示的文本", font, brush, new PointF(x, y)); } 注意:方法二绘制的文本不会被当作控件,因此无法直接交互(如点击事件)。如果文本需要交互,使用方法一。 根据引用[3]中的思想,位置坐标是相对于Panel的左上角的(即Panel的客户区),所以无论使用哪种方法,坐标都是相对于Panel内部。 考虑到用户可能需要在运行时动态改变文本,方法一更为灵活(可以动态修改Label的位置和文本),而方法二则需要调用Invalidate()来触发重绘。 因此,根据实际需求选择方法: - 如果是静态文本且需要复杂绘制(如旋转、渐变等),选择方法二。 - 如果是动态文本,且需要简单显示,选择方法一。 下面给出两种方法的完整示例: 方法一示例代码(动态添加标签): private void AddTextToPanel(string text, int x, int y) { Label lbl = new Label(); lbl.AutoSize = true; // 根据文本内容自动调整大小 lbl.Text = text; lbl.Location = new Point(x, y); panel1.Controls.Add(lbl); } 方法二示例代码(重绘文本): private void panel1_Paint(object sender, PaintEventArgs e) { DrawTextAtLocation(e.Graphics, "固定文本", 50, 50); } private void DrawTextAtLocation(Graphics g, string text, float x, float y) { using (Font font = new Font("宋体", 12)) using (SolidBrush brush = new SolidBrush(Color.Black)) { g.DrawString(text, font, brush, x, y); } } // 如果需要动态改变文本内容并重绘,可以定义一个字符串变量,然后在需要重绘时改变该变量并调用panel1.Invalidate(); private string dynamicText = ""; private void SetDynamicText(string text) { dynamicText = text; panel1.Invalidate(); // 触发重绘 } private void panel1_Paint(object sender, PaintEventArgs e) { DrawTextAtLocation(e.Graphics, dynamicText, 50, 50); } 请根据实际需求选择合适的方法。 §§相关问题§§ 1. 如何在C#的Panel控件中清除之前绘制的文本? 2. 如何更新Panel中指定位置的文本内容? 3. 在Panel中绘制文本时如何实现文本换行? </think> 在 C# 中,Panel 控件本身不具备直接写入文本的功能,但可通过以下两种常用方法实现在指定位置添加文本: ### 方法 1:使用 Label 控件(推荐) 在 Panel 内动态创建 Label 控件,通过设置位置和文本属性实现: ```csharp // 创建标签控件 Label textLabel = new Label(); // 设置文本属性 textLabel.Text = "指定位置的文本"; textLabel.AutoSize = true; // 自动适应文本宽度 // 设置相对于Panel左上角的位置 (单位:像素) textLabel.Location = new Point(x, y); // x,y为指定坐标 // 添加至Panel panel1.Controls.Add(textLabel); ``` **坐标说明**: - `Point(0,0)` 表示 Panel 左上角 - 使用 `panel1.Width` 和 `panel1.Height` 可获取容器尺寸实现居中定位 ### 方法 2:使用 GDI+ 绘图(静态文本) 通过重写 Panel 的 Paint 事件绘制文本: ```csharp private void panel1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; // 设置字体和颜色 using (Font font = new Font("宋体", 12)) using (SolidBrush brush = new SolidBrush(Color.Black)) { // 在指定坐标(50,30)绘制文本 g.DrawString("固定位置文本", font, brush, new PointF(50, 30)); } } ``` **调用重绘**:修改文本后需调用 `panel1.Invalidate()` 刷新 --- ### 定位技巧参考 1. **坐标基准**: - 所有坐标均相对于 Panel 左上角 `(0,0)` [^3] - 居中定位公式: ```csharp int x = (panel1.Width - textLabel.Width) / 2; int y = (panel1.Height - textLabel.Height) / 2; textLabel.Location = new Point(x, y); ``` 2. **动态调整**: ```csharp // 响应Panel尺寸变化时重定位 private void panel1_Resize(object sender, EventArgs e) { textLabel.Location = new Point( (panel1.Width - textLabel.Width) / 2, panel1.Height - 30 // 距底部30像素 ); } ``` ---
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值