Рисование собственного фона родительских и родительских детей в C#

Я пытаюсь использовать этот учебник, чтобы у меня была прозрачная кнопка. Он отлично работает для основного фона, но не отрисовывает других детей. Если я использую BringToFront() тогда у него нет рисунка другого ребенка, где он должен быть.

Я начал обойти это, добавив это в код:

foreach (Control child in Parent.Controls) {
    if(child != this) {
        InvokePaintBackground(child, pea);
        InvokePaint(child, pea);
    }
}

И хотя я получаю кое -что из того, что хочу, оно находится не в том месте (слева, а не посередине, где должно быть), и фигуры, нарисованные в событии рисования ребенка, также не отображаются.

Как я могу изменить так, чтобы у меня были все другие дети, дающие полную иллюзию прозрачности?

Примечание: я не беспокоюсь о том, чтобы причинять боль кому-либо, кроме других детей, так как знаю, что их нет, и есть множество других мест, где можно узнать, как рекурсивно получить всех детей.


Благодаря ответу C.Evenhuis, теперь он работает. Моя реализация проста (только один дочерний элемент), так что это мой код. Для будущих читателей обязательно прочитайте этот пост, чтобы получить полный охват.

using (PaintEventArgs pea = new PaintEventArgs(e.Graphics, rect)) {
    pea.Graphics.SetClip(rect);
    InvokePaintBackground(Parent, pea);
    InvokePaint(Parent, pea);
    foreach (Control child in Parent.Controls) {
        if (child != this) {
            pea.Graphics.ResetTransform();
            pea.Graphics.TranslateTransform(child.Left - Left, child.Top - Top);
            InvokePaintBackground(child, pea);
            InvokePaint(child, pea);
        }
    }
}

2 ответа

Решение

При рисовании все элементы управления предполагают, что их верхний левый угол находится в координате (0, 0). Это достигается установкой окна просмотра Graphics объект до координат управления перед OnPaint называется.

Чтобы нарисовать другие элементы управления, вам придется сделать это вручную:

if (child != this) 
{
    int offsetX = control.Left - Left;
    int offsetY = control.Top - Top;

    // Set the viewport to that of the control
    pevent.Graphics.TranslateTransform(offsetX, offsetY);

    // Translate the clip rectangle to the new coordinate base
    Rectangle clip = pevent.ClipRectangle;
    clip.Offset(-offsetX, -offsetY); // Ugly self-modifying struct
    PaintEventArgs clippedArgs = new PaintEventArgs(pevent.Graphics, clip);
    InvokePaintBackground(control, clippedArgs);
    InvokePaint(control, clippedArgs);
    pevent.Graphics.TranslateTransform(-offsetX, -offsetY)
}

Все становится немного сложнее, если основной элемент управления Panel содержит собственные дочерние элементы управления - они не отображаются автоматически вместе с их родителями. Если вам нужно поддержать это, я предлагаю отправить WM_PRINT сообщение родительскому элементу управления и элементам управления silbing под текущим элементом управления - для элементов управления одного уровня вы можете затем установить PRF_CHILDREN флаг, чтобы позволить ему рисовать своих потомков тоже.

Также в настоящее время вы рисуете все элементы управления родного брата - в том числе выше текущего элемента управления. Вы могли бы хотеть позволить петле идти назад и break когда вы достигнете текущего контроля. Это не будет реальной проблемой, пока вы не начнете укладывать несколько прозрачных элементов управления.

Это не ответ, но однажды мне пришлось сделать что-то подобное. Вот что я сделал:

this.SetStyle(
    ControlStyles.ResizeRedraw | 
    ControlStyles.OptimizedDoubleBuffer | 
    ControlStyles.AllPaintingInWmPaint |
    ControlStyles.SupportsTransparentBackColor |
    ControlStyles.UserPaint, true);

this.BackColor = Color.Transparent;

protected override void OnPaint(PaintEventArgs e)
{
    // TODO: Draw the button here
    base.OnPaint(e);
}

Это не привлекает детей, но работает лучше, чем InvokePaintBackground а также InvokePaint по какой-то причине. У меня было много неприятностей, когда я пытался нарисовать детей, особенно когда дети были владельцами, которых управлял сторонний контроль (я говорю действительно странные вопросы). Я задам вопрос, чтобы увидеть, есть ли другие идеи. Удачи.

Другие вопросы по тегам