воскресенье, 10 февраля 2013 г.

сохранить окно в hbitmap + c++

Цитата(consdush @ 17.02.2009, 15:30)

Те, генерируем битмап в подходящем месте, а на OnPaint выводим кусок битмапа.VlafFДалее о том, как подобные проблемы можно решить на Шарпе. Имеет смысл вынести рисование объекта в отдельный метод..Очень специфично именно для Шарпа надо отметить

Nox MetusДопустим, график рисуется по точкам.Не знаю как сейчас дела с железом, а раньше было быстрее передать в видеокарту отрисованный битмап чем передавать множество точек по одной точке. При передаче битмапа получится передача большего количества данных в видеопамять, зато процессору не надо будет часто синхронизироваться с видеокартой для передачи данных.Это наверное можно было бы обойти, если бы OnPaint буферизовывал вывод в graphics. Те если то что клиент делает с graphics в OnPain не выводилось на экран немедленно, а только после окончания OnPaint. Не знаю, может что то вроде этого и есть.А что, сейчас все по другому?

Цитата(consdush @ 15.02.2009, 14:09) Иначе рисование графика может стать тормозным.C чего ради ? 2D графика на современных видеокартах ускорена по самое не горюй.

Может я ошибусь в чем то но по моему график сначала надо отрисовать на битмапе а затем вывести битмап на экран.Иначе рисование графика может стать тормозным.

Цитата(VlafF @ 03.02.2009, 23:44) если необходимо сбросить картинку в Bitmap - вызываем этот же метод, куда в качестве параметра передаем Graphics.FromImage(bitmap)Это решение другой, не поставленной задачи . Поставленная задача была такая: «взять сформированное на экране изображение и сохранить его в файл». Вы предложили решение для другой задачи: «попытаться нарисовать на битмапе тоже самое, что нарисовалось на экране». При этом если битмап будет несовместимым с графическим контекстом, предлагаемом методу OnPaint, то вы получите, вообще говоря, другое изображение, не такое, как на экране.Цитата(VlafF @ 03.02.2009, 23:44) если бы предложенные решения не были такими кривыми.Ну что я могу сказать в свое оправдание ? Предложенное решение решало поставленную задачу . Мне кажется, что если решать не поставленную задачу, а вообще сохранение в файл векторной графики из System.Drawing, то оптимальней использовать метафайлы, а не битмэпы.

Наверное, уже не актуально для автора, но для других начинающих программистов, возможно, полезно будет знать, как решаются подобные проблемы. Как я понимаю, требуется отображать и уметь сохранять в виде изображения и сбрасывать в буфер обмена некие геометрические построения. Не рекомендуется без необходимости пользоваться неуправляемыми библиотеками - с ними могут быть проблемы, которые, например, касаются обработки ошибок, прав доступа и многие другие. Хотя в данном случае это будет работать, но это не тот пример, который, стоит учитывать начинающим. Тем более что это лишняя завязка на Windows (например, известно, что приложения с Windows.Forms уже работают под Linux, но там естественно нет виндовых dll). Не раз слышал как подобное творчество, где идет необоснованная завязка на неуправляемый код матерят люди, которые вынуждены разбирать эту мешанину. В общем это плохой стиль. Хочу подчеркнуть - я говорю именно о необоснованной завязке на неуправляемый код. Весьма нередки ситуации, когда без них не обойтись - сам использую.Далее о том, как подобные проблемы можно решить на Шарпе. Имеет смысл вынести рисование объекта в отдельный метод, который принимает на вход объект класса Graphics и осуществлять все рисование в нем. Этот метод будет вызываться из метода OnPaint - аргументом будет e.Graphics. Кроме того, если необходимо сбросить картинку в Bitmap - вызываем этот же метод, куда в качестве параметра передаем Graphics.FromImage(bitmap). В общем, все предельно просто - не стал бы писать про это, если бы предложенные решения не были такими кривыми.

