【问题标题】:win32 - How to draw a rectangle around a text string?win32 - 如何在文本字符串周围绘制一个矩形?
【发布时间】:2013-04-16 01:32:36
【问题描述】:

我是 Win32 的新手,并试图在 C++ 中获得基于 GDI 的代码(出于技术原因不想使用 GDI+)

编辑:简化问题:

我需要在窗口中间绘制的文本周围绘制一个矩形。 - 如何填充矩形坐标? - 任何人都可以帮助解决这条线 - Rectangle(x1,y1,x2,y2) 吗? - 如何计算这些 (x1,y1) & (x2,y2) 值?

谢谢你..

        hdc = BeginPaint(hWnd, &ps);
    GetClientRect(hWnd, &rcClient);
    SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));
    SetTextColor(hdc, RGB(255, 0, 0));

    DrawText(hdc, wstring(s.begin(),s.end()).c_str(), -1, &rectResult, DT_SINGLELINE | DT_CALCRECT);

    DrawText(hdc, wstring(s.begin(),s.end()).c_str(), -1, &rcClient, DT_SINGLELINE | DT_CENTER | DT_VCENTER);

    // Here I need help - How to I place the rectangle around the Text - which is drawn in the middle of the window?
    // It looks like need to use - rectResult.bottom/top/left/right - but don't know how.. 
    Rectangle(hdc, 0,0,100,100);   

【问题讨论】:

  • GY - 同意这更像是一项家庭作业 - 但对于 win32 编程来说相对较新 - 根据我所读到的 - 需要创建一个基于临时内存的 DC 来计算大小/宽度文本的 - 从这个线程中找到了大部分答案,但不知道如何创建一个临时 DC 来执行这个任务。即使它是被矩形包围的单个文本 - 我可以进一步扩展它 - stackoverflow.com/questions/1835749/win32-text-drawing-puzzle
  • 这是我目前拥有的代码的最低版本(对于单个文本): case WM_PAINT: hdc = BeginPaint(hWnd, &ps); GetClientRect(hWnd, &rcClient); SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT)); SetTextColor(hdc, RGB(255, 0, 0)); DrawText(hdc, wstring(s.begin(),s.end()).c_str(), -1, &rcClient, DT_SINGLELINE | DT_CENTER | DT_VCENTER); // TODO: 在此处添加任何绘图代码... EndPaint(hWnd, &ps);休息;
  • 谢谢 G.Y.欣赏链接(其中一个是我想避免的 GDI+)。感谢您或某人是否可以提供代码 sn-p 以在窗口中心绘制一些文本并用矩形包围它 - 要求矩形的原因是 - 它会让我更好地理解关于文本到像素的计算方式,并为我澄清了很多事情。在这个阶段进一步探索......谢谢
  • 您可以通过单击问题下方的edit 链接,然后关注our formatting instructions(橙色?图标)来发布代码。与传统论坛不同,Stack Overflow 鼓励您在问题和答案中添加信息,而不是留下一连串的 cmets。

标签: winapi gdi


【解决方案1】:

您实际上不必自己将文本居中。如果您传递了适当的标志,GDI 文本输出函数可以为您执行此操作。

例如,如果您调用DrawText 并传递DT_CENTER 标志,它将自动在指定矩形的中间(水平居中)绘制文本。

假设您只有一行文本(听起来很像),您可以通过传递 DT_SINGLELINEDT_VCENTER 标志使其自动垂直居中文本。

所以您真正需要做的就是编写代码将your window's client area 分成4 等份,然后将这些矩形传递给DrawText 函数。这不是很困难。如果您无法在脑海中想象它,请用铅笔和纸将其放在上面。

