2012-07-03 10 views
10

TIceTabSet(Chromeタブ)コンポーネントをいくつか更新しています。これらの変更の1つは、透明性を追加することです。テキスト以外はすべて正常に動作します。背景のアルファチャンネルが低くなるにつれて、テキストはますますぼやけてしまいます。ここにスクリーンショットがあります。Alphaを下げるとガラスの背景にテキストが描画されない

enter image description here

ここでは、タブを描画するコードです。そのほとんどはオリジナルのTIceTabSetコードです。私は単にタブを透明にするためにいくつかの変更を追加しました。サンプルのスクリーンショットではコードも少し変更されています。一番下のDrawTextコマンドは、テキストがキャンバスに描画される場所です。

procedure TIceTabSet.InnerDraw(Canvas: TCanvas; TabRect: TRect; Item: TIceTab); 
var 
    graphics : TGPGraphics; 
    Pen: TGPPen; 
    Brush: TGPSolidBrush; 
    path, linePath: TGPGraphicsPath; 
    linGrBrush: TGPLinearGradientBrush; 
    font: TGPFont; 
    solidBrush: TGPSolidBrush; 
    rectF: TGPRectF; 
    stringFormat: TGPStringFormat; 
    DC: HDC; 
    marginRight: integer; 
    iconY, iconX: integer; 
    textStart: Extended; 
    startColor, EndColor, textColor, borderColor: cardinal; 
    borderWidth: Integer; 
    TabProperties: TIceTabProperties; 
    Alpha: Byte; 
