8

私は、Delphi ツールバーのやや厄介な点に気付きました。TToolbarアイコンの論理グループを持つ があります。グループ化を目立たせるために、 style の区切りボタンを使用したいと思いますtbsDivider

これを行うと、次のようになります。

ここに画像の説明を入力

各アイコン間の二重の垂直線に注意してください。右側のものは、区切りツール ボタンの中央にあります。左側のものは、区切りツール ボタンの左端にあります。

したがって、tbsSeparator中央の行を削除するものに切り替えることができます。

ここに画像の説明を入力

しかし、仕切りを真ん中にしたいので、私はそれには熱心ではありません.

実際のアプリの古いバージョンを調べたところ、中央にセパレーターがあることがわかりました。Windowsテーマが無効になっている場合に可能のようです。tbsDividerアプリケーション マニフェストを削除すると、次のようになります。

ここに画像の説明を入力

それが私が探しているレイアウトです。これは、テーマがアクティブなときに達成できますか?

Embarcadero フォーラムでこの問題に関する議論を見つけましたが、有用な洞察はありませんでした: https://forums.embarcadero.com/message.jspa?messageID=467842

完全を期すために、.dfm ファイルからの適切な抜粋を次に示します。

object ToolButton1: TToolButton
  Left = 0
  Top = 0
  ImageIndex = 0
end
object ToolButton2: TToolButton
  Left = 23
  Top = 0
  Width = 16
  ImageIndex = 1
  Style = tbsDivider
end
object ToolButton3: TToolButton
  Left = 39
  Top = 0
  ImageIndex = 1
end
object ToolButton4: TToolButton
  Left = 62
  Top = 0
  Width = 16
  ImageIndex = 2
  Style = tbsDivider
end
object ToolButton5: TToolButton
  Left = 78
  Top = 0
  ImageIndex = 2
end
4

3 に答える 3

4

これは、私には VCL の欠陥のように見えます。このtbsDividerスタイルは、Win32 の同等のスタイルにマップされません。そのスタイルのツール ボタンは、スタイルとまったく同じ方法で VCL に実装されますtbsSeparatorが、カスタム ペイント メソッドを使用します。これは次から抽出されTToolButton.Paintます。

if Style = tbsDivider then
  with Canvas do
  begin
    R := Rect(Width div 2 - 1, 0, Width, Height);
    if StyleServices.Enabled then
    begin
      Details := StyleServices.GetElementDetails(ttbSeparatorNormal);
      StyleServices.DrawElement(Handle, Details, R);
    end
    else
      DrawEdge(Handle, R, EDGE_ETCHED, BF_LEFT)
  end;

v6 より前の comctl32 の昔は、スタイルは Win32スタイルのツール ボタンtbsSeparatorにマップされていました。TBSTYLE_SEPまた、v6 より前の comctl32 では、垂直線のないスペースとして単純にレンダリングされます。VCL の設計者は明らかにもっとや​​りたいと思っておりtbsDivider、上記のカスタム ペインティングを追加しました。

v6 comctl32 に早送りします。TBSTYLE_SEPコモン コントロールは、すべてのセパレータの左端に垂直線を描画します。したがって、上記のコードは、セパレーターの中央に余分な垂直線を追加するだけです。

tbsDivider次のようにコードを変更することで、a から左側の垂直線を取り除こうとすることができます。

if Style = tbsDivider then
  with Canvas do
  begin
    if StyleServices.Enabled then
    begin
      //re-paint the background to remove the vertical line drawn
      //for the standard separator button
      R := Rect(0, 0, Width, Height);
      StyleServices.DrawParentBackground(FToolBar.Handle, Handle, nil, False, R);
    end;

    R := Rect(Width div 2 - 1, 0, Width, Height);
    if StyleServices.Enabled then
    begin
      Details := StyleServices.GetElementDetails(ttbSeparatorNormal);
      StyleServices.DrawElement(Handle, Details, R);
    end
    else
      DrawEdge(Handle, R, EDGE_ETCHED, BF_LEFT)
  end;

しかし、左手の線を描いてから塗りつぶすとちらつきが多くてうまくいきません。

VCL の設計者は、v6 comctl32 への移行時に、この難解な詳細を単純に見落としていたのではないかと思います。

そのうちQCレポートを提出します。

于 2012-09-28T19:06:28.160 に答える
3

すでに説明したように、オペレーティング システムの変更により、TToolBar を使用してこれを行うことはできません。

ただし、ActionToolBars を使用すると、現在のバージョンの Delphi (XE6) と Windows 8.1/2012 R2 テーマを使用しても、目的を達成できます。手順は次のとおりです。

  1. アクション マネージャーを作成する
  2. 必要な数のアクションを追加します
  3. ImageList (および無効なメニュー項目用の別のオプション) を追加します。
  4. それぞれのアクションを画像に関連付けます
  5. ActionToolBar をフォームに追加する
  6. ツールバーに表示する各アクションをツールバーにドラッグ アンド ドロップします。
  7. ツールバーの個々のアクションを ShowCaption := False に設定します (必要な場合)。
  8. [ドラッグしてセパレーターを作成] (ActionManager エディターから) ボックスをドラッグ アンド ドロップして、セパレーターを追加します。
  9. ActionClientItems (アクションを ActionTooLBar にドラッグ アンド ドロップしたときに作成される) を配置したい場所にドラッグ アンド ドロップします。

最終結果 - アイコンの間に仕切りがある見栄えの良いアプリ。

ここに画像の説明を入力

于 2014-08-22T19:13:41.210 に答える
3

ネイティブ コントロールは、ツールバーがフラット スタイルの場合、区切りボタンの垂直線を描画します。したがって、フラット スタイルを削除すると、VCL の分割線だけが残ります。アプリケーションがテーマ化されている場合、スタイルを安全に削除できます。テーマ化されたツールバー ボタンはフラット スタイルを考慮しません (なぜツールバー セパレーターがそうするのか、私にはわかりません)。ただし、テーマを無効にすると、再び 2 行になります。その場合、仕切りの代わりに区切りを維持する方が良い選択肢のようです。

ドキュメントFlatに記載されているように、プロパティの設定を解除すると何らかの効果があると推測できます。ただし、有効な場合は無条件に有効にします。したがって、API 呼び出しが必要です。TToolBar.CreateParamsStyleServices

procedure TForm1.FormCreate(Sender: TObject);
var
  TbStyle: DWORD;
begin
  if StyleServices.Enabled then begin
    TbStyle := SendMessage(ToolBar1.Handle, TB_GETSTYLE, 0, 0);
    SendMessage(Toolbar1.Handle, TB_SETSTYLE, 0, TbStyle and not TBSTYLE_FLAT);
  end;
end;


これにより、問題の一部が解消されます。残りの部分は、分割線が 2 つのボタン間の正確な中央にないことです。ここでの VCL の問題は、線自体を描画したくないということです。そのため、セパレーターの左側にセパレーター線を描画するテーマ API を呼び出します。これを回避するために、VCL はセパレータの四角形の右半分を API に渡し、線はほぼ中央になります。テーマ API が描画する場所を正確に伝える方法があるかどうかはわかりません。

于 2012-09-29T01:09:24.073 に答える