void PaintWindow(HWND hWnd)
{
   // Set up the device context for drawing.
   PAINTSTRUCT ps;
   HDC hDC = BeginPaint(hWnd, &ps);
   HPEN hpenOld = static_cast<HPEN>(SelectObject(hDC, GetStockObject(DC_PEN)));
   HBRUSH hbrushOld = static_cast<HBRUSH>(SelectObject(hDC, GetStockObject(NULL_BRUSH)));

   // Calculate the dimensions of the 4 equal rectangles.
   RECT rcWindow;
   GetClientRect(hWnd, &rcWindow);

   RECT rc1, rc2, rc3, rc4;
   rc1 = rc2 = rc3 = rc4 = rcWindow;

   rc1.right  -= (rcWindow.right - rcWindow.left) / 2;
   rc1.bottom -= (rcWindow.bottom - rcWindow.top) / 2;

   rc2.left   = rc1.right;
   rc2.bottom = rc1.bottom;

   rc3.top   = rc1.bottom;
   rc3.right = rc1.right;

   rc4.top  = rc1.bottom;
   rc4.left = rc1.right;

   // Optionally, deflate each of the rectangles by an arbitrary amount so that
   // they don't butt up right next to each other and we can distinguish them.
   InflateRect(&rc1, -5, -5);
   InflateRect(&rc2, -5, -5);
   InflateRect(&rc3, -5, -5);
   InflateRect(&rc4, -5, -5);

   // Draw (differently-colored) borders around these rectangles.
   SetDCPenColor(hDC, RGB(255, 0, 0));    // red
   Rectangle(hDC, rc1.left, rc1.top, rc1.right, rc1.bottom);
   SetDCPenColor(hDC, RGB(0, 255, 0));    // green
   Rectangle(hDC, rc2.left, rc2.top, rc2.right, rc2.bottom);
   SetDCPenColor(hDC, RGB(0, 0, 255));    // blue
   Rectangle(hDC, rc3.left, rc3.top, rc3.right, rc3.bottom);
   SetDCPenColor(hDC, RGB(255, 128, 0));  // orange
   Rectangle(hDC, rc4.left, rc4.top, rc4.right, rc4.bottom);

   // Draw the text into the center of each of the rectangles.
   SetBkMode(hDC, TRANSPARENT);
   SetBkColor(hDC, RGB(0, 0, 0));   // black
   // TODO: Optionally, set a nicer font than the default.
   DrawText(hDC, TEXT("Hello World!"), -1, &rc1, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
   DrawText(hDC, TEXT("Hello World!"), -1, &rc2, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
   DrawText(hDC, TEXT("Hello World!"), -1, &rc3, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
   DrawText(hDC, TEXT("Hello World!"), -1, &rc4, DT_CENTER | DT_SINGLELINE | DT_VCENTER);

   // Clean up after ourselves.
   SelectObject(hDC, hpenOld);
   SelectObject(hDC, hbrushOld);
   EndPaint(hWnd, &ps);
}

 

【讨论】:

  • 谢谢科迪。您对单行的假设是正确的。这当然有帮助。想知道 (X,Y) 坐标是否已知 - 文本可以围绕它居中(而不是矩形)吗?可以想象 - 为此需要计算文本高度和宽度 - 以(X,Y)为中心? (为这个问题道歉,因为我实际上是在试图找到一种解决方案,将文本围绕 (x,y) (垂直和水平)居中。谢谢
  • @ejuser 当然,如果您知道坐标,您可以创建一个 RECT 结构并填充它们并将其传递给DrawText。是的,如果您愿意,您可以自己计算一串文本所需的宽度和高度。为此,您将使用GetTextExtentPoint32,就像我记得您在问题的某处提到的那样。这比让 Windows 为您做更多的工作。更多信息请联系here
  • 谢谢科迪。将进一步探索并回复 - 希望通过您提供的提示来解决这个问题。
  • 使用常规方法得到了解决方案并进一步探索。任何人都可以帮助如何在评论部分发布“格式化”代码(甚至可能吗?) - 放弃并发布格式化代码作为答案,因为这似乎是我能找出发布方法的唯一方法格式化代码。
  • @ejuser 在 cmets 和常规帖子中使用反引号进行内联代码格式化。像这样:` ` 但是你没有语法高亮或换行,所以它只适用于 very 短 sn-ps。发布答案是正确的选择,如果它实际上是问题的答案。否则,如果只是关于问题的更多信息,您应该编辑问题。 :-)
【解决方案2】:
RECT rect={0,0,0,0};
const char *str="Test Text";
DrawText(hDC, str, strlen(str), &rect, DT_CALCRECT | DT_NOCLIP);
Rectangle(hDC,rect.left,rect.top,rect.right,rect.bottom);
DrawText(hDC, str, strlen(str), &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE|DT_NOCLIP);

【讨论】:

    【解决方案3】:

    终于明白了 :) 非常感谢 Cody Gray 为我指明了正确的方向 :)

    GetTextExtentPoint32(hDC, str, strlen(str), &sz2); 
    rect2.top=rect2.bottom+sz2.cy;
    rect2.right=rect2.top+sz2.cx;
    Rectangle(hDC,rect2.left,rect2.top,rect2.right,rect2.bottom);
    DrawText(hDC, str, -1, &rect2, DT_CENTER | DT_VCENTER | DT_SINGLELINE|DT_NOCLIP);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多