Winforms ToolStrip.BackColor ส่งกลับสีผิด

ที่มาของปัญหาของฉัน

ฉันสร้างแอปพลิเคชันจำลองที่เรียบง่ายมากใน C # โดยใช้ winforms มีเพียง ToolStrip และ TrackBar ภายใน ToolStrip นั้น TrackBar ควรมี BackColor เหมือนกับ ToolStrip แต่ดูเหมือนว่าคุณสมบัติ ToolStrip.BackColor จะไม่ส่งคืนสีพื้นหลังตามจริง

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();
}

ผลลัพธ์ที่ได้คือ TrackBar สีขาวบน ToolStrip สีเทาอ่อน ดูเหมือนว่า

this.toolStrip.BackColor

ไม่ส่งคืนสีด้านหลังของ ToolStrip ที่ใช้ในการวาดจริง

อย่างไรก็ตาม...

ถ้าฉันเปลี่ยนฟังก์ชั่นของฉันเป็น

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

ฉันได้รับแถบเลื่อนสีขาวบน ToolStrip สีขาว แล้ว...การกำหนดมูลค่าทรัพย์สินให้ตัวเอง เปลี่ยนสีจากสีเทาอ่อนเป็นสีขาวได้จริงเหรอ???

ดังนั้นคำถามคือ...

มีวิธีที่ดีในการดึงสีพื้นหลังที่ถูกต้องของ ToolStrip โดยไม่มี 'แฮ็ก' หรือไม่

และพฤติกรรมนี้เกิดขึ้นโดยเจตนาหรือฉันพลาดอะไรไป?


person churill    schedule 14.06.2019    source แหล่งที่มา
comment
ตัวควบคุม ToolStrip สืบทอดคุณสมบัติ BackColor จากแบบฟอร์มหลัก แต่ไม่ได้ตั้งค่า เว้นแต่คุณจะตั้งค่าด้วยตนเอง โดยคงสีเริ่มต้นที่ เป็นกลาง (สีขาว-ish ควรเป็น Color.FromArgb(248, 248, 248)) ดังนั้น เมื่อคุณเพิ่ม TrackBar มันจะสืบทอด ToolStrip BackColor ซึ่งเท่ากับ BackColor ของแบบฟอร์ม แต่จะตั้งค่าไว้แทน ดังนั้น หากคุณต้องการโฮสต์ส่วนควบคุม เอเลี่ยน แบบกึ่งโปร่งใส ให้ตั้งค่า BackColor ของ TooStrip ก่อนที่จะโฮสต์ส่วนควบคุม หรือตั้งค่า BackColor ของส่วนควบคุมให้เป็นสีจริงของ ToolStrip   -  person Jimi    schedule 14.06.2019


คำตอบ (1)


BackColor เป็นคุณสมบัติโดยรอบ

Control.BackColor เป็นทรัพย์สินโดยรอบ:

คุณสมบัติ BackColor เป็นคุณสมบัติโดยรอบ คุณสมบัติโดยรอบเป็นคุณสมบัติการควบคุมที่หากไม่ได้ตั้งค่า จะถูกดึงมาจากการควบคุมหลัก ตัวอย่างเช่น ปุ่มจะมี BackColor เหมือนกับฟอร์มหลักตามค่าเริ่มต้น สำหรับข้อมูลเพิ่มเติมเกี่ยวกับคุณสมบัติโดยรอบ โปรดดูคลาส AmbientProperties หรือภาพรวมของคลาสการควบคุม

หมายความว่ามีการใช้งานเช่นนี้ (แหล่งที่มา):

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;
               }
          }
          ...

มีคุณสมบัติภายใน RawBackColor ซึ่งเป็นสีที่ตั้งค่าไว้อย่างชัดเจนสำหรับการควบคุมเฉพาะนี้ BackColor ได้รับการคำนวณแล้ว - หากไม่ได้ตั้งค่าสีอย่างชัดเจนสำหรับตัวควบคุมนี้ จะพยายามส่งคืน BackColor ของพาเรนต์

ToolStrip แสดงผลแตกต่างออกไป

หากต้องการใช้สไตล์ที่แตกต่างกันสำหรับเมนู ToolStrip รองรับ การแสดงผล:

