Нарисовать текст в несколько строк...
От: Sheridan Россия  
Дата: 22.11.04 05:45
Оценка:
Есть строка текста и RECT куда этот текст надо вывести в несколько строк... Даже не так... Надо перед созданием окна вычислить необходимый RECT и создать это окно нужного размера. Текст — просто строка неизвестного размера...
Вот что я делаю:
CToolTip::CToolTip(std::string Text, std::string Caption,int DeltaTop, int DeltaLeft, EIcon Icon)
{
    _caption = Caption;
    _text = Text;
    Options = GetToolTipManager()->ToolTipOptions;
    /*Вычисление размеров окошка*/
    int Width = Options->MinToolTipWidth;
    int Height = Options->MinToolTipHeight;
    int CaptionHeight = _caption.length() * Options->CaptionFontStruct.lfWidth;
    if (Height < CaptionHeight) Height += CaptionHeight - Height;

    int LineWidth = 0;
    int Lines = Height/Options->TextFontStruct.lfHeight;
    if (Height%Options->TextFontStruct.lfHeight) Lines++;
    if (Lines > 1)
    {
        int CharsPerLine = _text.length() / Lines;
        while(CharsPerLine>Options->MaxLineLength || CharsPerLine<Options->MinLineLength)
        {
            if (CharsPerLine>Options->MaxLineLength) Lines++;
            if (CharsPerLine<Options->MinLineLength) Lines--;
            CharsPerLine = _text.length() / Lines;
        }
        LineWidth = CharsPerLine*Options->TextFontStruct.lfWidth;
        int LinesHeight = Options->TextFontStruct.lfHeight * Lines;
        if(LinesHeight > Height) Height += Height - LinesHeight;
        for (int i=0;i<Lines;i++) TextStrings.push_back(_text.substr(i*CharsPerLine,CharsPerLine));
    }
    else    
    {
        LineWidth = _text.length()*Options->TextFontStruct.lfWidth;
        TextStrings.push_back(_text);
    }
    if(Width<LineWidth+Options->CaptionWidth) Width += Width - LineWidth+Options->CaptionWidth;
    WindowPos.x = DeltaLeft;
    WindowPos.y = DeltaTop - Height;
    TTWindowHandle = CreateWindowEx(WS_EX_TOPMOST | WS_EX_TOOLWINDOW,
                                    "Sheridan_ToolTip_Wnd_Class",
                                    "",
                                    WS_POPUP | WS_BORDER,
                                    WindowPos.x,
                                    WindowPos.y,
                                    Width,
                                    Height,
                                    NULL,
                                    NULL,
                                    NULL,
                                    (LPVOID) NULL);
    if (!TTWindowHandle) ShowError("CreateWindow");
    GetClientRect(TTWindowHandle,&TTWindowRect);
    _TTCaptionRect = TTWindowRect;
    _TTCaptionRect.right = Options->CaptionWidth;
    _TTTextRect = TTWindowRect; // - Собственно RECT под вывод текста
    _TTTextRect.top -= Options->TextBorderWidth;
    _TTTextRect.left += Options->CaptionWidth;
    _TTTextRect.right -= Options->TextBorderWidth;
    _TTTextRect.bottom += Options->TextBorderWidth; 
    SetWindowLong(TTWindowHandle,GWL_USERDATA,(LONG)this);
    Show();
}

Options это вот что
class CToolTipOptions
{
public:
    CToolTipOptions(void);
    ~CToolTipOptions(void);
    int MaxLineLength;
    int MinLineLength;
    int MinToolTipHeight;
    int MinToolTipWidth;
    int CaptionWidth;
    COLORREF StartGradientColor;
    COLORREF EndGradientColor;
    int GradientCount;
    COLORREF CaptionColor;
    COLORREF TextColor;
    unsigned int ShowTime;
    LOGFONT CaptionFontStruct;
    HFONT CaptionFont;
    LOGFONT TextFontStruct; // шрфт для текста
    HFONT TextFont;
    int TextBorderWidth;
    EGradientDirection GradientDirection;
};

