Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Как получить Битмап из Панели? / 13 сообщений из 13, страница 1 из 1
09.11.2004, 15:26
    #32773804
M234
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить Битмап из Панели?
Есть форма, не ней панель(и) на панели кнопки, ричтекстбоксы, пиктуребоксы и/или любые другие контролы.
Запускаем приложение, жмём на одну из кнопок и получаем файл *.bmp на котором изображена одна(любая) из панелей и всё что на ней есть.
Вот такая задачка.

Как "снять" изображение с панели?
Варианты?

-----------------------------------------------------------------------------
Нет худа без добра, да и добро без худа - чудо.
...
Рейтинг: 0 / 0
09.11.2004, 17:18
    #32774137
Roman S. Golubin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить Битмап из Панели?
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
		public void PaintToFile(string filename)
		{
			Bitmap bitmap = new Bitmap(this.Width, this.Height);
			Graphics g = Graphics.FromImage(bitmap);

			PaintEventArgs pe = new PaintEventArgs(g, this.Bounds);
			InvokePaint(this, pe);

			foreach(Control ctrl in this.Controls)
			{
				Bitmap bmpctrl = new Bitmap(ctrl.Width, ctrl.Height);
				Graphics grctrl = Graphics.FromImage(bmpctrl);

				PaintEventArgs pectrl = new PaintEventArgs(grctrl, ctrl.Bounds);
				InvokePaint(ctrl, pectrl);

				g.DrawImageUnscaled(bmpctrl, ctrl.Left, ctrl.Top);

				grctrl.Dispose();
				bmpctrl.Dispose();
				pectrl.Dispose();
			}


			bitmap.Save(filename);

			g.Dispose();
			bitmap.Dispose();
			pe.Dispose();
		}
--
WBR, Roman S. Golubin
ICQ UIN: 63253392
...
Рейтинг: 0 / 0
09.11.2004, 17:39
    #32774201
M234
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить Битмап из Панели?
Спасибо.
Прямо сразу готовое решение - круто.
НО, работает не очень правильно.
Создал тестовое приложение, форму с парой контролов и кнопкой.
Давлю на кнопку - отрабатывает ф-ия.
Результат: см. картинку.
всё черное и только кнопка отрисована.

-------------------------------------------------------------------------
Нет худа без добра, да и добро без худа - чудо.
...
Рейтинг: 0 / 0
09.11.2004, 17:47
    #32774221
Roman S. Golubin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить Битмап из Панели?
Писал на скорую руку так как домой пора.
Домой приеду - посмотрю, если время будет.
Или уже завтра только.
ОК?
...
Рейтинг: 0 / 0
09.11.2004, 17:51
    #32774236
M234
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить Битмап из Панели?
Roman S. GolubinПисал на скорую руку так как домой пора.
Домой приеду - посмотрю, если время будет.
Или уже завтра только.
ОК?

Конечно ОК.
Большое спасибо. Не морочте себе голову дома. Я никуда не тороплюсь.
...
Рейтинг: 0 / 0
10.11.2004, 10:34
    #32774862
Roman S. Golubin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить Битмап из Панели?
Проблема была в том, что сначала надо отображать background, а только потом сам элемент. Следующий кусок кода делает это правильно.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
		public void PrintToFile(string filename)
		{
			Bitmap bitmap = new Bitmap(this.ClientSize.Width, this.ClientSize.Height);
			Graphics graphics = Graphics.FromImage(bitmap);

			PrintBackground(graphics);
			Print(graphics);

			bitmap.Save(filename);

			graphics.Dispose();
			bitmap.Dispose();
		}

		public void PrintBackground(Graphics graphics)
		{
			PrintControlBackground(this, graphics);
		}

		public void Print(Graphics graphics)
		{
			PrintControl(this, graphics);
		}

		private void PrintControl(Control control, Graphics graphics)
		{
			PaintEventArgs pe = new PaintEventArgs(graphics, control.ClientRectangle);
			Print(control, pe);
		}

		private void PrintControlBackground(Control control, Graphics graphics)
		{
			PaintEventArgs pe = new PaintEventArgs(graphics, control.ClientRectangle);
			PrintBackground(control, pe);
		}

		private void Print(Control control, PaintEventArgs pe)
		{
			// Print control
				InvokePaint(control, pe);

			// Print subcontrols
			foreach(Control ctrl in control.Controls)
			{
				Bitmap bitmap = new Bitmap(ctrl.Width, ctrl.Height);
				Graphics graphics = Graphics.FromImage(bitmap);

				PrintControl(ctrl, graphics);

				pe.Graphics.DrawImageUnscaled(bitmap, ctrl.Left, ctrl.Top);

				graphics.Dispose();
				bitmap.Dispose();
			}
		}
		
		private void PrintBackground(Control control, PaintEventArgs pe)
		{
			// Print control
			InvokePaintBackground(control, pe);

			// Print subcontrols
			foreach(Control ctrl in control.Controls)
			{
				Bitmap bitmap = new Bitmap(control.Width, ctrl.Height);
				Graphics graphics = Graphics.FromImage(bitmap);

				PrintControlBackground(ctrl, graphics);

				pe.Graphics.DrawImageUnscaled(bitmap, ctrl.Left, ctrl.Top);

				graphics.Dispose();
				bitmap.Dispose();
			}
		}
Остается только проблема с элементами (в их число входят: treeview, textbox, listbox и т.п.) которым плевать на WM_PAINT или они отображают свое содержимое во всплывающих окнах. Что с ними делать - совершенно не понятно.
...
Рейтинг: 0 / 0
11.11.2004, 12:28
    #32777267
