2013-05-27 3 views
13

Word 2010の[オプション]ダイアログボックスは、クリック(選択)されたときにオレンジ色になる白い「トグル」ボタンセットを使用してカテゴリセレクタを実装します。Word 2010スタイルのオプションカテゴリセレクタをシミュレートする方法

Category selection in the Word 2010 Options dialog

どのように1は、Delphiで、このような行動を再実装するのでしょうか?現在のWindowsテーマに準拠する必要があります(つまり、clWhiteではなくclWindowとしてボタンの色を指定する必要があります)。

編集:明確にするために - 私は左のカテゴリセレクタにのみ問題があります。他のすべてはかなり簡単です。

+0

XE2、私は何が大きな違いを生むべきかわからないが、 – gabr

+0

あなたは独自のコンポーネントを作ることを主張していますか、この種の機能を持つ既存のコンポーネントに興味がありますか? – LightBulb

+0

もう一度私は十分に明確ではなかった - 私はむしろ既存のコンポーネントを再利用するだろう。 – gabr

答えて

8

あなたはTButtonGroupコンポーネントを使用することができます。

VCLスタイルの使用ははるかに簡単な解決策ですが、XE2でのスタイルの使用は非常に不快です。私の意見では、この機能はXE3では実用的になりました。私は私の解決策を提出していますデフォルトの塗装方法を使用するように要求パー

here使用可能なプロジェクトの

ソースコード。

このプロの画像は画像が必要ですが、画像はプロジェクトと共に圧縮されています。

XE4でコンパイルしてテストしました。

Example of TButtonGroup with custom visual effects



type 

    TButtonGroup = class(Vcl.ButtonGroup.TButtonGroup) 
    protected 
    procedure Paint; override; 
    end; 

    TForm1 = class(TForm) 
    ButtonGroup1: TButtonGroup; 
    Panel1: TPanel; 
    procedure ButtonGroup1DrawButton(Sender: TObject; Index: Integer; 
     Canvas: TCanvas; Rect: TRect; State: TButtonDrawState); 
    procedure FormCreate(Sender: TObject); 
    procedure FormDestroy(Sender: TObject); 
    private 
    { Private declarations } 
    public 
    { Public declarations } 
    end; 

var 
    Form1: TForm1; 
    MBitmap : TBitmap; 

implementation 

{$R *.dfm} 

procedure TButtonGroup.Paint; 
var 
    R : TRect; 
begin 
    inherited; 
    R := GetClientRect; 
    R.Top := Self.Items.Count * Self.ButtonHeight; 
    {Remove the clBtnFace background default Painting} 
    Self.Canvas.FillRect(R); 
end; 

procedure TForm1.ButtonGroup1DrawButton(Sender: TObject; Index: Integer; 
    Canvas: TCanvas; Rect: TRect; State: TButtonDrawState); 
var 
    TextLeft, TextTop: Integer; 
    RectHeight: Integer; 
    ImgTop: Integer; 
    Text : String; 
    TextOffset: Integer; 
    ButtonItem: TGrpButtonItem; 
    InsertIndication: TRect; 
    DrawSkipLine : TRect; 
    TextRect: TRect; 
    OrgRect: TRect; 

begin 

    //OrgRect := Rect; //icon 
    Canvas.Font := TButtonGroup(Sender).Font; 

     if bdsSelected in State then begin 
     Canvas.CopyRect(Rect,MBitmap.Canvas, 
         System.Classes.Rect(0, 0, MBitmap.Width, MBitmap.Height)); 
     Canvas.Brush.Color := RGB(255,228,138); 
     end 
     else if bdsHot in State then 
     begin 
     Canvas.Brush.Color := RGB(194,221,244); 
     Canvas.Font.Color := clBlack; 

     end 
     else 
     Canvas.Brush.color := clWhite; 

     if not (bdsSelected in State) 
     then 
     Canvas.FillRect(Rect); 


     InflateRect(Rect, -2, -1); 


    { Compute the text location } 
    TextLeft := Rect.Left + 4; 
    RectHeight := Rect.Bottom - Rect.Top; 
    TextTop := Rect.Top + (RectHeight - Canvas.TextHeight('Wg')) div 2; { Do not localize } 
    if TextTop < Rect.Top then 
     TextTop := Rect.Top; 
    if bdsDown in State then 
    begin 
     Inc(TextTop); 
     Inc(TextLeft); 
    end; 

    ButtonItem := TButtonGroup(Sender).Items.Items[Index]; 

    TextOffset := 0; 

    { Draw the icon - if you need to display icons} 