begin 
    DC := Canvas.Handle; 

    TabProperties := GetTabProperties(Item); 

    Alpha := Item.Index * 50; 

    startColor := MakeGDIPColor(TabProperties.TabStyle.StartColor, Alpha);// TabProperties.TabStyle.Alpha); 
    endColor := MakeGDIPColor(TabProperties.TabStyle.StopColor, Alpha); //TabProperties.TabStyle.Alpha); 
    textColor := MakeGDIPColor(TabProperties.Font.Color, 255); //TabProperties.TabStyle.Alpha); 
    borderColor := MakeGDIPColor(TabProperties.BorderColor, TabProperties.TabStyle.Alpha); 
    borderWidth := TabProperties.BorderWidth; 

    graphics := TGPGraphics.Create(DC); 
    Brush := TGPSolidBrush.Create(borderColor); 
    Pen:= TGPPen.Create(borderColor); 
    Font := GetGDIPFont(Canvas, FTabActive.Font); //TabProperties.Font); 
    try 
    graphics.SetSmoothingMode(SmoothingModeHighQuality); 

    pen.SetWidth(borderWidth); 

    path := TGPGraphicsPath.Create(); 
    try 
     path.AddBezier(TabRect.Left, TabRect.Bottom, TabRect.Left + FTabShape.LeftEdgeWidth/2, TabRect.Bottom, TabRect.Left + FTabShape.LeftEdgeWidth/2, TabRect.Top, TabRect.Left + FTabShape.LeftEdgeWidth, TabRect.Top); 
     path.AddLine(TabRect.Left + FTabShape.LeftEdgeWidth, TabRect.Top, TabRect.Right - FTabShape.RightEdgeWidth, TabRect.Top); 
     path.AddBezier(TabRect.Right - FTabShape.RightEdgeWidth, TabRect.Top, TabRect.Right - FTabShape.RightEdgeWidth/2, TabRect.Top, TabRect.Right - FTabShape.RightEdgeWidth/2, TabRect.Bottom, TabRect.Right, TabRect.Bottom); 

     linePath := TGPGraphicsPath.Create; 
     try 
     linePath.AddPath(path, false); 
     path.AddLine(TabRect.Right, TabRect.Bottom, TabRect.Left, TabRect.Bottom); 

     linGrBrush := TGPLinearGradientBrush.Create(
      MakePoint(0, TabRect.Top), 
      MakePoint(0, TabRect.Bottom), 
      startColor, 
      endColor); 
     try 
      graphics.DrawPath(pen, linePath); 

      graphics.FillPath(linGrBrush, path); 
     finally 
      linGrBrush.Free; 
     end; 
     finally 
     linePath.Free; 
     end; 
    finally 
     path.Free; 
    end; 

    marginRight := 0; 

    if TabDisplaysCloseButton(Item) then 
    begin 
     if (HighLightTabClose = Item) and 
     (FTabCloseButton.ShowCircle) then 
     begin 
     pen.SetWidth(1); 

     pen.SetColor(MakeGDIPColor(FTabCloseButton.CrossColorHotTrack, 255)); 
     brush.SetColor(MakeGDIPColor(FTabCloseButton.CircleColorHotTrack, 255)); 

     graphics.FillEllipse(brush, TabRect.Right - FTabShape.RightEdgeWidth - 7 - 2, 
            TabRect.Top + ((TabRect.Bottom - TabRect.Top - 7) div 2) - 3, 
            (TabRect.Right - FTabShape.RightEdgeWidth) - (TabRect.Right - FTabShape.RightEdgeWidth - 7) + 6, 
            (TabRect.Top + ((TabRect.Bottom - TabRect.Top + 7) div 2)) - (TabRect.Top + ((TabRect.Bottom - TabRect.Top - 7) div 2)) + 6); 

     graphics.DrawLine(pen, TabRect.Right - FTabShape.RightEdgeWidth - 5, TabRect.Top + ((TabRect.Bottom - TabRect.Top - 5) div 2), 
           TabRect.Right - FTabShape.RightEdgeWidth, TabRect.Top + ((TabRect.Bottom - TabRect.Top + 5) div 2)); 

     graphics.DrawLine(pen, TabRect.Right - FTabShape.RightEdgeWidth, TabRect.Top + ((TabRect.Bottom - TabRect.Top - 5) div 2), 
           TabRect.Right - FTabShape.RightEdgeWidth - 5, TabRect.Top + ((TabRect.Bottom - TabRect.Top + 5) div 2)); 
     end 
     else 
     begin 
     pen.SetWidth(2); 

     if HighlightTabClose = Item then 
      pen.SetColor(MakeGDIPColor(FTabCloseButton.CrossColorHotTrack, 255)) 
     else 
      pen.SetColor(MakeGDIPColor(FTabCloseButton.CrossColorNormal, 255)); 

     graphics.DrawLine(pen, TabRect.Right - FTabShape.RightEdgeWidth - 7, TabRect.Top + ((TabRect.Bottom - TabRect.Top - 7) div 2), 
           TabRect.Right - FTabShape.RightEdgeWidth, TabRect.Top + ((TabRect.Bottom - TabRect.Top + 7) div 2)); 

     graphics.DrawLine(pen, TabRect.Right - FTabShape.RightEdgeWidth, TabRect.Top + ((TabRect.Bottom - TabRect.Top - 7) div 2), 
           TabRect.Right - FTabShape.RightEdgeWidth - 7, TabRect.Top + ((TabRect.Bottom - TabRect.Top + 7) div 2)); 
     end; 

     marginRight := 10; 
    end; 

    solidBrush:= TGPSolidBrush.Create(MakeGDIPColor(textColor, 255)); 

    stringFormat:= TGPStringFormat.Create; 
    stringFormat.SetAlignment(StringAlignmentNear); 
    stringFormat.SetLineAlignment(StringAlignmentCenter); 
    stringFormat.SetTrimming(StringTrimmingEllipsisCharacter); 
    stringFormat.SetFormatFlags(StringFormatFlagsNoWrap); 

    SelectClipRgn(Canvas.Handle, 0); 
    textStart := TabRect.Left + FTabShape.LeftEdgeWidth; 
    iconX := 0; 
    iconY := 0; 

    if Assigned(Images) and (Item.ImageIndex <> -1) then 
    begin 
     iconY := TabRect.Top + ((TabRect.Bottom - TabRect.Top - Images.Height) div 2); 
     iconX := Round(textStart); 
     textStart := textStart + Images.Width + 4; 
    end; 

    rectF := MakeRect(textStart, TabRect.Top, TabRect.Right - textStart - FTabShape.RightEdgeWidth - marginRight, 
     TabRect.Bottom - TabRect.Top); 

    // ****** Text is drawn here ******* 
    if rectF.Width > 10 then 
     graphics.DrawString(format('Alpha: %d', [Alpha]), -1, font, rectF, stringFormat, solidBrush); 
    // ********************************* 

    finally 
    font.Free; 
    solidBrush.Free; 
    Pen.Free; 
    graphics.Free; 
    end; 

    if Assigned(Images) and 
    (Item.ImageIndex <> -1) then 
    Images.Draw(Canvas, iconX, iconY, Item.ImageIndex, true); 
