25

Windows の Aero テーマ グラス機能に対する Delphi 2009/2010 のサポート、正確には DoubleBuffered の意味、および Aero グラスとの関係について混乱しています。DoubleBuffered は VCL のプロパティであるだけでなく、 .net WinFormsにもあることがわかりました。最初は、コモン コントロール ライブラリで使用されるある種のウィンドウ スタイル ビットが設定されているのではないかと考えていました。なぜ使用するのか、いつ使用する必要があるのか​​?

[更新: ちらつきを軽減するための一般的な手法として、「ダブル バッファリング」とは何かを知っていることを述べる必要があります。 Windows 7. 以下にリンクされているブログ投稿が最も有益なようです。]

特に、DoubleBuffered プロパティに混乱しています。なぜそれが存在するのか、フォームとコントロールのガラス サポートとダブル バッファリングされたプロパティの間の関係がどのように設定されているのかを知りたいです。このような C++ の記事を読むと、ダブル バッファリングについて言及されていないことがわかります。

【追記2:以下、一部事実誤認があり訂正しました】

従来の Win32 アプリで DWM/Aero 合成をオンにしたときに、DWM/Aero 合成が引き起こす「黒がガラスになる」グリッチを回避するために、SetLayeredWindowAttributes を呼び出す方法について話している C++ 開発者を見つけました [ただし、以下のブログ リンクは、これが機能しなくなったことを示しています。 Windows 7 で、Microsoft がブロックするまで、実際には Vista で短時間しか機能しませんでした]。[間違った考えを始める]明るいマゼンタのような他の色を使用して、それをガラスの透明色に変えるべきではありませんか? [間違った考えを終わらせる]

DoubleBuffered を設定する必要がある場合と設定しない場合のルールは何ですか? そもそも DoubleBuffered が VCL に追加されたのはなぜですか? 設定するといつ問題が発生しますか?(リモート デスクトップが 1 つのケースのようですが、それが唯一のケースですか?) そして、それが設定されていない場合、ボタン テキストのレンダリングに問題が発生します。これは、Delphi がデフォルトの「ガラスとして黒をレンダリングする」を変更していないように見えるためです。 " Aero DWM で。

Aero グラスのレンダリングは基本的に奇妙で理解しにくい方法で行われているようです [この機能をラップするだけの Delphi ではなく、Windows 自体によって]、2009/2010 の内部 VCL ソース コードの多くStdCtrls のクラスは、Aero Glass で正しくレンダリングするために多くの複雑なロジックを実行する必要がありますが、まだ多くの問題があり、間違っているように見えます [更新 3: ガラスの多くのレンダリング グリッチ、VCL では、一般的なコントロール内で間違ってレンダリングされているようですが、Microsoft は修正を気にしていないようです。要するに、Delphi VCL コードの修正では、古い Windows 共通コントロール ライブラリと最新の [しかし風変わりな] Aero Glass 合成機能が互いにあまり好きではなく、特にうまく連携しないという事実を修正することはできません。このような高品質のテクノロジを構築し、それを世界に広めてくれた Microsoft に感謝します。]

そして、まだ十分に楽しくない場合。ParentDoubleBuffered があるのはなぜですか?

[7 月 30 日の更新: この質問は私にとって興味深いものです。なぜなら、大規模な既存の VCL フレームワークがある場合、この問題を解決するために Windows API に取り組むことは困難な問題であることを示していると思うからです。]

4

4 に答える 4

15

DoubleBuffer について

.NET には 1 つある可能性があり、Delphi のものと同じ名前と同じ目的を持っている可能性がありますが、Delphi はゼロから DoubleBuffer を実装しており、.NET も同じことをしていると思います。これを実装するウィンドウ スタイル ビットは使用されません。

DoubleBuffer と Glass Aero

かなり単純です。Glass 上にあるコントロールに DoubleBuffer を設定しないでください。DoubleBuffering を機能させるには、「バッファ」を初期化できる必要がありますが、Glass では何を初期化する必要がありますか? Windows 標準コントロール (TButton を含む) には DoubleBuffering は必要ありません。透明な表面と doublebuffer のような動作の両方を必要とする新しいコントロールの場合、レイヤード ウィンドウ API を使用できます。

コントロールを Glass で動作させる

ステップ1:

TForm1 = class(TForm)
...
protected
  procedure CreateWindowHandle(const Params: TCreateParams); override;