// if (FImages <> nil) and (ButtonItem.ImageIndex > -1) and 
//  (ButtonItem.ImageIndex < FImages.Count) then 
// begin 
//  ImgTop := Rect.Top + (RectHeight - FImages.Height) div 2; 
//  if ImgTop < Rect.Top then 
//  ImgTop := Rect.Top; 
//  if bdsDown in State then 
//  Inc(ImgTop); 
//  FImages.Draw(Canvas, TextLeft - 1, ImgTop, ButtonItem.ImageIndex); 
//  TextOffset := FImages.Width + 1; 
// end; 


    { Show insert indications } 

    if [bdsInsertLeft, bdsInsertTop, bdsInsertRight, bdsInsertBottom] * State <> [] then 
    begin 
     Canvas.Brush.Color := clSkyBlue; 
     InsertIndication := Rect; 
     if bdsInsertLeft in State then 
     begin 
     Dec(InsertIndication.Left, 2); 
     InsertIndication.Right := InsertIndication.Left + 2; 
     end 
     else if bdsInsertTop in State then 
     begin 
     Dec(InsertIndication.Top); 
     InsertIndication.Bottom := InsertIndication.Top + 2; 
     end 
     else if bdsInsertRight in State then 
     begin 
     Inc(InsertIndication.Right, 2); 
     InsertIndication.Left := InsertIndication.Right - 2; 
     end 
     else if bdsInsertBottom in State then 
     begin 
     Inc(InsertIndication.Bottom); 
     InsertIndication.Top := InsertIndication.Bottom - 2; 
     end; 
     Canvas.FillRect(InsertIndication); 
     //Canvas.Brush.Color := FillColor; 
    end; 

    if gboShowCaptions in TButtonGroup(Sender).ButtonOptions then 
    begin 
     { Avoid clipping the image } 
     Inc(TextLeft, TextOffset); 
     TextRect.Left := TextLeft; 
     TextRect.Right := Rect.Right - 1; 
     TextRect.Top := TextTop; 
     TextRect.Bottom := Rect.Bottom -1; 
     Text := ButtonItem.Caption; 
     Canvas.TextRect(TextRect, Text, [tfEndEllipsis]); 
    end; 

end; 

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    MBitmap := TBitmap.Create; 
    try 
    MBitmap.LoadFromFile('bg.bmp'); 
    except 
    on E : Exception do 
     ShowMessage(E.ClassName+' error raised, with message : '+E.Message); 
    end; 

end; 

procedure TForm1.FormDestroy(Sender: TObject); 
begin 
    MBitmap.Free; 
end; 

DFM:

object Form1: TForm1 
    Left = 0 
    Top = 0 
    Caption = 'Form1' 
    ClientHeight = 398 
    ClientWidth = 287 
    Color = clBtnFace 
    Font.Charset = DEFAULT_CHARSET 
    Font.Color = clWindowText 
    Font.Height = -11 
    Font.Name = 'Tahoma' 
    Font.Style = [] 
    OldCreateOrder = False 
    Position = poScreenCenter 
    StyleElements = [] 
    OnCreate = FormCreate 
    OnDestroy = FormDestroy 
    PixelsPerInch = 96 
    TextHeight = 13 
    object Panel1: TPanel 
    AlignWithMargins = True 
    Left = 5 
    Top = 5 
    Width = 137 
    Height = 388 
    Margins.Left = 5 
    Margins.Top = 5 
    Margins.Right = 5 
    Margins.Bottom = 5 
    Align = alLeft 
    BevelKind = bkFlat 
    BevelOuter = bvNone 
    Color = clWhite 
    ParentBackground = False 
    TabOrder = 0 
    StyleElements = [seFont] 
    object ButtonGroup1: TButtonGroup 
     AlignWithMargins = True 
     Left = 4 
     Top = 4 
     Width = 125 
     Height = 378 
     Margins.Left = 4 
     Margins.Top = 4 
     Margins.Right = 4 
     Margins.Bottom = 2 
     Align = alClient 
     BevelInner = bvNone 
     BevelOuter = bvNone 
     BorderStyle = bsNone 
     ButtonOptions = [gboFullSize, gboGroupStyle, gboShowCaptions] 
     DoubleBuffered = True 
     Font.Charset = DEFAULT_CHARSET 
     Font.Color = clWindowText 
     Font.Height = -11 
     Font.Name = 'Segoe UI' 
     Font.Style = [] 
     Items = < 
     item 
      Caption = 'General' 
     end 
     item 
      Caption = 'Display' 
     end 
     item 
      Caption = 'Proofing' 
     end 
     item 
      Caption = 'Save' 
     end 
     item 
      Caption = 'Language' 
     end 
     item 
      Caption = 'Advanced' 
     end> 
     ParentDoubleBuffered = False 
     TabOrder = 0 
     OnDrawButton = ButtonGroup1DrawButton 
    end 
    end 
end 

TButtonGroupをホスティングしてそこにPanelコンテナがあり、それは単に視覚的な改善のために加え、必要とされていません。

ランタイム時に選択色を変更したい場合は、efg's Hue/Saturation methodを使用して画像の色相を変更することをお勧めします。その場合、カラーパネルは残りますが色は変わります。

VCLスタイルのサポートを得るには、ButtonGroup1DrawButtonイベントをTButtonGroupコンポーネントから切り離すだけで、デフォルトのDrawButtonイベントが起動され、そのサポートが追加されます。

+2

VCLスタイルを使用すると、Windowsテーマに従わないことを意味します –

+4

@Eric、Office 2010はWindowsテーマにも従いません! – iamjoosy

+0

あなたはどちらも正しいです:)私はまだ最初のデモ/テストコードでは、このオプションを使い始めると思います。ありがとう! – gabr

-1

私はあなたが2つのことを考えていたと思います。右側の部分のページコントロールです。 左側の部分については、いくつかのオプションがあると思います。主なものは、おそらく1つの列とスピードボタンを使用するGridLayoutです。

あまりにも難しくありませんが、ちょっと面倒です。フレームを使ってボタンの部分を入れることができます。

唯一難しいのは分離バーですが、それをサブクラス化して特定のプロパティを持つことで可能です。

よろしく、

+0

私はTSpeedButtonについて考えましたが、現在のテーマからそのスタイルを取得し、それは通常Windows 7でグレーで塗りつぶされます.TSpeedButton.Paintをオーバーライド/再実装する必要があります。既存のペイントを変更してボタンをペイントします)。 – gabr

+0

なぜマイナス1?これは古いコンパイラや新しいコンパイラでうまくいくでしょう。 -1が「古い」解決策と見なされている場合は、DNAのソフトウェアは非常に古いものですが、依然として信頼しています。 – DaveBoltman

8

スタイルがlbOwnerDrawFixed(スペーシングのサイズが重要でない場合)またはlbOwnerDrawVariableの場合はそれを使用できます。

それに応じて、OnDrawItem & OnMeasureItemを処理できます。

clWindowの使用は問題ありませんが、AFAIKオレンジ色はWindowsのテーマの一部ではありませんが、clHighlightから開始し、次に色相シフトを適用してテーマに一致するものを得ることができます。シェーディング。

色相シフトが一定であれば、自動的にテーマの色に適応します。

(オレンジ用HueShiftなし)サンプルコード:、TListBoxコンポーネントをドロップlbOwnerDrawFixedを設定し、28 ItemHeightを調整し、設定したフォントを "のSegoe UI" と以下OnDrawItem

preview

var 
    canvas : TCanvas; 
    txt : String; 
