【问题标题】:How to draw curved text using MFC functions?如何使用 MFC 函数绘制曲线文本?
【发布时间】:2020-01-17 17:25:08
【问题描述】:

如何使用 MFC 函数绘制曲线文本?我想在下面实现这样的。

DrawText() 函数只能以直线绘制文本,我不知道如何以特定角度绘制曲线文本。请帮帮我。

谢谢。

【问题讨论】:

  • SetWorldTransform。你可能不得不改用TextOut() 函数,因为我感觉DrawText() 不支持转换。
  • @Jonathan,对于我的场景,如何为 SetWorldTransform 构造 XForm 以及如何为 TextOut() 计算 x、y 位置。
  • 这是一道数学题,不是编程题。

标签: winapi mfc


【解决方案1】:

你可以使用 GDI+,code project 中有一个示例,它是用 C# 编写的,我将它翻译成 C++:

    Graphics graphics(hWnd);

    RECT rect = { 0 };
    GetWindowRect(hWnd, &rect);
    POINT center = { (rect.right - rect.left) / 2,(rect.bottom - rect.top) / 2 };
    double radius = min(rect.right - rect.left, (rect.bottom - rect.top)) / 3;
    TCHAR text[] = L"ABCDEFGHIJLKMNOPQRSTUVWXYZ";
    REAL emSize = 24;
    Font* font = new Font(FontFamily::GenericSansSerif(), emSize, FontStyleBold);
    for (int i = 0; i < _tcslen(text); ++i)
    {
        RectF re, in;
        Status result = graphics.MeasureString(&text[i], 1, font, in, &re);;

        double charRadius = radius + re.Height;

        double angle = (((float)i / _tcslen(text)) - 0.25) * 2 * M_PI;

        double x = (int)(center.x + cos(angle) * charRadius);
        double y = (int)(center.y + sin(angle) * charRadius);


        result = graphics.TranslateTransform(x, y);

        result = graphics.RotateTransform((float)(90 + 360 * angle / (2 * M_PI)));
        PointF start(0, 0);
        SolidBrush Red(Color(255, 255, 0, 0));
        result = graphics.DrawString(&text[i], 1, font, start, &Red);

        result = graphics.ResetTransform();

        SolidBrush Green(Color(255, 0, 255, 0));
        Pen* pen = new Pen(&Green, 2.0f);
        result = graphics.DrawArc(pen, (REAL)(center.x - radius), (REAL)(center.y - radius), radius * 2, radius * 2, 0, 360);
    }

一些头文件:

#define _USE_MATH_DEFINES
#include <math.h>
#include <windows.h>
#include <objidl.h>
#include <gdiplus.h>
using namespace Gdiplus;
#pragma comment (lib,"Gdiplus.lib")

用法:

您必须在创建任何 GDI+ 对象之前调用 GdiplusStartup,并且 您必须删除所有 GDI+ 对象(或让它们退出 范围),然后再致电GdiplusShutdown

GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
//To Do.
GdiplusShutdown(gdiplusToken);

结果:

更新:

    Graphics graphics(hWnd);

    RECT rect = { 0 };
    GetWindowRect(hWnd, &rect);
    POINT center = { (rect.right - rect.left) / 2,(rect.bottom - rect.top) / 2 };
    double radius = min(rect.right - rect.left, (rect.bottom - rect.top)) / 3;
    TCHAR text[72][4] = { 0 };
    for (int i = 0; i < 72; i++)
    {
         _itot((i/2)*10, text[i],10);
         i++;
         _tcscpy(text[i],L"");
    }
    REAL emSize = 8;
    Font* font = new Font(FontFamily::GenericSansSerif(), emSize, FontStyleBold);
    for (int i = 0; i < 72; ++i)
    {
        RectF re, in,rel;
        Status result = graphics.MeasureString(text[i], _tcslen(text[i]), font, in, &re);
        result = graphics.MeasureString(L"|", 1, font, in, &rel);
        double charRadius = radius - re.Height;

        double angle = (((float)i / 72) - 0.25) * 2 * M_PI;

        double x = (center.x + cos(angle) * charRadius);
        double y = (center.y + sin(angle) * charRadius);


        result = graphics.TranslateTransform(x, y);

        result = graphics.RotateTransform((float)(90 + 360 * angle / (2 * M_PI)));
        PointF start(0- re.Width/2, 0);
        SolidBrush Red(Color(255, 255, 0, 0));
        result = graphics.DrawString(text[i], _tcslen(text[i]), font, start, &Red);
        result = graphics.ResetTransform();

        x = (int)(center.x + cos(angle) * radius);
        y = (int)(center.y + sin(angle) * radius);
        result = graphics.TranslateTransform(x, y);
        result = graphics.RotateTransform((float)(90 + 360 * angle / (2 * M_PI)));

        PointF start1(0 - rel.Width / 2, 0);
        result = graphics.DrawString(L"|", 1, font, start1, &Red);
        result = graphics.ResetTransform();
    }
    SolidBrush Green(Color(255, 0, 255, 0));
    Pen* pen = new Pen(&Green, 2.0f);
    Status result = graphics.DrawArc(pen, (REAL)(center.x - radius), (REAL)(center.y - radius), radius * 2, radius * 2, 0, 360);

结果:

【讨论】:

  • 我无法理解这个角度/弧度计算 double angle = (((float)i / 72) - 0.25) * 2 * M_PI;结果 = graphics.RotateTransform((float)(90 + 360 * 角度 / (2 * M_PI)));请解释一下。
  • 它计算第 i 个字符的坐标,并以度为单位旋转轴。这实际上是一个三角形变换。以下公式给出了相同的坐标和角度:double angle = (((float)i / 72)) * 2 * M_PI; double x = (center.x + sin(angle) * charRadius); double y = (center.y - cos(angle) * charRadius); result = graphics.RotateTransform((float)(360 * angle / (2 * M_PI)));
猜你喜欢
  • 2012-02-21
  • 2013-02-07
  • 1970-01-01
  • 2021-07-05
  • 2020-11-06
  • 1970-01-01
  • 2015-09-10
  • 2012-02-06
相关资源
最近更新 更多