2013-06-27 50 views
0

我有一個需要重畫多行文本的窗口,文本可以是可變長度的。 那麼如何去做這件事?在窗口中垂直居中多行文本,純winapi和C++

這是我現在所擁有的,它不起作用。

   RECT rc; 

       GetWindowRect (hwnd, &rc); 



       int rectHeight = DrawText(hMemDc, text.c_str(), text.size(), &rc, DT_CALCRECT);     // Get formating rectangle height 


       int windowHight = rc.bottom - rc.top; 
       int windowWidth = rc.right - rc.left; 


       int yTop = rc.top + ( (windowHight - rectHeight)/2 ); 
       int yBottom = yTop + rectHeight; 

       int xLeft = rc.left + 20; 
       int xRight = rc.right - 20; 


       rc.top  = yTop; 
       rc.bottom = yBottom; 
       rc.left  = xLeft; 
       rc.right  = xRight; 


       DrawText(hMemDc, text.c_str(), text.size(), &rc, DT_LEFT | DT_WORDBREAK); 
+0

有一個'DT_VCENTER'標誌。 – chris

+0

@chris它僅適用於單行。 – StudentX

+1

您需要通過第一次使用'DT_CALCRECT'得到的矩形,然後將計算出的矩形居中放置在窗口中並正常繪製。 –

回答

1

你的代碼有兩個問題。首先,您需要在DT_CALCRECT調用中指定DT_WORDBREAK,否則它將不包裝文字以適合可用寬度。

int rectHeight = DrawText(hMemDc, text.c_str(), text.size(), &rc, 
    DT_CALCRECT|DT_WORDBREAK); 

二,DT_CALCRECT通話將覆蓋與計算矩形的rc變量,所以你的窗口高度將是錯誤的,你的中心將無法正常工作。在DT_CALCRECT呼叫之前保存rc變量,或在之後再次呼叫GetWindowRect

GetWindowRect (hwnd, &rc); 
+0

非常感謝。 :)不知道DT_CALCRECT調用會覆蓋rc變量。 – StudentX

0

我解決了這個問題畫一些調試線,以幫助我的代碼:

   { 
        CPen p; 
        p.CreatePen(PS_SOLID, 0, RGB(0,0,255)); 
        pDrawDC->SelectObject(&p); 

        pDrawDC->MoveTo(rc.TopLeft()); 
        pDrawDC->LineTo(rc.BottomRight()); 
       } 

       CRect rdebug(rc); 

       int height= pDrawDC->DrawText(sLabel, &rdebug, DT_CENTER | DT_VCENTER | DT_WORDBREAK | DT_CALCRECT); 

       { 
        CPen p; 
        p.CreatePen(PS_SOLID, 0, RGB(0,255,0)); 
        pDrawDC->SelectObject(&p); 

        pDrawDC->MoveTo(rdebug.TopLeft()); 
        pDrawDC->LineTo(rdebug.BottomRight()); 
       } 

       int center_y= rc.CenterPoint().y; 
       rc.top= center_y - height/2; 
       rc.bottom= center_y + height /2; 

       { 
        CPen p; 
        p.CreatePen(PS_SOLID, 0, RGB(255,0,0)); 
        pDrawDC->SelectObject(&p); 

        pDrawDC->MoveTo(rc.TopLeft()); 
        pDrawDC->LineTo(rc.BottomRight()); 
       } 

       pDrawDC->DrawText(sLabel, rc, DT_CENTER | DT_VCENTER | DT_WORDBREAK); 

公告的中,RDebug,CPEN,和的LineTo線通過MoveTo僅用於調試目的。

我有下面的圖片:

debug image

現在,無需調試的一部分,我可以減少源代碼足跡:

   int height= pDrawDC->DrawText(sLabel, CRect(rc), DT_CENTER | DT_VCENTER | DT_WORDBREAK | DT_CALCRECT); 

       int center_y= rc.CenterPoint().y; 
       rc.top= center_y - height/2; 
       rc.bottom= center_y + height /2; 

       pDrawDC->DrawText(sLabel, rc, DT_CENTER | DT_VCENTER | DT_WORDBREAK);