คลาส ToolStrip ใช้โครงร่างการแสดงผลที่แตกต่างอย่างมากจากตัวควบคุม Windows Forms อื่นๆ ด้วยโครงร่างนี้ คุณสามารถใช้สไตล์และธีมได้อย่างง่ายดาย

ความหมายคือ ToolStrip มี Renderer และการเริ่มต้นของตัวเรนเดอร์นั้นขึ้นอยู่กับการตั้งค่าระบบ โดยทั่วไปแล้ว ไม่มีวิธีที่ง่ายในการทำให้แถบเครื่องมือกลายเป็นสีด้านหลัง

มีโอกาสดีที่โดยค่าเริ่มต้น ToolstripProfessionalRenderer ถูกนำมาใช้ ตัวเรนเดอร์ประเภทนี้จะลงสีพื้นหลังด้วยการไล่ระดับสีจริงๆ มี ColorTable คุณสมบัติซึ่งในทางกลับกันกำหนด MenuStripGradientBegin และ MenuStripGradientEnd

ดังนั้น ในกรณีส่วนใหญ่ (แต่ไม่ใช่ทั้งหมด) คุณสามารถกำหนดสีด้านหลังเริ่มต้นสำหรับคำแนะนำเครื่องมือได้ด้วยวิธีนี้:

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

หากคุณพยายามโฮสต์การควบคุมด้วยพื้นหลังที่ทาสีสม่ำเสมอ เช่น TrackBar การควบคุมนั้นอาจจะโดดเด่นในแถบเครื่องมือที่เต็มไปด้วยการไล่ระดับสี

ToolStripRenderer คำนึงถึงสีที่ตั้งค่าอย่างชัดเจน

ฉันไม่พบพฤติกรรมนี้ที่บันทึกไว้ที่ใด แต่ตาม ToolStripRenderer แหล่งที่มา พื้นหลังถูกทาสีเท่านั้น (เต็มไปด้วยการไล่ระดับสี) หากไม่ได้ตั้งค่า RawBackColor ของแถบเครื่องมือ:

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

ดังนั้น หากคุณตั้งค่า ToolStrip.BackColor ให้เป็นสีใดๆ อย่างชัดเจน ตัวเรนเดอร์จะใช้สีนี้เป็นสีด้านหลังเท่านั้น พฤติกรรมที่น่าสับสนนี้อธิบายว่าทำไม:

toolStrip.BackColor = toolStrip.BackColor;

มีผลจริง

จะทำอย่างไรตอนนี้?

ฉันมองเห็นหนทางข้างหน้าได้หลายวิธี ไม่มีวิธีใดที่ดีเลย:

  1. ตั้งค่า BackColor สำหรับแถบเครื่องมือและแถบแทร็กให้เป็นสีที่ทราบ วิธีนี้จะฆ่าการไล่ระดับสีที่สวยงามและสวยงามในพื้นหลังแถบเครื่องมือ หากคุณไม่สนใจเรื่องการไล่ระดับสีมากนัก นั่นเป็นวิธีที่ง่ายที่สุด

  2. ทำให้การควบคุมที่เป็นโฮสต์โปร่งใส เพื่อให้พื้นหลังของแถบเครื่องมือแสดงผ่าน สิ่งนี้จะไม่ทำงานสำหรับ TrackBar เนื่องจากไม่รองรับพื้นหลังแบบโปร่งใสด้วยเหตุผลบางประการ ดูคำถามนี้สำหรับตัวเลือกที่เป็นไปได้ (ฉันไม่ได้ลองเลย): พื้นหลังของแถบแทร็กใน TabControl

  3. แทนที่ OnPaint ของแถบแทร็ก และเติมด้วยการไล่ระดับสี เพื่อให้กลมกลืนกับพื้นหลังของแถบเครื่องมือ นี่ฟังดูเป็นปัญหา แต่ทำได้

person default locale    schedule 14.06.2019
comment
ขอบคุณสำหรับคำตอบ. นั่นเป็นเรื่องบ้าๆ ที่เกิดขึ้นในกรอบงาน ฉันตัดสินใจเขียนวิธีการลงสีแบบกำหนดเองสำหรับ Trackbar เพื่อเก็บการไล่ระดับสีไว้ในแถบเครื่องมือ และทาสีด้านหลังของ Trackbar ในการไล่ระดับสีแบบเดียวกัน - person churill; 14.06.2019