end; 

フルソースhereをダウンロードできます。これは進行中の作業であることにご注意ください。完了したら、元の著者に送信されます。

アップデート1

TLamaは確かに示唆したようにコードを変更するには役立ちますが、それは問題を完全に解決しません。ここにテキストが今どのように見えるかです:

enter image description here

...ここにGoogle Chromeがどのように見えるかです:

enter image description here

アップデート2

ここでは、TextRenderingHintSingleBitPerPixelGridFitでどのように見えるかです。

enter image description here

私は最良の結果を与えるすべてのオプションとTextRenderingHintAntiAliasを試してみました。

+0

ただ、いくつかのヒント(私はあなたの仕事がまだ進行中であることを知っている)が、それはあなたの描画プロシージャ(私はあなたがそれについて知っていると思います)のフォントプロパティを混在しているようです。また、 'Font'プロパティの変更を反映するために' FIceTabSet'を 'Invalidate'するだけで、' TIceTabProperties.FFont.OnChange'イベントハンドラを実装することを忘れないでください。また、メソッドとプロパティの書式設定と順序をグループ内で保持しようとすると、セッター、メッセージハンドラ、およびプロパティが目に見える別々のグループに表示されることをお勧めします。 – TLama

+0

@TLama:コメントありがとう。私は現在、すべてを動かそうとしています。それから、私は既存のコードを整理しようとしています(2年以上経過しており、かなり注意が必要です)。 – norgepaul

+0

