Ответы пользователя по тегу Windows Forms
  • Почему счётчик таймера на windows forms увеличивается на 2, а не на 1?

    FoggyFinder
    @FoggyFinder
    Дело в том что существует 2 разные подписки на событие Tick - одно "автоматическое" созданное конструктором форм и второе "собственное".

    VS показывает все ссылки если нажать на "reference" вверху:

    614b6a2b8e3c2686381595.png

    Удалив одну из них получим ожидаемое поведение.
    Ответ написан
    Комментировать
  • Разные View в WinForms?

    FoggyFinder
    @FoggyFinder
    Используйте обычный UserControl в качестве "страницы" (экраны), а для их отображения выберите ту панель которая подходит. В простейшем случае это может быть обычная Panel
    Ответ написан
  • Как заполнить treeview ( treenode ) данными из datatable?

    FoggyFinder
    @FoggyFinder
    Можно преобразовать DataTable к строго типизированной коллекции с помощью метода AsEnumerable. Тогда вы сможете сделать группировку значений с помощью метода GroupBy.

    После этого заполнить TreeView не составит труда.

    Пример

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            var treeView = new TreeView
            {
                Dock = DockStyle.Fill
            };
            this.Controls.Add(treeView);
    
            var dt = GetDataTable();
            PopulateTreeViewFromDataTable(treeView, dt);
        }
    
        private DataTable GetDataTable()
        {
            var dt = new DataTable("Цемент");
    
            dt.Columns.AddRange(new[] {
                new DataColumn("Name"),
                new DataColumn("NameOfCement")
            });
    
            dt.Rows.Add("Портланд", "Вихрь");
            dt.Rows.Add("Романцемент", "Тайга");
            dt.Rows.Add("Романцемент", "Свой");
            dt.Rows.Add("Алумацемент", "Курон");
    
            return dt;
        }
    
        public void PopulateTreeViewFromDataTable(TreeView tv, DataTable dataTable)
        {
            var data =
                dataTable
                    .AsEnumerable()
                    .Select(row => new
                    {
                        Name = row.Field<string>("Name"),
                        Cement = row.Field<string>("NameOfCement")
                    })
                    .GroupBy(x => x.Name);
    
            tv.Nodes.Clear();
    
            var root = tv.Nodes.Add(dataTable.TableName);
            foreach (var gr in data)
            {
                var node = root.Nodes.Add(gr.Key);
                foreach (var subItem in gr)
                {
                    node.Nodes.Add(subItem.Cement);
                }
            }
        }
    }


    Результат

    60856a498cd61836541563.jpeg
    Ответ написан
    Комментировать
  • Как выделить цветом те элементы первой матрицы, которые больше за соответствующие элементы второй матрицы c#?

    FoggyFinder
    @FoggyFinder
    Нужно применять стиль не ко всему столбцу, а к каждой ячейке по отдельности.

    Просто замените

    dataGridView1.Columns[j].DefaultCellStyle.BackColor = Color.Chartreuse;


    на

    dataGridView1[j, i].Style.BackColor = Color.Chartreuse;


    для ветки else - аналогично.

    По остальному:

    * Посмотрите границы циклов, оба раза используете количество столбцов - границы для второго должны определятся количеством строк

    Обновлено (исправлена опечатка)

    Должно получится примерно так

    private void task1_Click(object sender, EventArgs e)
    {
        int n1, n2;
        for (int j = 0; j < dataGridView1.ColumnCount; j++)
        {
            for (int i = 0; i < dataGridView1.RowCount; i++)
            {
                if (int.TryParse(dataGridView1[j, i].Value.ToString(), out n1) 
                    && int.TryParse(dataGridView2[j, i].Value.ToString(), out n2))
                {
                    if (n1 > n2)
                    {
                        dataGridView1[j, i].Style.BackColor = Color.Chartreuse;
                    }
                    else
                    {
                        dataGridView1[j, i].Style.BackColor = Color.White;
                    }
                }
            }
        }
    
        task2.Enabled = true;
    }
    Ответ написан
    3 комментария
  • Как рисовать в PictureBox на второй форме?

    FoggyFinder
    @FoggyFinder
    Удобнее всего выполнять рисование в обработчике события Paint. Если в какой-то момент нужно обновить отображение, то следует вызвать перерисовку.

    Пример, на основе вашего кода

    readonly int[] q;
    public Form2(int[] q)
    {
        InitializeComponent();
        this.q = q;
        this.WindowState = FormWindowState.Maximized;
        Size size = new Size(Screen.PrimaryScreen.WorkingArea.Width,
            Screen.PrimaryScreen.WorkingArea.Height);
        pictureBox1.Size = size;
        pictureBox1.Paint += PictureBox_Paint;
    }
    
    private void PictureBox_Paint(object sender, PaintEventArgs e)
    {
        Graphics g = e.Graphics;
        g.Clear(Color.FromArgb(q[2], q[3], q[4]));
        for (int i = 0; i < pictureBox1.Width; i += q[0])
        {
            for (int j = 0; j < pictureBox1.Height; j += q[0])
            {
                g.FillRectangle(new SolidBrush(Color.FromArgb(q[5], q[6], q[7])), i, j, q[1], q[1]);
            }
        }
    }


    Небольшой комментарий - совет не относящийся непосредственно к вопросу:

    Не передавайте массив в параметрах, создайте класс со свойствами чьи названия будут отражать смысл значений и используйте его.
    Ответ написан
  • Как построить график функции в windows forms c#?

    FoggyFinder
    @FoggyFinder
    Тут у вас сразу несколько ошибок:

    1. Нужно явно приводить к double иначе при делении двух int получите тоже целое.
    2. Вы берете очень большие границы. Рост знаменателя намного превышает скорость роста числителя. Сами посмотрите: возведите 50 в куб, что получите? График вы конечно построите, но наглядности будет немного.

    Что более важно: ваш отрезок OA = 2*a, а это значит что ваша правая граница точно должна быть меньше чем 2*a;

    3. Посмотрите как задана функция - в виде квадрата. Извлекая корень вы должны не забывать про нижнюю ветку - ту которую дают отрицательные значения y.
    Насколько мне известно возможности стандартного контрола довольно ограничены - вам придется заносить значения во вторую линию.

    Собирая все вместе, попробуйте что-то вроде такого:

    double a = 3;
    double step = 0.1;
    
    for (double x = 0; x < 2 * a - 1; x += step)
    {
        var n = x * x * x;
        var d = 2 * a - x;
        chart1.Series[0].Points.AddXY(x, Math.Sqrt(n / d));
        chart1.Series[1].Points.AddXY(x, -Math.Sqrt(n / d));
    }


    Здесь 1 (x < 2 * a - 1) вычитается только для примера, чтобы вы сравнили результат. В реальности вам придется определять границу более сложным путем чтобы для разных a и левой границы (x) получать наглядное представление. Но, по крайней мере, у вас есть от чего отталкиваться.
    Ответ написан
    Комментировать
  • Как сделать, что бы после закрытия messageboxа не открывались следующие?

    FoggyFinder
    @FoggyFinder
    Не уверен что правильно понял проблему, поэтому если окажется что мой ответ не подходит не стесняйтесь уточнять и спрашивать в комментариях, будем разбираться как починить.

    Код в обработчике button1_Click выполняется последовательно. После того как сработает первое условие вы уменьшаете значение на единицу и следующий if тоже становится верным.

    Первое что вам нужно сделать это вынести количество попыток в приватную переменную.
    kolvopotytok не самое подходящее название (и хотя я, например, могу понять что тут имеется ввиду количество попыток) лучше использовать названия на английском. Давайте возьмем countOfAttempts . Так как вы хотите отслеживать количество, то вам нужно завести еще одну переменную для учета их изначального (максимального) числа:

    public Form2(int digitfrom, int digitto)
    {
        InitializeComponent();
    
        Random rnd = new Random();
        r = rnd.Next(digitfrom, digitto);
        maxCountOfAttempts = countOfAttempts = 3;
    }
    private int r;
    private int maxCountOfAttempts, countOfAttempts;


    Затем вы можете заметить что каждый раз код внутри проверочного условия одинаковый.
    А теперь представьте, что диапазон будет достаточно широкий (скажем около сотни), а количество попыток увеличиться до 10. Копировать один и тот-же участок раз за разом не слишком эффективно. Давайте тогда вынесем весь код в отдельную функцию, которая будет принимать значение и в зависимости от него выводить информационное сообщение. Если пользователь угадал, то функция вернет true, в противном случае - false:

    private bool CheckResult(int a)
    {
        if (a == r)
        {
            MessageBox.Show($"Поздравляем!!! Вы угадали число с {countOfAttempts - 1} раза.");
            return true;
        }
        else if (a > r)
        {
            MessageBox.Show($"Число которое загадал ИИ меньше вашего!\nУ вас осталось {countOfAttempts - 1} попытки.");
            return false;
        }
        else
        {
    
            MessageBox.Show($"Число которое загадал ИИ больше вашего!\nУ вас осталось {countOfAttempts - 1} попытки.");
            return false;
        }
    }


    Теперь немного изменим сам обработчик:

    private void button1_Click(object sender, EventArgs e)
    {
        if (IsDigitsOnly(answer.Text))
        {
            int a = Convert.ToInt32(answer.Text);
            if (CheckResult(a))
                this.Close();
            else
            {
                countOfAttempts--;
                if (countOfAttempts == 0)
                {
                    MessageBox.Show("К сожелению вы проиграли\nЗагаданное число: " + r);
                    this.Close();
                }
            }
        }
        else
        {
            MessageBox.Show("Некорректный ввод данных", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
        answer.Clear();
    }


    Должно работать. Как видите код достаточно близкий к вашему, но в то-же время немного понятнее.

    И, если позволите, небольшой совет на будущее: старайтесь избегать использования goto.
    Ответ написан
    Комментировать
  • Вывод текста в label при клике c# windows forms?

    FoggyFinder
    @FoggyFinder
    В WinForms проектах конструктор форм прячет детали пользовательского интерфейса в файл Form1.Designer.cs (вместо Form1 будет название конкретного класса). Поэтому при копировании из других проектов или примеров нужно не забывать перенести также все подписки.

    Чтобы проверить их наличие (или отсутствие), в конструкторе форм выделите элемент и перейдите к просмотру его свойств (Properties).

    По умолчанию откроется вкладка свойств контрола. Для просмотра информации о событиях нужно перейти на следующую за ней (с нарисованной молнией):

    5db6e64c1bdca244908136.jpeg

    В списке находите требуемый элемент. Если справа ничего не присвоено, значит дело в отсутствующей подписке. Через выпадающий список (ComboBox) выбираете обработчик из доступных:

    5db6e7036cb33351827234.jpeg

    Запускаете, проверяете.
    Если все работает, значит проблема найдена правильно.

    Для подписки не обязательно использовать конструктор форм, можно создавать их самостоятельно, например, в конструкторе форм:

    button1.Click += Button1_Click;

    Но лучше придерживаться одного стиля, так и код будет проще восприниматься и лишних подписок не будет.
    Ответ написан
    Комментировать
  • Обработка события нажатия ЛКМ на заголовке DGV?

    FoggyFinder
    @FoggyFinder
    Обрабатывайте общее событие CellMouseClick. У выделенной на скриншоте ячейки оба индекса равны -1:

    private void DataGridView1_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
    {
        var row = e.RowIndex;
        var column = e.ColumnIndex;
    
        if(row == -1 && column == -1)
        {
            // Do something
        }
    }
    Ответ написан
  • Если объект соприкасается с чёрным цветом, то выполнять вывод в консоль?

    FoggyFinder
    @FoggyFinder
    Вначале небольшое лирическое отступление.

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

    Теперь к вопросу.

    Ваш объект (obj) это PictureBox , элемент управления, у которого, что не удивительно, нет своего метода intersects.

    Но вы можете использовать свойство Bounds чтобы получить местоположение и размеры ваших объектов:

    if(pictureBox1.Bounds.IntersectsWith(pictureBox2.Bounds))
    {
    // put your code here
    }


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

    Например, если ваш объект может менять цвета, а вас интересует является ли он черным, то в момент смены цветы храните это состояние (isBlack) в свойстве Tag вашего pictureBox.

    Если вы пишите какую-то простую игру по типу змейки, то пока не завязли, советую уделить немного времени на разделение кода на смысловые части - определите классы описывающую ваши объекты, логику взаимодействия и отдельно их отображение на форме.
    Ответ написан
    5 комментариев
  • Как проверить были ли все кликнуты элементы?

    FoggyFinder
    @FoggyFinder
    Рассматривайте "было ли нажатие" как состояние.

    Создайте новый, отдельный класс, который будет содержат все дополнительные состояния, свойства объекта для более удобной с ним работы:

    public class SomeObject
    {
        public bool WasClicked { get; set; }
        public MapObject2 Object { get; }
    
        public SomeObject(MapObject2 mobj)
        {
            Object = new MapObject2(mobj);
        }
    }


    Внимание - не используйте название SomeObject. Наименования должны отражать смысл, назначение объекта. Мне сложно понять цель проекта поэтому дать осмысленное название не могу. К классу MapObject2 это тоже относится.

    Есть и другие варианты, но я бы на вашем месте остановился именно на таком подходе.
    Ответ написан
  • Как визуально разделить форму (окно) на части(блоки) в WindowsForms?

    FoggyFinder
    @FoggyFinder
    Используйте Layout-s, в вашем случае должен подойти TableLayoutPanel, который позволяет компоновать элементы управления в виде таблицы.

    Простой пример на русском языке можно найти тут:

    TableLayoutPanel
    Ответ написан
    Комментировать
  • Как выделить ячейку на ПКМ в DataGridView?

    FoggyFinder
    @FoggyFinder
    Один из вариантов:

    private void dataGridView1_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
    {
        if (e.Button == MouseButtons.Right)
        {
            dataGridView1.ClearSelection();
            dataGridView1[e.ColumnIndex, e.RowIndex].Selected = true;
        }
    }
    Ответ написан
    Комментировать