Шрифт моздаю вот так:
    CaptionFontStruct.lfCharSet = DEFAULT_CHARSET;
    CaptionFontStruct.lfClipPrecision = CLIP_DEFAULT_PRECIS;
    CaptionFontStruct.lfEscapement = 900;
    strcpy(CaptionFontStruct.lfFaceName,"Microsoft Sans Serif");
    CaptionFontStruct.lfHeight = 12;
    CaptionFontStruct.lfItalic = FALSE;
    CaptionFontStruct.lfOrientation = 0;
    CaptionFontStruct.lfOutPrecision = OUT_DEVICE_PRECIS;
    CaptionFontStruct.lfPitchAndFamily = FF_ROMAN;
    CaptionFontStruct.lfQuality = ANTIALIASED_QUALITY;
    CaptionFontStruct.lfStrikeOut = FALSE;
    CaptionFontStruct.lfUnderline = FALSE;
    CaptionFontStruct.lfWeight = FW_SEMIBOLD;
    CaptionFontStruct.lfWidth = 5;
    CaptionFont = CreateFontIndirect(&CaptionFontStruct);
    TextFontStruct = CaptionFontStruct;
    TextFontStruct.lfHeight = 12;
    TextFontStruct.lfEscapement = 0;
    TextFont = CreateFontIndirect(&TextFontStruct);

А рисую просто
    RECT LineRect = _TTTextRect;
    
    SetTextColor(hdc,Options->TextColor);
    SelectFont(hdc,Options->TextFont);
    for (int i=0;i<TextStrings.size();i++)
    {
        LineRect.bottom = LineRect.top+Options->TextFontStruct.lfHeight+1;
        DrawText(hdc,TextStrings[i].c_str(),TextStrings[i].length(),&LineRect,DT_CENTER);
        LineRect.top = LineRect.bottom;
    }

И в итоге получается вот что [Текст — "Текст тестового хинта [If you add a minimize button to your dialog, you will need the code below]"]

Что я не так делаю?
-=RSDN@Home 1.1.4 beta 3 rev. 233=- [silent]
Matrix has you...
Re: Нарисовать текст в несколько строк...
От: vovas Россия  
Дата: 22.11.04 06:41
Оценка: 2 (1)
Здравствуйте, Sheridan, Вы писали:

S>DrawText(hdc,TextStrings[i].c_str(),TextStrings[i].length(),&LineRect,DT_CENTER);


попробуй так DT_WORDBREAK
(ширину окна можно задать жестко а потом через
GetTextExtentPoint32() вычислить количество строк в окне —
и соответственно его высоту)
Re[2]: Нарисовать текст в несколько строк...
От: Sheridan Россия  
Дата: 22.11.04 06:44
Оценка:
Здравствуйте, vovas, Вы писали:

V>Здравствуйте, Sheridan, Вы писали:


S>>DrawText(hdc,TextStrings[i].c_str(),TextStrings[i].length(),&LineRect,DT_CENTER);


V>попробуй так DT_WORDBREAK

V>(ширину окна можно задать жестко а потом через
V>GetTextExtentPoint32() вычислить количество строк в окне —
V>и соответственно его высоту)

Гм... А поподробнее немного можно? А то я винапи мало знаю, все больше в билдере пишу...
-=RSDN@Home 1.1.4 beta 3 rev. 233=- [silent]
Matrix has you...
Re[3]: Нарисовать текст в несколько строк...
От: vovas Россия  
Дата: 22.11.04 06:54
Оценка:
Здравствуйте, Sheridan, Вы писали:

S>Гм... А поподробнее немного можно? А то я винапи мало знаю, все больше в билдере пишу...


подробнее — очень много кода
ты же юзаешь DrawText() — а это чисттый winapi
вот там вместо DT_CENTER нужно указать
DT_WORDBREAK (перенос строки в указаном
прямоугольнике).
ну а про GetTextExtentPoint32() придется почитать

вот, быстро накидал

#define WIND_WIDTH   200
CDC hDC = GetDC(); 
TCHAR szText[LEN] = {0};
::_tcscpy( szText, _TEXT("kdjfhsjkfnsdkjfsbdwejkfhwejkfhwejkfhwejk") );
int iLen = ::_tcslen( szText );
SIZE stSizeText = {0};
::GetTextExtentPoint32( hDC, szText, ::_tcslen( szText ), &stSizeText );
int iWndHeight = (stSizeText.cx / WIND_WIDTH + 1) * stSizeText.cy;
/*количество строк умножается на высоту строки*/
Re[4]: Нарисовать текст в несколько строк...
От: Sheridan Россия  
Дата: 22.11.04 07:18
Оценка:
гм... судя по
BOOL GetTextExtentPoint32(
  HDC hdc,           // handle to DC
  LPCTSTR lpString,  // text string
  int cbString,      // characters in string
  LPSIZE lpSize      // string size
);

