Smeezy Ответов: 2

Работа с colordialog


У меня есть примерно 40 ярлыков на моей форме. Я хотел бы позволить пользователю изменить цвет меток, а затем сохранить этот цвет по умолчанию при закрытии формы. (Щелчок по самой форме приведет к удалению изменений цвета как формы, так и меток, восстановив их в тех цветах, которые были установлены вместе с установкой).

У меня он прекрасно работает с задним цветом формы, но не может заставить его работать с ярлыками. Я подозреваю, что разница заключается в том, что я смог привязать Backcolor к форме, тогда как я не знаю, как это сделать со всеми ярлыками как группой".

Спасибо

Что я уже пробовал:

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

Этот код изменяет цвет всех меток на моей форме, но не сохраняет изменения.

private void btnFcolor_Click(object sender, EventArgs e)
        {
            ColorDialog cd = new ColorDialog();
            if (cd.ShowDialog() == DialogResult.OK)

                foreach (Control l in Controls)
                {
                    if (l.GetType() == typeof(System.Windows.Forms.Label))
                    {
                        l.ForeColor = cd.Color;
                    }
                }



Этот код изменяется, сохраняет задний цвет самой формы и сохраняет ее при выходе.

private void btnColor_Click(object sender, EventArgs e)
        {
            using (var dlg = new ColorDialog())
            {
                if (dlg.ShowDialog() == DialogResult.OK)
                {
                    this.BackColor = Properties.Settings.Default.FormBackColor = dlg.Color;
                    Properties.Settings.Default.Save();
                }

Richard MacCutchan

Вы забыли включить код для сохранения настройки.

Smeezy

У меня он был там, но он не работает. Вот почему я здесь.

Richard MacCutchan

Ну вы должны объяснить, что подразумевается под - это не работает.".

Smeezy

Та же самая строка кода, которую я использовал для FormBackColor (с поправкой на FormForeColor, конечно), просто дает мне ошибки, когда я пытаюсь сделать это с forecolor. Я подумал, что это может быть связано с тем, что "foreach" повторяет метки. По шкале 1-10 с кодированием я нахожусь на твердом уровне 0,75, так что дальше этого я не могу дать вам лучшего ответа. Это просто дало мне ошибки подчеркивания.

Richard MacCutchan

"просто дает мне ошибки"
Тогда, пожалуйста, скажите нам, что это за ошибки!

Smeezy

Так вот что у меня изначально было. Проблема на данный момент заключается в том, что все, что я заменяю "FormBackColor", дает мне ошибку подчеркивания. Использование FormbackColor также не будет работать, потому что тогда он влияет только на formbackcolor, а не на метку forecolor.

частная btnFcolor_Click недействительным(объект отправителя, EventArgs в электронной)
{
Компонент colordialog кд = новый компонент colordialog();
if (cd.ShowDialog() == DialogResult.ОК)

по каждому элементу (L управление в Управление)
{
if (l.GetType() == typeof(System.Окна.Формы.Этикетка))
{
л.Свойство forecolor = кд.Цвет;
}

л.Свойство Forecolor = "Свойства".Настройки.По умолчанию.FormBackColor = cd.Color;
Свойства.Настройки.По умолчанию.Сохранить();
}
}

Richard MacCutchan

Если вы создадите проект, вы получите правильное сообщение об ошибке, которое скажет вам, что не так.

Richard MacCutchan

Я только что попробовал его, и он отлично работает.

Smeezy

Я использовал "FormBackColor", чтобы привязать изменения к цвету формы, но когда я попробовал это сделать с "FormForeColor", все, что он сделал, это изменил цвет шрифта одной кнопки. Затем я поместил все в панель, но она изменила цвет только одной этикетки.

2 Ответов

Рейтинг:
14

Richard Deeming

Элементы управления могут быть вложены в другие элементы управления; не все они являются прямыми дочерними элементами формы.

Вам понадобится рекурсивный метод для обработки всего дерева элементов управления:

private void btnFcolor_Click(object sender, EventArgs e)
{
    using (var dlg = new ColorDialog())
    {
        if (dlg.ShowDialog() == DialogResult.OK)
        {
            SetLabelColor(Controls.Cast<Control>(), dlg.Color);
            Properties.Settings.Default.FormForeColor = dlg.Color;
            Properties.Settings.Default.Save();
        }
    }
}

private void SetLabelColor(IEnumerable<Control> controls, Color color)
{
    foreach (Label label in controls.OfType<Label>())
    {
        label.ForColor = color;
    }
    foreach (Control control in controls.Where(c => c.HasChildren))
    {
        SetLabelColor(control.Controls.Cast<Control>(), color);
    }
}


Smeezy

Спасибо, Ричард. Я попробовал ваш код, но получаю ошибки "волнистой линии". В частности, слова "где" и "контролирует" (с большой буквы С). Я не совсем понимаю все, что вы здесь сказали. Могу я где - нибудь почитать об этом? Нужно ли мне добавить "использование", ссылку или что-то еще?

Richard Deeming

Where и OfType это методы LINQ. Вам понадобится using System.Linq; в самом верху вашего досье.

Язык-интегрированный запрос (LINQ) (C#) | Microsoft Docs[^]

Smeezy

Это у меня уже есть.

Richard Deeming

Ах, извините; я забыл, что коллекция элементов управления не сильно типизирована.

Вам понадобится ... .Cast<Control>() до того, как .Where(...) метод, чтобы заставить его работать.

foreach (Control control in controls.Cast<Control>().Where(c => c.HasChildren))

Richard Deeming

Или, если это выглядит немного пугающе, вы можете переместить условие внутри цикла:

foreach (Control control in controls)
{
    if (control.HasChildren)
    {
        SetLabelColor(control.Controls, color);
    }
}

Smeezy

Я попробую это сделать. У меня есть, чтобы перейти на что-то другое прямо сейчас. Я доложу, когда вернусь к этому. Спасибо.

Smeezy

Поэтому я продолжаю получать "элементы управления", подчеркнутые красным цветом, которые говорят: не удается преобразовать из "системы".Окна.Формы.Контроль.Система ControlCollection' to'.Окна.Форм.Форма.Экземпляре коллекции controlcollection в код кнопки.

Затем в методе SetLabelColor "Controls" и "Would" оба дают мне еще одно красное подчеркивание с ошибкой: "Form.ControlCollection" не содержит определения для "Controls" и не может быть найден доступный метод расширения "Controls", принимающий первый аргумент типа "Form.ControlCollection" (вы пропускаете директиву using или ссылку на сборку?)

Richard Deeming

Это раздражает - я не знаю, почему у них есть разные вложенные классы для представления коллекций элементов управления.

Попробуйте изменить SetLabelColor способ принятия решения IEnumerable<Control>, и добавление a .Cast<Control>() к .Controls коллекция, когда вы ее называете. Я обновил свой ответ с учетом изменений.

Maciej Los

5ed!

Smeezy

Привет, Ричард, я обновил информацию, как ты и просил, но все равно безуспешно. Как и раньше, метка ForeColor и кнопка Forecolor (чего я не хочу) меняются, но сохраняется только кнопка forecolor. Таким образом, кнопка forecolor меняется и сохраняется, как я и ожидал, просто это не должно происходить на кнопке! Но почему она меняется? Я не вижу ничего закодированного, чтобы это изменить. На этот раз я включил функции обратного цвета форм ниже, которые работают так, как они должны работать только в качестве ссылки.

//Возвращает FormBackColor к цвету установки по умолчанию. (это работает, как и ожидалось)
private void Form1_MouseClick(отправитель объекта, MouseEventArgs e)
{
этот.BackColor = Свойства.Настройки.По умолчанию.FormBackColor = Система.Рисование.Цвет.DarkSlateGray;
Свойства.Настройки.По умолчанию.Сохранить();
}

//Позволяет пользователю установить FormBackColor и сохранить его в качестве цвета по умолчанию. (это работает, как и ожидалось)
частная btnColor_Click недействительным(объект отправителя, EventArgs в электронной)
{
использование (var cd = new ColorDialog())
{
if (cd.ShowDialog() == DialogResult.ОК)
{
этот.BackColor = Свойства.Настройки.По умолчанию.FormBackColor = cd.Color;
Свойства.Настройки.По умолчанию.Сохранить();
}
}
}

//Создает элемент управления для изменения цвета метки forecolors. (при этом также изменяется кнопкой "цвет текста", хотя).
частный недействительными SetLabelColor(интерфейс IEnumerable&ЛТ;контроль&ГТ; управление, цвет)
{
foreach (Label label in controls.Метод oftype())
{
этикетка.Цвет текста = Цвет;
}
по каждому элементу (управление контроля в контроля.Где(c => c.HasChildren))
{
SetLabelColor(управление.Управления.Cast<control>(), цвет);
}
}

//Позволяет пользователю установить метку ForeColor и сохраняет ее в качестве цвета по умолчанию. (это позволит изменить метку и кнопку forecolors, но спасает только кнопка "цвет текста")
частная btnFcolor_Click недействительным(объект отправителя, EventArgs в электронной)
{
использование (var dlg = new ColorDialog())
{
if (dlg.ShowDialog() == DialogResult.ОК)
{
SetLabelColor(Элементы Управления.Cast<control>(), dlg.Цвет);
Свойства.Настройки.По умолчанию.FormForeColor = dlg.Цвет;
Свойства.Настройки.По умолчанию.Сохранить();
}
}
}
}
}

Richard Deeming

Это не имеет никакого смысла - .OfType<Label>() будет только перебирать элементы управления, которые являются метками, а кнопки-не метками.

Вы уверены, что не используете LinkLabel вместо а Button?

Smeezy

Да. Я перетащил объекты кнопок из "общих элементов управления". Однако я думаю, что проблема заключается в "FormForeColor".

После выбора формы я создал объект привязки с именем
FormForeColor". В настройках приложения в свойствах я затем привязал это к формам "ForeColor". Я уверен, что это влияет на все объекты в форме, однако простое использование только "Forecolor" в элементе управления btnColor (ниже) дает мне еще одну ошибку подчеркивания.

частная btnFcolor_Click недействительным(объект отправителя, EventArgs в электронной)
{
использование (var dlg = new ColorDialog())
{
if (dlg.ShowDialog() == DialogResult.ОК)
{
SetLabelColor(Элементы Управления.Cast<control>(), dlg.Цвет);
Свойства.Настройки.По умолчанию.FormForeColor = dlg.Цвет;
Свойства.Настройки.По умолчанию.Сохранить();
}
}

Richard Deeming

Привязка является наиболее вероятным виновником - почти все элементы управления в форме наследуют свой forecolor от самой формы, если они не имеют явного набора значений.

Контроль.Свойства Forecolor (Системы.Окна.Формы) | Microsoft Docs[^]
"Этот ForeColor свойство-это окружающее свойство. Окружающее свойство-это свойство элемента управления, которое, если оно не задано, извлекается из родительского элемента управления. Например, а Button будет иметь то же самое BackColor как его родитель Form по умолчанию."

Вам нужно будет либо удалить привязку, либо установить определенную ForeColor для элементов управления, которые вы не хотите менять.

NB: Если вы решите сохранить привязку, вам не нужно будет перебирать элементы управления, чтобы обновить их.

Smeezy

Я удалил привязку, и она действительно перестала влиять на цвет кнопки, но все равно не сохранит изменение.

Richard Deeming

Я не уверен, что понимаю. Вы получаете ошибку, или вы просто забыли позвонить в службу поддержки? SetLabelColor метод, когда ваша форма загружается?

Smeezy

Я этого не устанавливал. Это так же просто, как поместить "SetLabelColor;" в Form1_Load?

Richard Deeming

Да, это должно сработать:

SetLabelColor(Controls.Cast<Control>(), Properties.Settings.Default.FormForeColor);

Smeezy

Не уверен, что я когда-нибудь выйду за рамки того, где я нахожусь с кодированием! Сейчас это вроде как работает. Независимо от того, какой цвет я выберу, когда я снова открою программу, передний цвет всех меток будет красным. Я не понимаю, откуда это берется.

//Позволяет пользователю установить метку ForeColor и сохраняет ее в качестве цвета по умолчанию.
частная btnFcolor_Click недействительным(объект отправителя, EventArgs в электронной)
{
использование (var dlg = new ColorDialog())
{
if (dlg.ShowDialog() == DialogResult.ОК)
{
SetLabelColor(Элементы Управления.Cast<control>(), dlg.Цвет);
}
}

частный недействительными SetLabelColor(интерфейс IEnumerable&ЛТ;контроль&ГТ; управление, цвет)
{
foreach (Label label in controls.Метод oftype())
{
этикетка.Цвет текста = Цвет;
}
по каждому элементу (управление контроля в контроля.Где(c => c.HasChildren))
{
SetLabelColor(управление.Управления.Cast<control>(), цвет);
}
}
частный недействительными методе form1_load(объект отправителя, EventArgs в электронной)
{
SetLabelColor(Элементы Управления.Cast<control>(), Свойства.Настройки.По умолчанию.FormForeColor);
}

Richard Deeming

Вы удалили код, который обновляет настройки.

private void btnFcolor_Click(object sender, EventArgs e)
{
    using (var dlg = new ColorDialog())
    {
        if (dlg.ShowDialog() == DialogResult.OK)
        {
            SetLabelColor(Controls.Cast<Control>(), dlg.Color);
            Properties.Settings.Default.FormForeColor = dlg.Color;
            Properties.Settings.Default.Save();
        }
    }
}

Smeezy

ОК. Я только что это понял. Я забыл добавить диалог сохранения обратно!

Smeezy

Я очень ценю твою помощь Ричард! Это было поучительно, хотя бы для того, чтобы подкрепить знание о том, что мне предстоит пройти долгий путь! Однако мне нужно спросить, почему это было не так просто, как это было сделано с backcolor?

Richard Deeming

Если вы хотите изменить передний цвет всех элементов управления в форме, то должен сработать тот же подход привязки, который вы использовали для заднего цвета.

Это тот факт, что вы только хотели изменить цвет передней панели для определенного типа управления, что сделало его более сложным.

Smeezy

Понял. Еще раз спасибо!

Рейтинг:
0

Maciej Los

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


Вам нужно переопределить События onload[^] метод:
protected override void OnLoad(EventArgs e)
{
    //get color from settings
    color = ...
    this.BackColor = color;
    SetLabelColor(this.Controls, color);
    base.OnLoad(e);
}


Итак, создайте пустую форму и назовите ее ColorForm и поставьте там вышеописанный код. Затем ваша базовая форма должна наследовать от ColorForm.

public partial class YourBaseForm : ColorForm
{
 //
}