Winforms ToolStrip.BackColor mengembalikan warna yang salah

Asal mula masalah saya

Saya membuat aplikasi tiruan yang sangat sederhana di C# menggunakan winforms. Ini hanya berisi ToolStrip dan TrackBar di dalam ToolStrip itu. TrackBar seharusnya memiliki BackColor yang sama dengan ToolStrip, namun tampaknya properti ToolStrip.BackColor tidak mengembalikan warna latar belakang sebenarnya.

public Form1()
{
    //// Here the ToolStrip is created.
    //// This code is generated by the designer.
    this.InitializeComponent();
    //// Here the the TrackBar is created.
    //// I think this is impossible to do via the Designer.
    this.CreateSpeedSlider();
}

private void CreateSpeedSlider()
{
    this.toolStrip.SuspendLayout();
    this.speedSlider = new TrackBar
    {
        TickStyle = TickStyle.None,
        AutoSize = false,
        Height = this.toolStrip.Height,
        Minimum = 0,
        Maximum = 10,
        BackColor = this.toolStrip.BackColor,
    };

    this.toolStrip.Items.Add(new ToolStripControlHost(this.speedSlider));
    this.toolStrip.ResumeLayout();
}

Hasilnya adalah TrackBar putih pada ToolStrip abu-abu terang. Jadi sepertinya begitu

this.toolStrip.BackColor

tidak mengembalikan warna belakang ToolStrip yang sebenarnya digunakan untuk menggambarnya.

Namun...

Jika saya mengubah fungsi saya menjadi

private void CreateSpeedSlider()
{
    this.toolStrip.BackColor = this.toolStrip.BackColor;
    ...
}

Saya mendapatkan penggeser putih pada ToolStrip putih. Jadi...menetapkan nilai properti pada dirinya sendiri sebenarnya mengubah warna dari abu-abu muda menjadi putih???

Jadi pertanyaannya adalah...

Apakah ada cara yang baik untuk mengambil warna latar belakang ToolStrip yang benar tanpa 'peretasan' seperti itu?

Dan apakah perilaku ini disengaja atau saya melewatkan sesuatu?


person churill    schedule 14.06.2019    source sumber
comment
Kontrol ToolStrip mewarisi properti BackColor dari Formulir induk, namun tidak menyetelnya, kecuali Anda menyetelnya secara manual, dengan mempertahankan Warna netral default (putih, seharusnya Color.FromArgb(248, 248, 248)). Jadi, saat Anda menambahkan TrackBar, ia mewarisi ToolStrip BackColor, sama dengan BackColor Formulir, namun justru menyetelnya. Jadi, jika Anda ingin menghosting kontrol semi-transparan alien, atur BackColor dari TooStrip sebelum menghosting kontrol, atau atur BackColor kontrol ke warna ToolStrip yang sebenarnya.   -  person Jimi    schedule 14.06.2019


Jawaban (1)


BackColor adalah properti ambien

Control.BackColor adalah properti ambien:

Properti BackColor adalah properti ambien. Properti ambien adalah properti kontrol yang, jika tidak disetel, akan diambil dari kontrol induk. Misalnya, sebuah Button akan memiliki BackColor yang sama dengan Form induknya secara default. Untuk informasi selengkapnya tentang properti ambien, lihat kelas AmbientProperties atau ikhtisar kelas Kontrol.

Artinya diimplementasikan seperti ini (sumber):

public virtual Color BackColor
{
     get
     {
          Color c = RawBackColor; // inheritedProperties.BackColor
          if (!c.IsEmpty)
          {
               return c;
          }
          Control p = ParentInternal;
          if (p != null && p.CanAccessProperties)
          {
               c = p.BackColor;
               if (IsValidBackColor(c))
               {
                    return c;
               }
          }
          ...

Ada properti internal RawBackColor yang merupakan warna yang ditetapkan secara eksplisit untuk kontrol khusus ini. BackColor sendiri dihitung - jika warna tidak disetel secara eksplisit untuk kontrol ini, ia akan mencoba mengembalikan BackColor induknya.

ToolStrip dirender secara berbeda.

Untuk menerapkan gaya berbeda pada menu ToolStrip mendukung merender:

Kelas ToolStrip menerapkan skema rendering yang sangat berbeda dari kontrol Windows Forms lainnya. Dengan skema ini, Anda dapat dengan mudah menerapkan gaya dan tema.

Artinya, ToolStrip memiliki Renderer dan inisialisasi penyaji tersebut bergantung pada setelan sistem. Jadi, secara umum tidak ada cara mudah untuk mendapatkan warna belakang dari sebuah toolstrip.

Kemungkinannya bagus jika secara default ToolstripProfessionalRenderer digunakan. Jenis penyaji ini sebenarnya melukis latar belakang dengan gradien. Ia memiliki ColorTable properti yang, pada gilirannya, mendefinisikan MenuStripGradientBegin dan MenuStripGradientEnd.

Jadi, di sebagian besar (tapi tidak semua) kasus, Anda dapat menentukan warna belakang default untuk toolstip dengan cara ini:

var renderer = (ToolStripProfessionalRenderer)toolStrip.Renderer;
Console.WriteLine(renderer.ColorTable.MenuStripGradientBegin);
Console.WriteLine(renderer.ColorTable.MenuStripGradientEnd);

Jika Anda mencoba menghosting kontrol dengan latar belakang yang dicat seragam, seperti TrackBar, kontrol tersebut mungkin akan terlihat menonjol di strip alat yang dipenuhi gradien.

ToolStripRenderer memperhitungkan pengaturan warna secara eksplisit

Saya tidak dapat menemukan perilaku ini didokumentasikan di mana pun, tetapi menurut ToolStripRenderer sumber, latar belakang hanya dicat (diisi dengan gradien) jika RawBackColor strip alat tidak disetel:

internal bool ShouldPaintBackground(Control control)
{
    return (control.RawBackColor == Color.Empty && control.BackgroundImage == null);
}

Jadi, jika Anda secara eksplisit menyetel ToolStrip.BackColor ke warna apa pun, penyaji hanya akan menggunakan warna ini sebagai warna belakang. Perilaku membingungkan ini menjelaskan alasannya:

toolStrip.BackColor = toolStrip.BackColor;

memiliki efek nyata.

Apa yang harus dilakukan sekarang?

Saya dapat melihat banyak cara ke depan, tidak ada satupun yang bagus:

  1. Atur BackColor untuk strip alat dan track bar ke beberapa warna yang diketahui. Ini akan mematikan gradien yang indah dan indah di latar belakang toolstrip. Jika Anda tidak terlalu peduli dengan gradien, itulah cara termudah untuk melakukannya.

  2. Jadikan kontrol yang dihosting transparan, sehingga latar belakang setrip alat terlihat jelas. Ini tidak akan berfungsi untuk TrackBar karena tidak mendukung latar belakang transparan, karena alasan tertentu. Lihat pertanyaan ini, untuk opsi yang memungkinkan (saya tidak mencobanya): Latar Belakang Trackbar di TabControl.

  3. Ganti track bar OnPaint dan isi dengan gradien, sehingga menyatu dengan latar belakang strip alat. Ini kedengarannya bermasalah, tapi bisa dilakukan.

person default locale    schedule 14.06.2019
comment
Terima kasih atas jawabannya. Ada beberapa hal gila yang terjadi dalam kerangka kerja. Saya memutuskan untuk menulis metode pengecatan khusus untuk Trackbar untuk menjaga gradien di strip alat dan mengecat bagian belakang Trackbar dalam gradien yang sama. - person churill; 14.06.2019