...
end;

procedure TForm15.CreateWindowHandle(const Params: TCreateParams);
begin
  inherited;
  SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_LAYERED);
  SetLayeredWindowAttributes(Handle, RGB(60, 60, 60), 0, LWA_COLORKEY);
end;

ステップ 2、これはフォームの OnPaint ハンドラである必要があります。

procedure TForm15.FormPaint(Sender: TObject);
var rClientRect:TRect;
begin
  if GlassFrame.Enabled then
  begin
    rClientRect := ClientRect;

    Canvas.Brush.Color := RGB(60, 60, 60);
    Canvas.Brush.Style := bsSolid;
    Canvas.FillRect(rClientRect);

    if not GlassFrame.SheetOfGlass then
    begin
      rClientRect.Top := rClientRect.Top + GlassFrame.Top;
      rClientRect.Left := rClientRect.Left + GlassFrame.Left;
      rClientRect.Right := rClientRect.Right - GlassFrame.Right;
      rClientRect.Bottom := rClientRect.Bottom - GlassFrame.Bottom;
      Canvas.Brush.Color := clBtnFace;
      Canvas.FillRect(rClientRect);
    end;
  end;
end;

ステップ 3 : GlassFrame.Enabled = True; を設定します。他のすべての Glass プロパティを設定し、好きな場所にコントロールをフォームに追加します。Glass またはその他の場所にある可能性があります。コントロールに「DoubleBuffered = True」がないことを確認してください。それだけです、楽しんでください。TButton、TCkBox、および TEdit でテストしました。

... 編集 ...

残念ながら、この方法を使用すると、「ガラス」は 100% 透明な表面として扱われ、そうではありません。ガラスのように見えますが、ガラスのようには動作しません。100% の透明度の問題は、その透明な領域をクリックすると、クリックがウィンドウの後ろのウィンドウに移動することです。最悪。

この記事を書いている時点では、元のガラスのデフォルトの BLACK キーの色を変更する API はないと確信しています (Google は、ガラス上にあるコントロールにカスタム描画を使用する必要がある方法について、数え切れないほどのブログやフォーラムの投稿を見つけました。MSDN の DWM 関数のリストでそれを変更する関数)。デフォルトの BLACK カラーを変更しないと、ほとんどのコントロールは適切にレンダリングできません。これは、clWindowText を使用してテキストを書き込み、それが BLACK であるためです。いくつかのフォーラムで提案されているトリックの 1 つは、SetLayeredWindowAttributes API を使用して透過色を変更することです。そしてそれはうまくいきます!それが完了すると、コントロールに黒いテキストがスローされますが、残念ながらガラスはもはやガラスではなく、ガラスはガラスのように見えますが、100% の透明度のように動作します。これはこのソリューションをほとんど無効にし、Microsoft 側の二重基準を示しています。元の BLACK は 100% の透明度のように動作しませんが、より良いものに変更すると 100% の透明度のように動作します。

私の意見では、Glass でカスタム コントロールを使用するという一般的な考え方は間違っています。それが唯一うまくいくかもしれませんが、それは間違っています。なぜなら、私たちはプラットフォーム全体で一貫したコントロールを使用することになっているからです: カスタム コントロールを提案すると、一貫性のない Winamp のようなアプリケーションへの扉が開かれ、各ユーザーがホイールを再作成します。芸術的なアイデアに合わせてください。開発者が特定のウィンドウ コントロールを忠実に再作成し、ガラス上で動作させることができたとしても、「修正」は一時的なものであり、次のバージョンのウィンドウ用に再作成する必要があります。言うまでもなく、既存のバージョンのウィンドウにはおそらく複数のバリアントが必要です。

もう 1 つの解決策は、レイヤード ウィンドウを UpdateLayeredWindow と共に使用することです。しかし、それは非常に多くの理由で苦痛です。

これは私にとって行き止まりです。しかし、私は質問に「お気に入り」フラグを付けます。もっと良いものが表示されたら、それについて知りたいです。

于 2010-07-29T16:42:23.263 に答える
7

あなたの質問は、Delphi Haven の CR からのブログ投稿につながりました...

Stack Overflow を見ていると、Aero ガラスに関するかなり詳細な質問 (一連の質問) に気付きました。

于 2010-07-29T10:49:00.840 に答える
3

