2012-02-20 10 views
4

質問は簡単です。どのようにTStringGridセルに次のテキストを描画するには?DrawTextなどの関数を使用して下付き文字をレンダリングする

enter image description here

オペレーティングシステムWindows XP(またはWindows VistaまたはWindows 7)です。優先する開発環境はC++ Builder 6ですが、DelphiのC++ Builder XEのソリューションも受け入れます。好ましいAPI関数はDrawTextですが、これより優れた関数が存在する場合は問題ありません。フォントの名前がTimes New Romanで、フォントサイズは11現在、私は、セルの内容(簡易)をレンダリングするために、このメソッドを使用していますされています

void __fastcall TForm_Main::StringGrid_DrawCell(TObject *Sender, 
    int ACol, int ARow, TRect &Rect, TGridDrawState State) 
{ 
    TStringGrid *grid = (TStringGrid*)Sender; 
    if (grid == NULL) return; 

    // 1. BACKGROUND 
    grid->Canvas->Brush->Color = grid->Color; 
    grid->Canvas->FillRect(Rect); 

    // 2. TEXT 
    grid->Canvas->Font->Assign(grid->Font); // Times New Roman, 11pt 

    // horizontal centering 
    RECT RText = static_cast<RECT>(Rect); 
    AnsiString text = grid->Cells[ACol][ARow]; 
    if (!text.IsEmpty()) { 
     int text_len = strlen(text.c_str()); 
     SIZE size; 
     memset(&size, 0, sizeof(SIZE)); 
     GetTextExtentPoint32(grid->Canvas->Handle, text.c_str(), text_len, &size); 
     int offset_x = (Rect.Width() - size.cx) >> 1; 
     RText.left += offset_x; RText.right += offset_x; 

     // rendering 
     DrawText(grid->Canvas->Handle, text.c_str(), text_len, &RText, DT_LEFT | DT_VCENTER | DT_SINGLELINE); 
    } 
} 

一部の文字は、サンプルコード0x2081の添え字グリフのような特殊なUnicode文字が(1を添字に割り当てられてい)しかし、残念ながらこれは大文字Uの大文字小文字ではありません。また、これらの文字はすべてのフォントでサポートされていません(Times New Romanフォントは0x2070 - 209Fのコード範囲をサポートしません)。this Wikipediaの記事を参照してください。私はMicrosoft Wordで実装されているようなより一般的なソリューションを探しています。 MS WordはTimes New Romanフォントを使用して大文字Uを下付き文字として表示するのに問題はありません。

+1

テキストを小さいフォントサイズで、数ピクセルを通常よりも低くレンダリングしてみませんか? – GolezTrol

+1

何が最良の割合を知っていますか?最高のポジション?私は添え字付きの文字を少し下にシフトすべきだと思っています(これは私の例ではMS Wordの出力から直接取ったものではありません)。たぶんこれにいくつかの基準があります。私はこれらの詳細を知らない。アウトプットをプロフェッショナルかつ美しいものにしたい。 – truthseeker

+3