нужен HDC... Если я его сразу после создания окна возьму — ничего страшного? И не надо ли потом ReleaseDC делать?
-=RSDN@Home 1.1.4 beta 3 rev. 233=- [silent]
Matrix has you...
Re[5]: Нарисовать текст в несколько строк...
От: Crab Украина  
Дата: 22.11.04 09:30
Оценка:
Здравствуйте, Sheridan, Вы писали:

S>гм... судя по

S>
S>BOOL GetTextExtentPoint32(
S>  HDC hdc,           // handle to DC
S>  LPCTSTR lpString,  // text string
S>  int cbString,      // characters in string
S>  LPSIZE lpSize      // string size
S>);
S>

S>нужен HDC... Если я его сразу после создания окна возьму — ничего страшного? И не надо ли потом ReleaseDC делать?

DC лучше всего брать перед вызовом GetTextExtentPoint32. А освобождать надо, да.

I'm the hero I'm back
With weapons and with magic spells
Re[5]: Нарисовать текст в несколько строк...
От: Stanky  
Дата: 22.11.04 10:35
Оценка:
> нужен HDC... Если я его сразу после создания окна возьму — ничего
> страшного?
>
Ну если он достаточно интенсивно используется, то это даже хороший вариант!!!

> И не надо ли потом ReleaseDC делать?

>
При завершении процесса система сама всё прибьёт!!!
Posted via RSDN NNTP Server 1.9 gamma
Не бойся выглядеть глупо, от этого ты выглядишь ещё глупей!!!
Re: Нарисовать текст в несколько строк...
От: Alexey Goncharov Россия  
Дата: 22.11.04 14:30
Оценка:
Здравствуйте, Sheridan, Вы писали:

S>Есть строка текста и RECT куда этот текст надо вывести в несколько строк... Даже не так... Надо перед созданием окна вычислить необходимый RECT и создать это окно нужного размера. Текст — просто строка неизвестного размера...


Попробуйте вызвать DrawText с параметром DT_CALCRECT
Re[6]: Нарисовать текст в несколько строк...
От: Sheridan Россия  
Дата: 23.11.04 07:27
Оценка:
Здравствуйте, Stanky, Вы писали:

>> И не надо ли потом ReleaseDC делать?

>>
S>При завершении процесса система сама всё прибьёт!!!
ИМХО лучьше прибить... Особенно в моем случае
-=RSDN@Home 1.1.4 beta 3 rev. 233=- [silent]
Matrix has you...
Re[6]: Нарисовать текст в несколько строк...
От: Sheridan Россия  
Дата: 23.11.04 07:36
Оценка:
Короче я сделал вот как:
    int CaptionWidth = 0; 
    int CaptionHeight = 0;
    int TextWidth = 0; 
    int TextHeight = 0;
    SIZE stSizeText = {0};
    HDC hdc = GetDC(TTWindowHandle);

    SelectFont(hdc,Options->CaptionFont);
    GetTextExtentPoint32( hdc, _caption.c_str(), _caption.length(), &stSizeText );
    CaptionHeight = stSizeText.cx;
    CaptionWidth = stSizeText.cy;

    SelectFont(hdc,Options->TextFont);
    GetTextExtentPoint32( hdc, _text.c_str(), _text.length(), &stSizeText );
    TextWidth = stSizeText.cx;
    TextHeight = stSizeText.cy;

    
    int Lines = 1;
    while (CaptionWidth + TextWidth + Options->TextBorderWidth*4 > Options->MaxToolTipWidth)
    {
        TextWidth = TextWidth/2;
        Lines++;
    }
    TextHeight = Lines * TextHeight; 

    int Width = CaptionWidth + TextWidth + Options->TextBorderWidth*4 + Options->CaptionLineWidth;
    int Height = (CaptionHeight > TextHeight ? CaptionHeight : TextHeight) + Options->TextBorderWidth*2;

    ReleaseDC(TTWindowHandle,hdc);

И в итоге чтото гдето потерял... Толи по ширине, толи по высоте... Непойму никак... Вот что получается...



Почемуто получается всегда что высота CaptionHeight больше TextHeight....
-=RSDN@Home 1.1.4 beta 3 rev. 233=- [silent]
Matrix has you...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.