begin 
    canvas:=ListBox1.Canvas; 
    canvas.Brush.Style:=bsSolid; 
    canvas.Brush.Color:=clWindow; 
    canvas.FillRect(Rect); 
    InflateRect(Rect, -2, -2); 
    if odSelected in State then begin 
     canvas.Pen.Color:=RGB(194, 118, 43); 
     canvas.Brush.Color:=RGB(255, 228, 138); 
     canvas.RoundRect(Rect.Left, Rect.Top, Rect.Right, Rect.Bottom, 6, 6); 
     canvas.Pen.Color:=RGB(246, 200, 103); 
     canvas.RoundRect(Rect.Left+1, Rect.Top+1, Rect.Right-1, Rect.Bottom-1, 6, 6); 
    end; 
    canvas.Font.Color:=clWindowText; 
    canvas.Brush.Style:=bsClear; 
    txt:=ListBox1.Items[Index]; 
    Rect.Left:=Rect.Left+10; 
    canvas.TextRect(Rect, txt, [tfLeft, tfSingleLine, tfVerticalCenter]); 
end; 
を使用

このようなコンポーネントが複数ある場合は、TListBoxをサブクラス化することをお勧めします。また、RoundRectのアンチエイリアスを使用するには、GR32またはGDI +を使用できます。

XPとの下位互換性のため、XPでは利用できないため、 "Segoe UI"フォントを動的に設定する必要があります(XPでは "Arial"は良いフォールバック、 "Tahoma"は近くにありますが保証されません)。そこにいる)

+1

システムテーマを遵守しない別の答えにコメントし、自分自身でそのような回答を追加することは奇妙です –

+0

GDIではなくテーマ描画関数を使用するなど、実際には最良のアプローチかもしれません。 – gabr

+2

@DavidHeffernan VCLのスキンはテーマの色に従わないのですが、所有者はテーマの色を描いていてもそれに従います(暗い背景に行くと、clWindowのオーナー描画は暗く、VCLスキンはまだ白です) –

4

私たちはこの外観にTMS Control's Advanced Poly Pagerを使用します。私は非常にそれをお勧めします。これは非常に強力で柔軟なコントロールのセットです。具体的には、オフィススタイルのダイアログにはTAdvPolyListを使用し、配色をカスタム調整します。 (これはほぼ同じ良い見ていない彼らのTAdvOfficePagerに異なることに注意してください誤って2つのアップを混在させないでください。!)それはあなたがすることができます

  • 左のカテゴリセレクタを持っています
  • ページコントロールなので、右側のページ(通常のページコントロールと同じ)でコントロールするのが簡単です
  • タブとページの間に視覚的なリンクを表示します。 do(Wordにはバリアがあり、このコントロールはありません。より良い、直感的でよくリンクされたUI deisgnです)
  • 希望すればclWindowのような色定数を使用することができます。
  • イメージ、画像、リンクなどを含む、さまざまなアイテムが左パネルに表示されます。スクリーンショットには、要素のいくつかを分離する微妙な灰色の分割線があります。このコントロールでもこれを行うことができると確信していますが、カスタムペイントのTListBoxなど、ポスターから与えられたいくつかの回答と確実に関係することは難しいでしょう。
  • 素晴らしいですね!

自分のサイトの画像は実際にはOfficeの外観を模倣する方法を完全には示していませんが、これらの2つのスクリーンショット(サイトの高解像度)から、達成可能な種類のものを見ることができるはずです:

AdvPolyList Office menu emulation

Nicer menu emulation

私たちのメニューは、第二のスクリーンショットへの単純なテキスト項目(何もCと似ていますオンプレックスのようなチェックボックスや画像など - 私は彼らがあなたができることを実証するためにそこに置いたと思う)、もっとあなたのような配色を使用し、さらに各ページに青いヘッダを追加しました。

私たちは数年前にそれを購入し、決してそれを後悔していません。強くお勧めします。

+1

+1 - 私は同意します:) – Shambhala

+0

それはかなり素敵ですが、私はいつかそれをテストしたときに私はその低迷(かなりではないが)を感じることができます。 –

関連する問題