DoubleBuffered は、ちらつきを減らすために使用される標準的なグラフィック技術です。基本的に、フォームの新しいバージョンを 2 番目のキャンバスに描画してから、現在のキャンバスと交換します。描画プロセスが遅くても、そのスワップは高速です。それと Aero の間に直接的な関係はありません。どちらかまたは両方を個別に使用できます。Delphi ではダブル バッファリングが非常に長い間使用されてきましたが、現在では画面の更新ごとのプロセッサ サイクルが大幅に増加しており、その必要性は少なくなっています。それがあなたがそれについて聞いたことがない理由かもしれません。

ダブル バッファリングは、リアクティブにのみ使用する必要があります。アプリが画面を再描画しているときにちらつきが見られる場合は、それをオンにして、何が起こるかを確認してください。その場合、最初の手段は DisableUpdates/EnableUpdates (それらについては Delphi ヘルプを参照) と Windows API LockWindowUpdate (同上) になります。

ParentDoubleBuffered は、ほとんどの Parent... プロパティと同様に、このフォームがその親の DoubleBuffered プロパティを使用するかどうかを示します。これにより、アプリのメイン フォームで一度プロパティを設定するだけで、作成するすべてのフォームに影響を与えることができます。または、そのプロパティを false に設定した場合。

これは、下位互換性のあるコードを使用している場合の典型的な状況です。今日ではめったに使用されないものの、動作する (そして必要な場合もある) ものがあります。ほとんどの人はそれらについて心配する必要はありません。ほとんどの人にとって、それらはただそこにあり、無視することができますが、私たちの中には、それらがどうしても必要な人もいます (ちらつきを止めるために、時折複雑なパターンで再描画する非常に複雑なフォームがいくつかあります)。

于 2010-07-29T06:08:32.620 に答える
1

OK、少しまっすぐにしようと思います。

まず第一に、ダブルバッファリングは、画面上のレンダリングに関しては非常に標準的な手法です。たとえば、テキストエディタコンポーネントで常に使用しています。テキストを再描画する必要があると想像してください。非常に簡単に言えば、最初にクライアントの長方形全体を多かれ少なかれクリアしFillRect(ClientRect)、次に最初の文字から最後の文字まで、それぞれ最初の文字から最後の文字まで線を引きます。しかし、これはエンドユーザーには非常に醜く見え、ほぼ同じテキストコンテンツの2つの状態の間で、表示がクリアされた状態で数ミリ秒程度になります。

解決策は、すべての描画をオフスクリーンビットマップに実行し、完了したらオフスクリーンビットマップを画面に描画することです。次に、前のフレームと新しいフレームが同一である場合、画面に数ミリ秒の間空の白い長方形が表示される非ダブルバッファの場合とは対照的に、表示には何も起こりません。ちらつきます。私は常にすべてのビジュアルコントロールにダブルバッファリングを使用しています。これにより、ビジュアルコントロールの品質と感触が大幅に向上します。ギガバイトのメモリ(RAM)を備えた最新のシステムでは、メモリ使用量の増加は決して問題ではありません。そして、ほとんどすべての場合、バッファのスワッピングは十分に高速です(ただし、コピーするピクセルはかなりあります)。

多くの場合、ウィンドウのサイズを変更するときに、ダブルバッファリングの欠如を観察できます。時々彼らはh**lのようにちらつきます。OpenGLなどのテクノロジが本質的にダブルバッファリングされていることに気付くのも興味深いかもしれません(ほとんどの場合、少なくとも)。

したがって、ダブルバッファリングは、特にガラス板とは何の関係もありません。実際、Delphiのほとんどの子孫には、プロパティとプロパティTWinControlがあります(参照)。DoubleBufferedParentDoubleBuffered

ParentDoubleBufferedプロパティは、、、、などに関連するのと同じ方法DoubleBufferedで関連付けられます。これは、コントロールが親ウィンドウからパラメータの値を継承するかどうかを決定するだけです。ParentColorColorParentShowHintShowHintParentFontFont

次に、ガラスについての質問に移ります。まあ、少なくともVCLアプリケーションでは、ガラスのシート(またはガラスフレーム)にコントロールを追加するのは一般的に厄介であることは非常に一般的な知識です。誰かがそれを適切に行う方法を議論する長いブログ記事を書くべきです...

于 2010-07-29T12:14:43.860 に答える