Практическое руководство. Установка значения, отображаемого c помощью элемента управления ProgressBar в Windows Forms
Элемент управления ToolStripProgressBar заменяет элемент управления ProgressBar и расширяет его функциональные возможности; однако при необходимости элемент управления ProgressBar можно сохранить для обратной совместимости и использования в будущем.
Платформа .NET Framework предоставляет несколько различных способов отображения заданного значения в элементе управления ProgressBar. Ваш подход будет зависеть от вашей задачи. В следующей таблице приведены доступные подходы.
| Подход | Description |
|---|---|
| Задайте значение элемента управления ProgressBar напрямую. | Этот подход можно использовать для задач, в которых вы знаете общее количество элементов, например для чтения записей из источника данных. Кроме того, если вам нужно задать значение только один или два раза, это простой способ сделать это. Наконец, используйте этот процесс, если необходимо уменьшить значение, отображаемое индикатором выполнения. |
| Увеличьте отображение ProgressBar на фиксированное значение. | Этот подход можно использовать при отображении простого счетчика между минимальным и максимальным значениями, например затраченным временем или количеством обработанных файлов из известного общего числа. |
| Увеличьте отображение ProgressBar на изменяемое значение. | Этот подход можно использовать, если необходимо изменить отображаемое значение несколько раз в разных объемах. В примере показано, сколько места на жестком диске потребляется при записи ряда файлов на диск. |
Самый прямой способ задать значение, отображаемое индикатором выполнения, — задать свойство Value. Это можно сделать во время разработки или во время выполнения.
Установка значения ProgressBar напрямую
- Задайте значения Minimum и Maximum элемента управления ProgressBar.
- В коде задайте для свойства элемента управления Value целочисленное значение между установленными минимальным и максимальным значениями.
Примечание. Если свойство Value задается вне границ, установленных свойствами Minimum и Maximum, элемент управления создает исключение ArgumentException.
В следующем примере кода показано, как задать значение ProgressBar напрямую. Код считывает записи из источника данных и обновляет индикатор выполнения и метку при каждом чтении записи данных. В этом примере требуется, чтобы в форме был элемент управления Label, элемент управления ProgressBar и таблица данных со строкой, вызываемой CustomerRow с полями FirstName и LastName .
Public Sub CreateNewRecords() ' Sets the progress bar's Maximum property to ' the total number of records to be created. ProgressBar1.Maximum = 20 ' Creates a new record in the dataset. ' NOTE: The code below will not compile, it merely ' illustrates how the progress bar would be used. Dim anyRow As CustomerRow = DatasetName.ExistingTable.NewRow anyRow.FirstName = "Stephen" anyRow.LastName = "James" ExistingTable.Rows.Add(anyRow) ' Increases the value displayed by the progress bar. ProgressBar1.Value += 1 ' Updates the label to show that a record was read. Label1.Text = "Records Read = " & ProgressBar1.Value.ToString() End Sub
public void createNewRecords() < // Sets the progress bar's Maximum property to // the total number of records to be created. progressBar1.Maximum = 20; // Creates a new record in the dataset. // NOTE: The code below will not compile, it merely // illustrates how the progress bar would be used. CustomerRow anyRow = DatasetName.ExistingTable.NewRow(); anyRow.FirstName = "Stephen"; anyRow.LastName = "James"; ExistingTable.Rows.Add(anyRow); // Increases the value displayed by the progress bar. progressBar1.Value += 1; // Updates the label to show that a record was read. label1.Text = "Records Read = " + progressBar1.Value.ToString(); >
Увеличение индикатора выполнения на фиксированное значение
- Задайте значения Minimum и Maximum элемента управления ProgressBar.
- Задайте для свойства Step элемента управления целое число, представляющее сумму для увеличения отображаемого значения индикатора выполнения.
- Вызовите метод PerformStep, чтобы изменить значение, отображаемое значением, заданным в свойстве Step. В следующем примере кода показано, как индикатор выполнения может поддерживать количество файлов в операции копирования. В следующем примере каждый файл считывается в память, а индикатор выполнения и метка обновляются в соответствии с общим числом прочитанных файлов. В этом примере требуется, чтобы форма содержала элемент управления Label и элемент управления ProgressBar.
Public Sub LoadFiles() ' Sets the progress bar's minimum value to a number representing ' no operations complete -- in this case, no files read. ProgressBar1.Minimum = 0 ' Sets the progress bar's maximum value to a number representing ' all operations complete -- in this case, all five files read. ProgressBar1.Maximum = 5 ' Sets the Step property to amount to increase with each iteration. ' In this case, it will increase by one with every file read. ProgressBar1.Step = 1 ' Dimensions a counter variable. Dim i As Integer ' Uses a For. Next loop to iterate through the operations to be ' completed. In this case, five files are to be copied into memory, ' so the loop will execute 5 times. For i = 0 To 4 ' Insert code to copy a file ProgressBar1.PerformStep() ' Update the label to show that a file was read. Label1.Text = "# of Files Read = " & ProgressBar1.Value.ToString Next i End Sub
public void loadFiles() < // Sets the progress bar's minimum value to a number representing // no operations complete -- in this case, no files read. progressBar1.Minimum = 0; // Sets the progress bar's maximum value to a number representing // all operations complete -- in this case, all five files read. progressBar1.Maximum = 5; // Sets the Step property to amount to increase with each iteration. // In this case, it will increase by one with every file read. progressBar1.Step = 1; // Uses a for loop to iterate through the operations to be // completed. In this case, five files are to be copied into memory, // so the loop will execute 5 times. for (int i = 0; i >
Увеличение индикатора выполнения на динамическое значение
- Задайте значения Minimum и Maximum элемента управления ProgressBar.
- Вызовите метод Increment, чтобы изменить значение, отображаемое указанным целым числом. В следующем примере кода показано, как индикатор выполнения может вычислить, сколько дискового пространства использовалось во время операции копирования. В следующем примере, когда каждый файл записывается на жесткий диск, индикатор выполнения и метка обновляются и отражают объем доступного места на жестком диске. В этом примере требуется, чтобы форма содержала элемент управления Label и элемент управления ProgressBar.
Public Sub ReadFiles() ' Sets the progress bar's minimum value to a number ' representing the hard disk space before the files are read in. ' You will most likely have to set this using a system call. ' NOTE: The code below is meant to be an example and ' will not compile. ProgressBar1.Minimum = AvailableDiskSpace() ' Sets the progress bar's maximum value to a number ' representing the total hard disk space. ' You will most likely have to set this using a system call. ' NOTE: The code below is meant to be an example ' and will not compile. ProgressBar1.Maximum = TotalDiskSpace() ' Dimension a counter variable. Dim i As Integer ' Uses a For. Next loop to iterate through the operations to be ' completed. In this case, five files are to be written to the disk, ' so it will execute the loop 5 times. For i = 1 To 5 ' Insert code to read a file into memory and update file size. ' Increases the progress bar's value based on the size of ' the file currently being written. ProgressBar1.Increment(FileSize) ' Updates the label to show available drive space. Label1.Text = "Current Disk Space Used = " &_ ProgressBar1.Value.ToString() Next i End Sub
public void readFiles() < // Sets the progress bar's minimum value to a number // representing the hard disk space before the files are read in. // You will most likely have to set this using a system call. // NOTE: The code below is meant to be an example and // will not compile. progressBar1.Minimum = AvailableDiskSpace(); // Sets the progress bar's maximum value to a number // representing the total hard disk space. // You will most likely have to set this using a system call. // NOTE: The code below is meant to be an example // and will not compile. progressBar1.Maximum = TotalDiskSpace(); // Uses a for loop to iterate through the operations to be // completed. In this case, five files are to be written // to the disk, so it will execute the loop 5 times. for (int i = 1; i>
См. также
- ProgressBar
- ToolStripProgressBar
- Общие сведения об элементе управления ProgressBar
- Элемент управления ProgressBar
Использование Visual C# для создания плавного индикатора выполнения
В этой статье содержатся сведения о создании пользовательского элемента управления UserControl для создания плавного прокручиваемого элемента управления ProgressBar.
Исходная версия продукта: Visual C #
Исходный номер базы знаний: 323116
Аннотация
В этой статье показано, как создать простой настраиваемый элемент управления UserControl для создания плавного прокручиваемого элемента управления ProgressBar.
В более ранних версиях элемента управления ProgressBar, таких как версия, которая предоставляется вместе с элементом ActiveX «Общие элементы управления Microsoft Windows», ход выполнения можно просматривать в двух разных представлениях. Чтобы управлять этими представлениями, используйте свойство Scrolling, которое включает стандартные и плавные параметры. При плавной прокрутке создается сплошной цветной блок, который представляет ход выполнения, а стандартная прокрутка выглядит сегментированной и состоит из ряда небольших блоков или прямоугольников.
Элемент управления ProgressBar, входящий в состав Microsoft Visual C#, поддерживает только стандартный параметр.
В примере кода в этой статье показано, как создать элемент управления, поддерживающий следующие свойства:
- Минимум. Это свойство получает или задает меньшее значение для диапазона допустимых значений для хода выполнения. Значение по умолчанию для этого свойства равно нулю (0); Для этого свойства нельзя задать отрицательное значение.
- Максимум: это свойство получает или задает верхнее значение для диапазона допустимых значений для хода выполнения. Значение по умолчанию для этого свойства — 100.
- Значение: это свойство получает или задает текущий уровень хода выполнения. Значение должно находиться в диапазоне, определяемом свойствами Минимум и Максимум.
- ProgressBarColor: это свойство получает или задает цвет индикатора выполнения.
Создание пользовательского элемента управления ProgressBar
- Чтобы создать проект библиотеки элементов управления Windows в Visual C#, выполните следующие действия:
- Запустите Microsoft Visual Studio.
- В меню Файл выберите пункт Создать и затем пункт Проект.
- В диалоговом окне Новый проект щелкните Visual C# в разделе Типы проектов, а затем выберите Windows Forms библиотека элементов управления в разделе Шаблоны.
- В поле Имя введите SmoothProgressBar и нажмите кнопку ОК.
- В обозревателе проектов переименуйте модуль класса по умолчанию с UserControl1.cs в SmoothProgressBar.cs.
- В окне Свойства объекта UserControl измените свойство Name с UserControl1 на SmoothProgressBar.
int min = 0;// Minimum value for progress range int max = 100;// Maximum value for progress range int val = 0;// Current progress Color BarColor = Color.Blue;// Color of progress meter protected override void OnResize(EventArgs e) < // Invalidate the control to get a repaint. this.Invalidate(); >protected override void OnPaint(PaintEventArgs e) < Graphics g = e.Graphics; SolidBrush brush = new SolidBrush(BarColor); float percent = (float)(val - min) / (float)(max - min); Rectangle rect = this.ClientRectangle; // Calculate area for drawing the progress. rect.Width = (int)((float)rect.Width * percent); // Draw the progress meter. g.FillRectangle(brush, rect); // Draw a three-dimensional border around the control. Draw3DBorder(g); // Clean up. brush.Dispose(); g.Dispose(); >public int Minimum < get < return min; >set < // Prevent a negative value. if (value < 0) < value = 0; >// Make sure that the minimum value is never set higher than the maximum value. if (value > max) < max = value; >min = value; // Ensure value is still in range if (val < min) < val = min; >// Invalidate the control to get a repaint. this.Invalidate(); > > public int Maximum < get < return max; >set < // Make sure that the maximum value is never set lower than the minimum value. if (value < min) < min = value; >max = value; // Make sure that value is still in range. if (val > max) < val = max; >// Invalidate the control to get a repaint. this.Invalidate(); > > public int Value < get < return val; >set < int oldValue = val; // Make sure that the value does not stray outside the valid range. if (value < min) < val = min; >else if (value > max) < val = max; >else < val = value; >// Invalidate only the changed area. float percent; Rectangle newValueRect = this.ClientRectangle; Rectangle oldValueRect = this.ClientRectangle; // Use a new value to calculate the rectangle for progress. percent = (float)(val - min) / (float)(max - min); newValueRect.Width = (int)((float)newValueRect.Width * percent); // Use an old value to calculate the rectangle for progress. percent = (float)(oldValue - min) / (float)(max - min); oldValueRect.Width = (int)((float)oldValueRect.Width * percent); Rectangle updateRect = new Rectangle(); // Find only the part of the screen that must be updated. if (newValueRect.Width > oldValueRect.Width) < updateRect.X = oldValueRect.Size.Width; updateRect.Width = newValueRect.Width - oldValueRect.Width; >else < updateRect.X = newValueRect.Size.Width; updateRect.Width = oldValueRect.Width - newValueRect.Width; >updateRect.Height = this.Height; // Invalidate the intersection region only. this.Invalidate(updateRect); > > public Color ProgressBarColor < get < return BarColor; >set < BarColor = value; // Invalidate the control to get a repaint. this.Invalidate(); >> private void Draw3DBorder(Graphics g)
Создание примера клиентского приложения
- В меню Файл выберите пункт Создать и затем пункт Проект.
- В диалоговом окне Добавление нового проекта щелкните Visual C# в разделе Типы проектов, Windows Forms Приложение в разделе Шаблоны и нажмите кнопку ОК.
- Чтобы добавить два экземпляра элемента управления SmoothProgressBar в форму, выполните следующие действия:
- В меню Сервис выберите пункт Выбрать элементы панели элементов.
- Перейдите на вкладку Платформа .NET Framework Компоненты.
- Нажмите кнопку Обзор и найдите файлSmoothProgressBar.dll , созданный в разделе Создание пользовательского элемента управления ProgressBar .
- Нажмите кнопку ОК.
Примечание. Элемент управления SmoothProgressBar добавляется на панель элементов.
if (this.smoothProgressBar1.Value > 0) < this.smoothProgressBar1.Value--; this.smoothProgressBar2.Value++; >else
this.smoothProgressBar1.Value = 100; this.smoothProgressBar2.Value = 0; this.timer1.Interval = 1; this.timer1.Enabled = true;Примечание. Два индикатора хода выполнения отображают ход выполнения текста. Один индикатор хода выполнения отображает ход выполнения все более, а другой индикатор хода выполнения отображает ход выполнения в порядке уменьшения или обратного отсчета.
Как сделать progress bar?
Выполняется сортировка в потоках. В любой момент из переменной last_index я могу узнать сколько отсортированных элементов уже есть. Так же в переменной count есть их количество. Нужно сделать чтоб отдельный поток выводил progress bar в консоль. Не могу понять как это сделать на с++. Если не сложно можно код для этого потока.
Отслеживать
51.6k 201 201 золотой знак 63 63 серебряных знака 245 245 бронзовых знаков
задан 12 окт 2019 в 12:05
Oleksii Havryshkiv Oleksii Havryshkiv
111 1 1 золотой знак 1 1 серебряный знак 12 12 бронзовых знаков
Какая хоть операционная система?
12 окт 2019 в 13:31
@MrBin Windows.
12 окт 2019 в 14:15У вас 2 пути. Либо использовать прогресс бар из WinAPI напрямую, либо использовать фреймворк по типу Qt.
12 окт 2019 в 18:32
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
Есть ширина width , есть прогресс progress . Ширина — размер прогресс-бара в единицах консоли, прогресс — текущий прогресс сортировки (принимает значения [0; 1]). В каждый момент времени прогресс равен отношению количества отсортированных к общему количеству элементов массива. Для отрисовки прогресс-бара отрисовываем progress * width активных ячеек и width — progress * width неактивных ячеек.
Решение для Windows.
#include // std::cout #include // std::thread #include // WinApi auto handle = GetStdHandle(STD_OUTPUT_HANDLE); // устанавливает курсор в консоли на указанную позицию void set_cursor(int x, int y) < SetConsoleCursorPosition(handle, < static_cast(x), static_cast(y) >); > // отрисовывает прогресс-бар в консоли по указанным координатам // x - х-координата для прогресс-бара // y - у-координата для прогресс-бара // width - ширина прогресс-бара // progress - пройденный прогресс [0; 1] // fill_symbol - символ, которым будет заполнятся пройденный отрезок // void render_progress_bar(int x, int y, int width, double progress, char fill_symbol) < int fill_w = static_cast(width * progress); int empty_w = width - fill_w; set_cursor(x, y); for (int i = 0; i < fill_w; ++i) std::cout int main() < const int progress_x = 1; const int progress_y = 1; const int progress_width = 50; double progress = 0; // поток отрисовки auto thread = std::thread< [progress_x, progress_y, progress_width, &progress] < const int size = 3; char symbols[size] = < '|', '/', '-' >; int symbol_idx = 0; do < render_progress_bar(progress_x, progress_y, progress_width, progress, symbols[symbol_idx]); std::this_thread::sleep_for(std::chrono::milliseconds(100)); ++symbol_idx; if (symbol_idx >= size) symbol_idx = 0; > while (progress < 1); render_progress_bar(progress_x, progress_y, progress_width, progress, symbols[symbol_idx]); >>; int count = 100; int last_index = 0; // имитация изменения прогресса while (last_index < count) < last_index += 1 + rand() % 5; if (last_index >count) last_index = count; progress = static_cast(last_index) / count; std::this_thread::sleep_for(std::chrono::milliseconds(400)); > thread.join(); return 0; >Как сделать progress bar c
Как сделать ProgressBar с надписью
21.04.2022 | Категория: Образ мышления: Assembler | Автор: ManHunter
Не перестаю удивляться, почему разработчики Microsoft с самого начала не реализовали «из коробки» очевиднейшие решения. Например, есть хороший и удобный элемент диалоговых окон — Progress Bar. Легко реализовать, удобно управлять, но по какой-то причине нет никаких инструментов, чтобы системными средствами наложить на индикатор прогресса какую-нибудь надпись типа «42% завершено». Градиентный ProgressBar мы уже делали, настала очередь реализовать ProgressBar с надписью.