Цитата(GonzA @ 18.01.2009, 12:48) Правильно я понимаю, что то что я нарисую в Graphics будет отрисовываться на битмапе?Правильно.Цитата(GonzA @ 18.01.2009, 12:56) Как мне использовать созданый мной график из битмепа для отрисовывания графики на форме.Что за битмап такой?Цитата(GonzA @ 18.01.2009, 12:56) Я так понимаю что если я создам свой график я не смогу его использовать в форме или смогу?Можете рисовать на битмапе, потом рисовать его в OnPaint. Но это как удаление гланд через уста из которых я не говорю по-русски.Цитата(GonzA @ 18.01.2009, 12:56) И ещё, а как делается захват изображения при помощи неуправляемого кода?Там небось придётся высчитывать координаты формы и из этой области выдирать изображение или там как то учитываются формы?Не придётся. Контекст устройства привязан к клиентской части окна (не формы поддчеркиваю, т.е. вы можете делать захват любого окна или контрола на вашей форме, впрочем, как и всей формы), если вы атрибуты контекста не меняли, то начало координат находится в левом верхнем углу клиентской области. А код такой:Код  public partial class Form1 : Form  {    public Form1() {      InitializeComponent();    }    [DllImport("gdi32.dll")]    private static extern IntPtr CreateCompatibleDC(IntPtr hdc);    [DllImport("gdi32.dll")]    private static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int width, int height);    [DllImport("gdi32.dll")]    private static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);    [DllImport("gdi32.dll")]    private static extern int DeleteObject(IntPtr hObject);    [DllImport("gdi32.dll")]    private static extern int DeleteDC(IntPtr hdc);    [DllImport("gdi32.dll")]    private static extern int BitBlt(      IntPtr hdcDest, // handle to destination DC      int    nXDest,  // x-coord of destination upper-left corner      int    nYDest,  // y-coord of destination upper-left corner      int    nWidth,  // width of destination rectangle      int    nHeight, // height of destination rectangle      IntPtr hdcSrc,  // handle to source DC      int    nXSrc,   // x-coordinate of source upper-left corner      int    nYSrc,   // y-coordinate of source upper-left corner      UInt32 dwRop    // raster operation code    );    private void Form1_Paint(object sender, PaintEventArgs e) {      Graphics g = e.Graphics;      g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;      Pen p = new Pen(Color.Red, 4);      g.DrawArc(p, new Rectangle(10, 10, 100, 100), 0, 360);    }    private void button1_Click(object sender, EventArgs e) {      Graphics g = this.CreateGraphics();      IntPtr srcHDC = g.GetHdc();      IntPtr hdc = CreateCompatibleDC(srcHDC);      IntPtr hBitmap = CreateCompatibleBitmap(srcHDC, this.ClientSize.Width, this.ClientSize.Height);      SelectObject(hdc, hBitmap);      BitBlt(hdc, 0, 0, this.ClientSize.Width, this.ClientSize.Height, srcHDC, 0, 0, 0x00CC0020);      Bitmap bmp = Bitmap.FromHbitmap(hBitmap);      DeleteObject(hBitmap);      DeleteDC(hdc);      bmp.Save("capture.png");      g.ReleaseHdc();      g.Dispose();    }  }Результат (содержимое capture.png):

Ещё есть вопрос. Я использую Graphics в OnPaint(PaintEventArgs e) как e.Graphics.Как мне использовать созданый мной график из битмепа для отрисовывания графики на форме.Я так понимаю что если я создам свой график я не смогу его использовать в форме или смогу?И ещё, а как делается захват изображения при помощи неуправляемого кода?Там небось придётся высчитывать координаты формы и из этой области выдирать изображение или там как то учитываются формы?

Цитата(Eyeless Watcher @ 17.01.2009, 20:57) Ну прям уж никак.КодBitmap bitmap = new Bitmap();Graphics graphics = Graphics.FromImage(bitmap);В этот Graphics рисуете. Полученный Bitmap потом можно использовать. Только не забудьте Graphics сказать Dispose().Правильно я понимаю, что то что я нарисую в Graphics будет отрисовываться на битмапе?

Цитата(Eyeless Watcher @ 17.01.2009, 20:57) Ну прям уж никак.КодBitmap bitmap = new Bitmap();Graphics graphics = Graphics.FromImage(bitmap);В этот Graphics рисуете. Полученный Bitmap потом можно использовать. Только не забудьте Graphics сказать Dispose().Пфф... понятно, что на битмапе можно рисовать. Вопрос-то в другом был. У вас есть контекст устройства (завёртка вокруг него и есть Graphics), прилетающий к вам в событии OnPaint. Вы в нём что-то рисуете. Как потом этот контекст преобразовать в битмап? Для этого в неуправляемом коде делают так: создают совместимый контекст в памяти, выбирают туда совместимый битмап, делают операцию BitBlt. Но в управляемом коде нет BitBlt. Нет даже ничего похожего. Q.E.D.

Ну прям уж никак.КодBitmap bitmap = new Bitmap();Graphics graphics = Graphics.FromImage(bitmap);В этот Graphics рисуете. Полученный Bitmap потом можно использовать. Только не забудьте Graphics сказать Dispose().

C помощью управляемых функций никак.

Привет народ.У меня такая проблемма. Я формирую изображение на экране в e.Graphics. Мне охота потом взять полученное изображение и сохранить в виде рисунка (Bitmap) как это сделать?

Полная версия этой страницы:

Форум Академгородка, Новосибирск > Взять изображение из e.Graphics (С#)

Комментариев нет:

Отправить комментарий