БлогNot. Visual Studio, простое рисование на графической канве формы и дисплея

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 просмотров]


теги: графика программирование c++/cli

К этой статье пока нет комментариев, Ваш будет первым