ProgressBar с надписью
Использовать стандартный элемент msctls_progress32 не будем, вместо него возьмем элемент EDIT или STATIC, как и в предыдущем примере. Полоса индикатора и надпись реализуется путем рисования прямо на канве элемента диалогового окна, которое выделено под индикатор.
Основная загвоздка заключается в том, что при отрисовке текста поверх индикатора прогресса, надо учитывать разницу в цвете фона и полосы выполненной части. Посмотрите на скриншоте, чтобы стало понятно, о чем идет речь. В некоторых случаях при определенной комбинации цветов можно использовать единый цвет, но это не самое хорошее решение. Так что сделаем все правильно.
Взаимодействие основного потока приложения и кастомного индикатора реализуется через субклассирование. Установка обработчика ничем не отличается от десятка других примеров, которые мы ранее разбирали.
Code (Assembler) : Убрать нумерациюВыделить код
- ; Субклассирование ProgressBar
- invoke GetDlgItem , [ hwnddlg ] , ID_PROGRESS
- movebx , eax
- ; Установить наш собственный обработчик
- invoke SetWindowLong , ebx , GWL_WNDPROC , ProgressWindowProc
- ; Сохранить хэндл предыдущего обработчика
- mov [ OldProc ] , eax
Процедура обработчика заточена на перехват сообщения WM_PAINT, при поступлении которого рисуется все содержимое ProgressBar. Главная особенность заключается в том, что сперва весь элемент заливается фоновым цветом, на нем рисуется текст, а затем с помощью функции SelectClipRgn от всей площади элемента выделяется участок, на котором выполняется рисование полосы прогресса и дублируется тот же текст, но уже другим цветом. При таком способе незадействованная часть остается без изменений. Ширина полосы прогресса вычисляется в процентном значении от ширины всей площади элемента.
Code (Assembler) : Убрать нумерациюВыделить код
- ;————————————————
- ; Субклассированный обработчик
- ;————————————————
- proc ProgressWindowProc hEdit : DWORD , uMsg : DWORD , wParam : DWORD , lParam : DWORD
- locals
- text dd ?
- ps PAINTSTRUCT
- hDC dd ?
- rcClient RECT
- endl
- cmp [ uMsg ] , WM_PAINT
- je . wm_paint
- . char_ok :
- ; Передать управление предыдущему обработчику
- invoke CallWindowProc , [ OldProc ] , [ hEdit ] , [ uMsg ] , \
- [ wParam ] , [ lParam ]
- ret
- . wm_paint :
- movebx , [ hEdit ]
- ; Размеры окна
- leaedi , [ rcClient ]
- invoke GetClientRect , ebx , edi
- ; Получить текст из свойств
- invoke GetProp , ebx , szProp
- mov [ text ] , eax
- ; Начать рисование
- leaeax , [ ps ]
- invoke BeginPaint , ebx , eax
- mov [ hDC ] , eax
- ; Шрифт
- invoke SelectObject , [ hDC ] , [ hFont ]
- invoke SetBkMode , [ hDC ] , TRANSPARENT
- ; Отрисовать общий фон
- invoke GetSysColorBrush , COLOR_WINDOW
- invoke FillRect , [ hDC ] , edi , eax
- ; Текст для отрисовки есть?
- cmp [ text ] , 0
- je @ f
- invoke GetSysColor , COLOR_WINDOWTEXT
- invoke SetTextColor , [ hDC ] , eax
- invoke DrawText , [ hDC ] , buff , — 1 , edi , \
- DT_NOPREFIX + DT_SINGLELINE + DT_VCENTER + DT_CENTER
- @ @ :
- ; Вычислить размеры области для заливки
- invoke GetProp , ebx , szPerc
- movecx , eax
- moveax , [ edi + RECT . right ]
- subeax , [ edi + RECT . left ]
- xoredx , edx
- mulecx
- movecx , 100
- divecx
- ; Позиция выполненного прогресса
- addeax , [ edi + RECT . left ]
- ; Наложить выполненный прогресс
- invoke CreateRectRgn , [ edi + RECT . left ] , [ edi + RECT . top ] , \
- eax , [ edi + RECT . bottom ]
- invoke SelectClipRgn , [ hDC ] , eax
- invoke GetSysColorBrush , COLOR_HIGHLIGHT
- invoke FillRect , [ hDC ] , edi , eax
- ; Текст для отрисовки есть?
- cmp [ text ] , 0
- je @ f
- invoke GetSysColor , COLOR_HIGHLIGHTTEXT
- invoke SetTextColor , [ hDC ] , eax
- invoke DrawText , [ hDC ] , buff , — 1 , edi , \
- DT_NOPREFIX + DT_SINGLELINE + DT_VCENTER + DT_CENTER
- @ @ :
- leaeax , [ ps ]
- invoke EndPaint , [ hDC ] , eax
- invoke ReleaseDC , ebx , [ hDC ]
- xoreax , eax
- ret
- endp
- szProp db ‘text’ , 0
- szPerc db ‘percent’ , 0
Я использую системные цвета, но никто не мешает вам заменить их по своему усмотрению. Шрифт настраивается в основном приложении, накладываемый текст и значение процентов передается через свойства функцией SetProp, что позволяет использовать одновременно несколько независимых индикаторов. В принципе, точно так же через свойства можно передавать шрифты и цвета, но это все тоже в зависимости от ваших задач.
Code (Assembler) : Убрать нумерациюВыделить код
- ; Шрифт текста
- invoke CreateFont , 32 , 12 , 0 , 0 , FW_BOLD , FALSE , FALSE , FALSE , \
- ANSI_CHARSET , OUT_RASTER_PRECIS , \
- CLIP_DEFAULT_PRECIS , PROOF_QUALITY , \
- FIXED_PITCH + FF_DONTCARE , szFont
- mov [ hFont ] , eax
- ; Хэндл ProgressBar
- invoke GetDlgItem , [ hwnddlg ] , ID_PROGRESS
- movebx , eax
- ; Сформировать строку для отрисовки
- invoke wsprintf , buff , szText , [ percent ]
- addesp , 12
- ; Назначить строку свойством ProgressBar
- invoke SetProp , ebx , szProp , buff
- ; Назначить значение процента свойством ProgressBar
- invoke SetProp , ebx , szPerc , [ percent ]
- ; Перерисовать содержимое окна
- invoke InvalidateRect , ebx , 0 , FALSE
Непосредственно обновление ProgressBar выполняется при помощи функции InvalidateRect, ее надо вызывать сразу после установки новых значений в свойствах.
В приложении пример программы с исходным текстом, которая выводит на форму кастомизированный индикатор прогресса с наложением текста.
Пример программы с исходным текстом (FASM)