6

I am new to Win32 and trying to get a GDI based code in C++ ( for technical reasons don't want to use GDI+)

Edit: Simplied the question:

I need to draw a rectangle around the text that is drawn in the middle of the window. - How can I populate the rectangle co-ordinates? - Can any one help with the line - Rectangle(x1,y1,x2,y2)? - How to calculate these (x1,y1) & (x2,y2) values?

Thank you..

        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);   
ejuser
  • 181
  • 2
  • 5
  • 13
  • This smells like homework. where is your effort or your program structure? – G.Y Apr 23 '13 at 00:59
  • 1
    G.Y - Agree that this is more of a home work - but being relatively new to win32 programming - and based on what I have read - need to create a temporary memory based DC to calculate the size/width of the text - Found most of the answers from this thread but don't know how to create a temporary DC to perform this task. Even if it is a single text surrounded by a rectangle - I can expand further on it - http://stackoverflow.com/questions/1835749/win32-text-drawing-puzzle – ejuser Apr 23 '13 at 01:02
  • 1
    This is the minimum version of the code I have so far( for a single text): 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: Add any drawing code here... EndPaint(hWnd, &ps); break; – ejuser Apr 23 '13 at 01:08
  • 1
    Read all those: http://www.functionx.com/win32/Lesson10.htm http://stackoverflow.com/questions/6639285/any-good-tutorials-resources-to-learn-win32-gdi Most important: http://msdn.microsoft.com/en-us/library/windows/desktop/dd145203(v=vs.85).aspx – G.Y Apr 23 '13 at 01:10
  • and don't skip this too: http://msdn.microsoft.com/en-us/library/windows/desktop/ms533895(v=vs.85).aspx – G.Y Apr 23 '13 at 01:12
  • Once you set your effort better and edit your question to contain at least a program structure with what you got so far - this can be a valid question. – G.Y Apr 23 '13 at 01:15
  • 1
    Thanks G.Y. Appreciate the links(one of them is GDI+ which I want to avoid). Appreciate if you or someone can be kind enough to provide a code snippet to draw some text at the center of the window and surround it by a rectangle - The reason asking for the rectangle is - it would allow me to understand a bit better on how the text to pixels is calculated and clarify a lot of things for me. Exploring further at this stage.. Thanks – ejuser Apr 23 '13 at 01:21
  • Can you at least add what you got so far as code to your question.. even if I can help - you're not really letting me. – G.Y Apr 23 '13 at 01:36
  • Trying for the equivalent of the code for the code posted in this link ( here the rectangle is drawn around the text: http://stackoverflow.com/questions/1126730/how-to-find-the-width-of-a-string-in-pixels-in-win32 – ejuser Apr 23 '13 at 02:39
  • >
    
      hdc = BeginPaint(hWnd, &ps);
      GetClientRect(hWnd, &rcClient);
      RECT rectResult={0,0,0,0};
      
      // This code is supposed to provide the text metrics into the rectResult
      DrawText(hdc, wstring(s.begin(),s.end()).c_str(), -1, &rectResult, DT_SINGLELINE | DT_VCENTER | DT_CALCRECT);
    
      // This code would center the text
      DrawText(hdc, wstring(s.begin(),s.end()).c_str(), -1, &getRect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
      
      // Now how do I use rectResult values to draw the rectangle?
      Rectangle(hdc, 100, 100, 150, 150);
    
    – ejuser Apr 23 '13 at 03:16
  • can any one help on how to post the code as the code seem to get mixed up ( no help available on this topic to post the formatted code). Thanks – ejuser Apr 23 '13 at 03:17
  • 1
    You can post code by clicking the [edit] link underneath the question, and then following [our formatting instructions](http://stackoverflow.com/editing-help#code) (the orange ? icon). Unlike traditional forums, Stack Overflow encourages you to add information to questions and answers, rather than leaving a flurry of comments. – Cody Gray - on strike Apr 23 '13 at 03:25

3 Answers3

12

You don't actually have to center the text yourself. The GDI text output functions can do that for you if you pass the appropriate flags.

For example, if you call DrawText and pass the DT_CENTER flag, it will automatically draw the text in the middle of the specified rectangle (horizontally centered).

Assuming you have only a single line of text (which it sounds like you do), you can get it to automatically vertically center the text by passing the DT_SINGLELINE and DT_VCENTER flags.

So all you really have to do is write code to divide your window's client area up into 4 equal parts, and then pass those rectangles to the DrawText function. That's not terribly difficult. Put a pencil and paper to it if you can't visualize it in your head.

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);
}

 

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
  • Thank You Cody. Your Assumption is correct about single line. This certainly helps. Wondering if (X,Y) co-ordinates are known - can that text be centered around it ( instead of a rectangle )? Would imagine - for this the text height & width need to be calculated - to center around (X,Y)? ( apologize for the question as I was actually trying to find a solution to centering the text around (x,y) ( both vertically & Horizontally). Thanks – ejuser Apr 23 '13 at 04:18
  • @ejuser Sure, if you know the coordinates, you can create a RECT structure with them filled in and pass it to `DrawText`. And yes, you can calculate the width and height required for a string of text yourself if you want to. For that, you'll use [`GetTextExtentPoint32`](http://msdn.microsoft.com/en-us/library/windows/desktop/dd144938.aspx), like I recall you mentioned somewhere in the question. It's just more work than letting Windows do it for you. More information on that is [here](http://stackoverflow.com/a/11600004/366904). – Cody Gray - on strike Apr 23 '13 at 04:21
  • Thanks Cody. Would explore further and reply back - Hope to get this figured out with the hints you have provided. – ejuser Apr 23 '13 at 04:39
  • Got a solution for this using regular method and exploring further. Can any one help on how to post the "formatted" Code Under Comment section ( is it even possible?) - Gave up and posting the formatted code as answer as that seems to be the only way I could figure out the way to post the formatted code. – ejuser Apr 24 '13 at 03:04
  • @ejuser Use backticks for inline code formatting, both in comments and regular posts. Like this: \` \` But you don't get syntax highlighting or line breaks, so it's only for *very* short snippets. Posting an answer is the right choice, if it actually an answer to the question. Otherwise, if it's just more info about the question, you should edit the question. :-) – Cody Gray - on strike Apr 24 '13 at 03:27
  • When setting `hbrushOld`, shouldn't it be rather `GetStockObject(DC_BRUSH)` instead of `GetStockObject(NULL_BRUSH)` to retrieve the current DC brush handle? – DocKimbel Aug 15 '15 at 10:51
1
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);
ejuser
  • 181
  • 2
  • 5
  • 13
1

Got it finally :) Thanks a lot Cody Gray for pointing me in right direction about this :)

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);
ejuser
  • 181
  • 2
  • 5
  • 13