M234
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить Битмап из Панели?
Ещё раз спасибо за помощь.
Вчера я не работал, потому запоздало отвечаю.
Теоретически после отрисовки бэкграунда нужно вызвать метод отрисовки текста на контроле и прилепить это сверху бэкграунда.
Но вот как это сделать?
У листбкса можно ещё с методом DrawItem поиграться, а у текст бокса ничего похожего нет....
Можно достучаться до самого текста, преобразовать его в графику и прилепить сверху, НО как быть если текст не помещается по длине на одной строке контрола и занимает несколько?
Я то после преобразования буду иметь длинную картинку с текстом в одну строку. Как мне его ломать? Я не знаю.

Если у кого-то ещё мысли возникнут, прошу писать сюда.

-------------------------------------------------------------------------
Нет худа без добра, да и добро без худа - чудо.
...
Рейтинг: 0 / 0
11.11.2004, 14:13
    #32777569
Roman S. Golubin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить Битмап из Панели?
Проблема в том, что многие контролы после отрисовки бакграунда и собственно самого контрола дорисовывают картинку прямо в контекст рабочего стола функциями типа FillReversibleRectangle - как их отследить я понятия не имею.

Как вариант есть еще снятие копии изображения с окна напрямую с помощью WinAPI, но работать он будет только под Windows, потому этот вариант, имхо, не есть очень гуд:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern long BitBlt (IntPtr hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, int dwRop);

private void SaveFormImage(string path)
{
	Graphics gform = this.CreateGraphics();

	Bitmap bitmap = new Bitmap(this.Size.Width, this.Size.Height, gform);

	Graphics gimage = Graphics.FromImage(bitmap);

	IntPtr dcg = gform.GetHdc();
	IntPtr dci = gimage.GetHdc();

	int widthDiff = (this.Width - this.ClientRectangle.Width);
	int heightDiff  = (this.Height - this.ClientRectangle.Height);
			int borderSize = widthDiff / 2;
			int heightTitleBar = heightDiff - borderSize;

	BitBlt(dci, 0, 0,
		this.ClientRectangle.Width + widthDiff, 
		this.ClientRectangle.Height + heightDiff, 
		dcg, 0 - borderSize, 
		0 - heightTitleBar, 13369376);

	gform.ReleaseHdc(dcg);
	gimage.ReleaseHdc(dci);

	bitmap.Save(path);
}
...
Рейтинг: 0 / 0
11.11.2004, 15:15
    #32777720
M234
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить Битмап из Панели?
Да, так действительно работает и мне в принципе всё равно, что только для виндовса.
Дело в другом: задачка сложнее.
Мне нужно "снять" изображение с панели а не с формы.
Проблема в том, что панель, и соответственно контролы на ней, может быть не вся видна на форме, например если панель больших размеров чем форма, а невидимая часть панели доступна по скроллу. В этом случае я получаю изображение видимой части панели, остальное обрезается.

-------------------------------------------------------------------------
Нет худа без добра, да и добро без худа - чудо.
...
Рейтинг: 0 / 0
11.11.2004, 15:59
    #32777851
Roman S. Golubin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить Битмап из Панели?
Тогда только вариант с InvokePaint и InvokePaintBackground, но т.к. майкрософтам было лениво переписать все элемены под .Net и они использовали ActiveX и WinAPI, то большинство контролов будут отображаться некорректно. А сделано это, я думаю, специально, что бы дать заработать всяким разным дочкам с системами CrystalReports - как вариант ухода от налогов, а бьет в первую очередь по пользователям .Net Framework.

PS: Ну, или еще как вариант - перебирать все элементы, позиционировать их в место, где они будут видны, снимать экранную копию с каждого в отдельности и потом добавлять ее в общую картинку... но, имхо, геморойно будет, да и пользователю наверно будет неприятно видеть мелькающие элементы :-) Или, как еще вариант - хук на форму (возможно и на все контролы на форме и перехват... но это все извраты - самый честный вариант - переписать все контролы на чистом .Net (без API и ActiveX)
...
Рейтинг: 0 / 0
11.11.2004, 16:44
    #32778006
M234
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить Битмап из Панели?
Roman S. GolubinА сделано это, я думаю, специально, что бы дать заработать всяким разным дочкам с системами CrystalReports - как вариант ухода от налогов, а бьет в первую очередь по пользователям .Net Framework.


то есть, есть возможность (попробовать) решить эту задачку с помощью CrystalReports или я чего-то не правильно понял?
Могу я из CrystalReports получить на выходе картинку(jpg,bmp...) ?
...
Рейтинг: 0 / 0
11.11.2004, 17:12
    #32778068
Roman S. Golubin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить Битмап из Панели?
CrystalReports работает только со своими собственными компонентами, вроде... и для печати отчетов заточена, а не форм.

Речь выше шла о том, что майкрософт сделала все что бы усложнить жизнь обладателям голого фреймворка при печати отчетов с формы (согласись, это было бы слишком просто, если бы все работало и сразу), содрать с наиболее богатых из них побольше денег, втюхав им Crystal Reports, и уйти от претензий антимонопольного комитета (читай - уплаты налогов).
...
Рейтинг: 0 / 0
11.11.2004, 17:17
    #32778080
M234
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить Битмап из Панели?
Roman S. GolubinCrystalReports работает только со своими собственными компонентами, вроде...

Пынятно. Ende Gelaende! (приплыли!) :)
Ладно спасибо за помощь. Тему можно закрыть. Буду искать другие подходы.
...
Рейтинг: 0 / 0
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Как получить Битмап из Панели? / 13 сообщений из 13, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]