Visual Studio, простое рисование на графической канве формы и дисплея
В блоге уже есть ряд заметок, показывающих работу с графической канвой формы в Visual C++ (раз, два). Цель этого примера - продемонстрировать, как одним и тем же кодом вывести программно созданный рисунок сначала в окно формы, а затем просто на дисплей вне окна. Сделать последнее позволяет метод GetDC из Windows API, получающий контекст графического устройства.
Итак, создадим пустой проект Windows Forms, я делал из сохранённого заранее шаблона в Studio 2015. Дальше процесс расписан по шагам.
1. В классе формы определён флажок, показывающий, нужно ли перерисовывать картинку:
private: bool Redraw;
2. Он инициализирован в методе Load
формы (так как при загрузке нужно отрисовать в первый раз):
private: System::Void MyForm_Load(System::Object^ sender, System::EventArgs^ e) { this->DoubleBuffered = true; //Включить для формы двойную буферизацию, чтоб не было "мерцаний" Redraw = true; }
3. Всё рисование делается в методе Paint
формы (исключений из этого правила мало):
private: System::Void MyForm_Paint(System::Object^ sender, System::Windows::Forms::PaintEventArgs^ e) { if (Redraw) Draw(e->Graphics); //Удобнее иметь свой отдельный метод для рисования } void Draw(System::Drawing::Graphics^ g) { //Графический контекст передан в наш метод array <Pen ^> ^pens = gcnew array <Pen ^>(3) { Pens::Red, Pens::Green, Pens::Black }; //Разные перья для рисования int width = (this->ClientSize.Width-1) / 2, //Половинки ширины и высоты клиентской части окна height = (this->ClientSize.Height-1) / 2; for (int i = 0; i < 2; i++) //Демо - рисуем перьями g->DrawEllipse(pens[i], i*width, i*height, width, height); array <Brush ^> ^brushes = gcnew array <Brush ^>(2) { Brushes::Red, Brushes::Green }; //Разные кисти для выполнения заливки цветом for (int i = 0; i < 2; i++) //Демо - рисуем кистями g->FillEllipse(brushes[i], i*width, i*height, width, height); g->DrawLine(pens[2], 0, 0, width*2, height*2); //Рисуем линию пером Redraw = false; //Ставим состояние "перерисовано" }
4. Некоторые события формы должны будут инициализировать принудительную перерисовку, например,
когда пользователь закончил изменение размеров окна (событие SizeChanged
):
private: System::Void MyForm_SizeChanged(System::Object^ sender, System::EventArgs^ e) { Redraw = true; //Установить флажок Invalidate(); //Принудительно перерисовать }
5. Передав в наш Draw
другой графический контекст (например, контекст графического экрана Windows), можно нарисовать
ту же графику "в другом месте", например, поверх всех окон или под ними.
Покажем в качестве примера перехват графического контекста основного дисплея (при изменении размеров окна нашей формы картинка будет перерисовываться вне окна формы, начиная с левого верхнего угла экрана). Решение работает только для Windows.
5.1. Заинклудить в самом начале файла формы .h:
#include <Windows.h>
5.2. Подключить к проекту стандартную Windows-библиотеку user32
. Для этого перейти к меню Проект, Свойства проекта, открыть слева список Компоновщик, затем Ввод, и прописать в поле "Дополнительные зависимости" значение
user32.lib
5.3. Проверить, что в namespace проекта подключены
using namespace System::Drawing; using namespace System::Runtime::InteropServices;
5.4. Метод Paint
формы изменится, так как перед вызовом Draw
он будет получать графический контекст
дисплея:
private: System::Void MyForm_Paint(System::Object^ sender, System::Windows::Forms::PaintEventArgs^ e) { if (Redraw) { HDC DesktopPointer = GetDC(NULL); Graphics ^ g = Graphics::FromHdc((IntPtr)DesktopPointer); Draw(g); ReleaseDC(NULL, DesktopPointer); } }
Рисование по-прежнему зависит от положения окна приложения, но можно было вместо this->ClientSize
попытаться использовать размеры экрана.
18.10.2016, 14:14 [16887 просмотров]