@truthseeker:プロフェッショナルに見せたい場合は、(スカラー)変数に* italics *を使用する必要があります! [これはどのように見えるのですか?](http://privat.rejbrand.se/phiu120.png) –

答えて

0

いくつかの文字を上付き文字としてレンダリングする場合は、その前に^を付ける必要があります。同様に、添え字には接頭辞_を付ける必要があります。

void __fastcall TForm_Main::StringGrid_DrawCell(TObject *Sender, int ACol, int ARow, TRect &Rect, TGridDrawState State) 
{ 
    TStringGrid *grid = (TStringGrid*)Sender; 
    if (grid == NULL) 
    { 
     return; 
    } 
    WideString wtext = L"φ_U = 120"; 
    if (wtext.IsEmpty()) return; 

    // layout 
    SIZE size; 
    memset(&size, 0, sizeof(SIZE)); 
    SSGetTextExtentPoint(grid->Canvas, wtext, size); 
    int offset_x = (Rect.Width() - size.cx + 1) >> 1; // horizontal centering 
    RECT RText = static_cast<RECT>(Rect); 
    RText.left += offset_x; 
    RText.right += offset_x; 

    // rendering 
    SetBkMode(grid->Canvas->Handle, TRANSPARENT); 
    SSDrawText(grid->Canvas, wtext, RText, DT_LEFT); 
} 

int TForm_Main::SSGetTextExtentPoint(TCanvas *canvas, WideString text, SIZE &size) 
{ 
    // Source: http://www.codeproject.com/Articles/12660/Using-Subscripts-and-Superscripts-When-Showing-Tex 
    SaveDC(canvas->Handle); 

    SIZE sz; 
    RECT outRect = 
    {0, 0, 0, 0}; 

    HFONT oldFont; 

    LOGFONT lf; 
    GetObject(canvas->Font->Handle, sizeof(LOGFONT), &lf); 

    POINT sub, sup, subofs, supofs; 

    // Calculate subscript/superscript size and offsets 
    bool use_pixel_unit = false; 
    if (lf.lfHeight < 0) 
    { 
     lf.lfHeight = MulDiv(-lf.lfHeight, 72, GetDeviceCaps(canvas->Handle, LOGPIXELSY)); 
     use_pixel_unit = true; 
    } 
    sub.x = lf.lfWidth/2; 
    sup.x = lf.lfWidth/2; 
    sub.y = lf.lfHeight/3 * 2; 
    sup.y = lf.lfHeight/3 * 2; 

    subofs.x = lf.lfWidth/2; 
    supofs.x = lf.lfWidth/2; 
    subofs.y = lf.lfHeight/6; 
    supofs.y = lf.lfHeight/3; 

    lf.lfWidth = sub.x; 
    lf.lfHeight = sub.y; 
    if (use_pixel_unit) 
    { 
     lf.lfHeight = -MulDiv(lf.lfHeight, GetDeviceCaps(canvas->Handle, LOGPIXELSY), 72); 
    } 
    HFONT SubFont; 
    SubFont = CreateFontIndirect(&lf); 

    lf.lfWidth = sup.x; 
    lf.lfHeight = sup.y; 
    HFONT SupFont; 
    if (use_pixel_unit) 
    { 
     lf.lfHeight = -MulDiv(lf.lfHeight, GetDeviceCaps(canvas->Handle, LOGPIXELSY), 72); 
    } 
    SupFont = CreateFontIndirect(&lf); 

    WideString temp = text; 
    TCHAR c; 

    // Calculate the size of the text that needs to be displayed 
    do 
    { 
     int x1  = 1, x2 = 1, x = 1; 
     WideString s = ""; 
     c   = ' '; 
     bool bFind = true; 

     // Find the first "^" or "_", indicating the sub- or superscript 
     while (bFind) 
     { 
     x1 = text.Pos(L"^"); 
     x2 = text.Pos(L"_"); 
     if ((x1 == 0) && (x2 == 0)) 
     { 
      x = 0; 
     } 
     else if ((x1 > 0) && (x2 > 0)) 
     { 
      x = min(x1, x2); 
     } 
     else if (x1 > 0) 
     { 
      x = x1; 
     } 
     else 
     { 
      x = x2; 
     } 
     if (x == 0) 
     { 
      bFind = false; 
      x  = text.Length() + 1; 
     } 
     else if (x == text.Length()) 
     { 
      bFind = false; 
     } 
     else if (text[x] != text[x + 1]) 
     { 
      bFind = false; 
      c  = text[x]; 
     } 
     else 
     { 
     x++; 
     } 
     s = s + text.SubString(1, x - 1); 
     text.Delete(1, min(x, text.Length())); 
     } 
     sz = canvas->TextExtent(s); 
     outRect.right += sz.cx; 
     if ((outRect.bottom - outRect.top) < sz.cy) 
     { 
     outRect.top = outRect.bottom - sz.cy; 
     } 

     switch (c) 
     { 
     case '^': 
     oldFont = (HFONT)SelectObject(canvas->Handle, SupFont); 
     GetTextExtentPoint32W(canvas->Handle, text.c_bstr(), 1, &sz); 
     outRect.right += sz.cx + supofs.x; 
     text.Delete(1, 1); 
     SelectObject(canvas->Handle, oldFont); 
     break; 
     case '_': 
     oldFont = (HFONT)SelectObject(canvas->Handle, SubFont); 
     GetTextExtentPoint32W(canvas->Handle, text.c_bstr(), 1, &sz); 
     outRect.right += sz.cx + subofs.x; 
     text.Delete(1, 1); 
     SelectObject(canvas->Handle, oldFont); 
     break; 
     } 
    } 
    while (c != ' '); 

    // Adjust text position 
    outRect.bottom += subofs.y; 
    outRect.top -= subofs.x; 

    size.cx = outRect.right - outRect.left; 
    size.cy = outRect.bottom - outRect.top; 

    DeleteObject(SubFont); 
    DeleteObject(SupFont); 
    // Done, restoring the device context 
    RestoreDC(canvas->Handle, -1); 
    return 0; 
} 

// --------------------------------------------------------------------------- 
int TForm_Main::SSDrawText(TCanvas *canvas, WideString text, RECT &drawRect, int justification) 
{ 
    // Source: http://www.codeproject.com/Articles/12660/Using-Subscripts-and-Superscripts-When-Showing-Tex 
    SaveDC(canvas->Handle); 

    SIZE sz; 
    RECT outRect = 
    {0, 0, 0, 0}; 

    HFONT oldFont; 
    LOGFONT lf; 
    GetObject(canvas->Font->Handle, sizeof(LOGFONT), &lf); 

    POINT sub, sup, subofs, supofs; 
    bool contains_subscript = false; 
    bool contains_superscript = false; 

    // Calculate subscript/superscript size and offsets 
    bool use_pixel_unit = false; 
    if (lf.lfHeight < 0) 
    { 
     lf.lfHeight = MulDiv(-lf.lfHeight, 72, GetDeviceCaps(canvas->Handle, LOGPIXELSY)); 
     use_pixel_unit = true; 
    } 

    sub.x = (lf.lfWidth + 1) >> 1; 
    sup.x = (lf.lfWidth + 1) >> 1; 
    sub.y = (lf.lfHeight << 1)/3; 
    sup.y = (lf.lfHeight << 1)/3; 
    if (lf.lfHeight == 10) 
    { 
     sub.y++; // make subscript a little larger 
    } 

    subofs.x = (lf.lfWidth + 1) >> 1; 
    supofs.x = (lf.lfWidth + 1) >> 1; 
    subofs.y = (lf.lfHeight + 3)/6; 
    supofs.y = (lf.lfHeight)/3; 

    long sub_shift_down = lf.lfHeight - sub.y; 

    lf.lfWidth = sub.x; 
    lf.lfHeight = sub.y; 
    if (use_pixel_unit) 
    { 
     lf.lfHeight = -MulDiv(lf.lfHeight, GetDeviceCaps(canvas->Handle, LOGPIXELSY), 72); 
    } 
    HFONT SubFont; 
    SubFont = CreateFontIndirect(&lf); 

    lf.lfWidth = sup.x; 
    lf.lfHeight = sup.y; 
    if (use_pixel_unit) 
    { 
     lf.lfHeight = -MulDiv(lf.lfHeight, GetDeviceCaps(canvas->Handle, LOGPIXELSY), 72); 
    } 
    HFONT SupFont; 
    SupFont = CreateFontIndirect(&lf); 

    WideString temp = text; 
    TCHAR c; 

    // Calculate the size of the text that needs to be displayed 
    do 
    { 
     int x1  = 1, x2 = 1, x = 1; 
     WideString s = ""; 
     c   = ' '; 
     bool bFind = true; 

     // Find the first "^" or "_", indicating the sub- or superscript 
     while (bFind) 
     { 
     x1 = text.Pos(L"^"); 
     x2 = text.Pos(L"_"); 
     if ((x1 == 0) && (x2 == 0)) 
     { 
      x = 0; 
     } 
     else if ((x1 > 0) && (x2 > 0)) 
     { 
      x = min(x1, x2); 
     } 
     else if (x1 > 0) 
     { 
      x = x1; 
     } 
     else 
     { 
      x = x2; 
     } 
     if (x == 0) 
     { 
      bFind = false; 
      x  = text.Length() + 1; 
     } 
     else if (x == text.Length()) 
     { 
      bFind = false; 
     } 
     else if (text[x] != text[x + 1]) 
     { 
      bFind = false; 
      c  = text[x]; 
     } 
     else 
     { 
      x++; 
     } 
     s = s + text.SubString(1, x - 1); 
     text.Delete(1, min(x, text.Length())); 
     } 
     sz = canvas->TextExtent(s); 
     outRect.right += sz.cx; 
     if ((outRect.bottom - outRect.top) < sz.cy) 
     { 
     outRect.top = outRect.bottom - sz.cy; 
     } 

     switch (c) 
     { 
     case '^': 
     oldFont = (HFONT)SelectObject(canvas->Handle, SupFont); 
     GetTextExtentPoint32W(canvas->Handle, text.c_bstr(), 1, &sz); 
     outRect.right += sz.cx + supofs.x; 
     text.Delete(1, 1); 
     SelectObject(canvas->Handle, oldFont); 
     contains_superscript = true; 
     break; 
     case '_': 
     oldFont = (HFONT)SelectObject(canvas->Handle, SubFont); 
     GetTextExtentPoint32W(canvas->Handle, text.c_bstr(), 1, &sz); 
     outRect.right += sz.cx + subofs.x; 
     text.Delete(1, 1); 
     SelectObject(canvas->Handle, oldFont); 
     contains_subscript = true; 
     break; 
     } 
    } 
    while (c != ' '); 

    // Adjust text position 
    if (contains_subscript) 
    { 
     outRect.bottom += subofs.y; 
    } 
    if (contains_superscript) 
    { 
     outRect.top -= supofs.y; 
    } 
    POINT Origin; 
    Origin.y = drawRect.top + (((drawRect.bottom - drawRect.top) - (outRect.bottom - outRect.top) + 1) >> 1); 

    switch (justification) 
    { 
    case DT_CENTER: 
    Origin.x = (drawRect.right - drawRect.left)/2 - (outRect.right - outRect.left)/2 + drawRect.left; 
    break; 
    case DT_LEFT: 
    Origin.x = drawRect.left; 
    break; 
    case DT_RIGHT: 
    Origin.x = drawRect.right - (outRect.right - outRect.left); 
    } 

    POINT pnt = Origin; 

    text = temp; 

    // Draw text 
    do 
    { 
     int x1  = 1, x2 = 1, x = 1; 
     WideString s = ""; 
     c   = ' '; 
     bool bFind = true; 

     // Find the first "^" or "_", indicating the sub- or superscript 
    while (bFind) 
     { 
     x = text.Pos(L"^_"); 
     x1 = text.Pos(L"^"); 
     x2 = text.Pos(L"_"); 
     if ((x1 == 0) && (x2 == 0)) 
     { 
      x = 0; 
     } 
     else if ((x1 > 0) && (x2 > 0)) 
     { 
      x = min(x1, x2); 
     } 
     else if (x1 > 0) 
     { 
      x = x1; 
     } 
     else 
     { 
      x = x2; 
     } 
     if (x == 0) 
     { 
      bFind = false; 
      x  = text.Length() + 1; 
     } 
     else if (x == text.Length()) 
     { 
      bFind = false; 
     } 
     else if (text[x] != text[x + 1]) 
     { 
      bFind = false; 
      c  = text[x]; 
     } 
     else 
     { 
      x++; 
     } 
     s = s + text.SubString(1, x - 1); 
     text.Delete(1, min(x, text.Length())); 
     } 
     // Draw main text 
     ExtTextOutW(canvas->Handle, pnt.x, pnt.y, 0, &drawRect, s.c_bstr(), s.Length(), NULL); 
     GetTextExtentPoint32W(canvas->Handle, s.c_bstr(), s.Length(), &sz); 
    pnt.x += sz.cx; 

     // Draw subscript or superscript 
     switch (c) 
     { 
     case '^': 
     oldFont = (HFONT)SelectObject(canvas->Handle, SupFont); 
     ExtTextOutW(canvas->Handle, pnt.x + supofs.x, pnt.y - supofs.y, 0, &drawRect, text.c_bstr(), 1, NULL); 
     GetTextExtentPoint32W(canvas->Handle, text.c_bstr(), 1, &sz); 
     pnt.x += sz.cx + supofs.x; 
     text.Delete(1, 1); 
     SelectObject(canvas->Handle, oldFont); 
     break; 
     case '_': 
     oldFont = (HFONT)SelectObject(canvas->Handle, SubFont); 
     ExtTextOutW(canvas->Handle, pnt.x + subofs.x, pnt.y + subofs.y + sub_shift_down, 0, &drawRect, text.c_bstr(), 1, NULL); 
     GetTextExtentPoint32W(canvas->Handle, text.c_bstr(), 1, &sz); 
     pnt.x += sz.cx + subofs.x; 
     text.Delete(1, 1); 
     SelectObject(canvas->Handle, oldFont); 
     break; 
     } 
    } 
    while (c != ' '); 

    DeleteObject(SubFont); 
    DeleteObject(SupFont); 
    // Done, restoring the device context 
    RestoreDC(canvas->Handle, -1); 
    return 0; 
} 
関連する問題