['TextRenderingHintSingleBitPerPixelGridFit'](http://msdn.microsoft.com/en-us/library/ms534404%28v=vs.85%29.aspx)モードを試しましたか? – TLama

答えて

13

イアンボイドは、How to draw ClearType text on Aero glass ?という素晴らしい投稿で、ガラス板にテキストをレンダリングするときにアンチエイリアスを適用する必要があります。だからあなたの問題を解決するために、あなたのコードをこのように変更しよう:

if rectF.Width > 10 then 
begin 
    if (GetParentForm.GlassFrame.Enabled) and (GetParentForm.GlassFrame.SheetOfGlass) then 
    graphics.SetTextRenderingHint(TextRenderingHintAntiAliasGridFit); 
    graphics.DrawString(Item.DisplayCaption, -1, font, rectF, stringFormat, solidBrush); 
end; 

あなたの問題をシミュレートするには、次のコードは、3種類の方法でないように、それは、ちょうどエアロガラスの板の上にテキストをレンダリングするのに十分です。

uses 
    GDIPAPI, GDIPOBJ; 

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    Font.Color := clWhite; 
    GlassFrame.SheetOfGlass := True; 
    GlassFrame.Enabled := True; 
end; 

procedure TForm1.FormPaint(Sender: TObject); 
var 
    S: WideString; 
    GPFont: TGPFont; 
    GPGraphics: TGPGraphics; 
    GPSolidBrush: TGPSolidBrush; 
    GPGraphicsPath: TGPGraphicsPath; 
begin 
    S := 'This is a sample text rendered on the sheet of Aero glass!'; 
    GPFont := TGPFont.Create(Canvas.Handle, Font.Handle); 
    GPSolidBrush := TGPSolidBrush.Create(MakeColor(GetRValue(Font.Color), 
    GetGValue(Font.Color), GetBValue(Font.Color))); 
    GPGraphicsPath := TGPGraphicsPath.Create; 
    GPGraphicsPath.AddString(S, Length(S), TGPFontFamily.Create(Font.Name), 
    GPFont.GetStyle, GPFont.GetSize, MakePoint(20.0, 60.0), nil); 
    try 
    GPGraphics := TGPGraphics.Create(Canvas.Handle); 
    try 
     GPGraphics.SetSmoothingMode(SmoothingModeAntiAlias); 
     GPGraphics.FillPath(GPSolidBrush, GPGraphicsPath); 
     GPGraphics.DrawString(S, Length(S), GPFont, MakePoint(20.0, 20.0), 
     nil, GPSolidBrush); 
     GPGraphics.SetTextRenderingHint(
     TextRenderingHintSingleBitPerPixelGridFit); 
     GPGraphics.DrawString(S, Length(S), GPFont, MakePoint(20.0, 40.0), 
     nil, GPSolidBrush); 
    finally 
     GPGraphics.Free; 
    end; 
    finally 
    GPFont.Free; 
    GPSolidBrush.Free; 
    GPGraphicsPath.Free; 
    end; 
end; 

そして、それは次の画像に結果:を有効

  1. 最初のテキストがテキストアンチエイリアスなしDrawString関数によってレンダリングされました
  2. もう一つはSmoothingModeAntiAliasスタイル
に設定スムージングモードで this articleに触発、 TextRenderingHintSingleBitPerPixelGridFitモード
  • パス充填によってレンダリングされた第三の一つに構成有効テキストアンチエイリアシングとDrawString関数によってレンダリングされました

    enter image description here

  • +0

    スクリーンショットのテキストがよさそうです。問題は、テキストが透明な背景に描かれているときに、それが空白のガラスに描かれていると、間違って見えることがあるようです。例えばあなたの2番目の行が私にとって最高に見えます。透明な背景にTextRenderingHintSingleBitPerPixelGridFitを使用すると、フォントを変更する色に関係なく、常に白で描画されます。アップデート2の画像を参照してください。 – norgepaul

    +0

    私はこの回答を受け入れましたが、ガラスに直接描画しないと100%動作しません。私が問題を見つけ出すなら、私はここに解決策を掲示します。 – norgepaul

    5

    別の方法として、テーマapi(Vista以降)で描画することができます。さまざまなシャドウ/ボーダー/グロー設定で再生すると、判読可能なテキストを表示することができます。ガラスのシートにいくつかのトライアウト:


    enter image description here

    コード(XE2):コードの残りの部分について

    procedure TForm1.FormPaint(Sender: TObject); 
    var 
        R: TRect; 
        ThemeData: HTHEME; 
        Opts: TDTTOpts; 
    begin 
        R := Rect(10, 10, 150, 30); 
        vcl.themes.DrawGlassText(Canvas.Handle, 'DrawGlassText Sample', R, 0, 3, 
         clBlack, TStyleManager.SystemStyle.GetElementDetails(ttsLabel)); 
    
    
        OffsetRect(R, 160, 0); 
        ThemeData := OpenThemeData(Handle, 'textstyle'); 
    
        Opts.dwSize := SizeOf(Opts); 
        Opts.crText := ColorToRGB(clBlack); 
        Opts.crShadow := $D0D0B0; 
        Opts.iTextShadowType := TST_SINGLE; 
        Opts.ptShadowOffset := Point(1, 1); 
        Opts.fApplyOverlay := True; 
        Opts.iGlowSize := 3; 
        Opts.dwFlags := DTT_TEXTCOLOR or DTT_SHADOWTYPE or DTT_SHADOWCOLOR 
         or DTT_SHADOWOFFSET or DTT_GLOWSIZE; 
        DrawThemeTextEx(ThemeData, Canvas.Handle, TEXT_LABEL, TS_NORMAL, 
         'DrawThemeTextEx Sample', -1, 0, @R, Opts); 
    
        OffsetRect(R, 180, 0); 
        Opts.crText := ColorToRGB(clBlack); 
        Opts.iGlowSize := 4; 
        Opts.fApplyOverlay := True; 
        Opts.dwFlags := DTT_TEXTCOLOR or DTT_GLOWSIZE; 
        DrawThemeTextEx(ThemeData, Canvas.Handle, TEXT_BODYTITLE, 0, 
         'Another Sample', -1, 0, @R, Opts); 
    
        CloseThemeData(ThemeData); 
    end; 
    
    +0

    +1、私はOPが光ることなくテキストをレンダリングしたいと思いますが、これは 'DrawThemeTextEx'関数でも可能です。 – TLama

    +0

    @TLama - グローのサイズを0に設定すると、いくつかの設定でテキストが消えるだけです。私はOPが輝きのないテキストをレンダリングしたいと思っているようだが、見ることができる限り、輝きがなくてもあらゆる種類の背景に対して読みやすいテキストを得ることは本当に難しい。 –

    +0

    残念ながら、グロー効果はタブ上に描画されたときに外見になります。しかし、良いアイデア、ありがとう。 – norgepaul