Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Win Api
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 21.04.2008, 21:03   #1
HunterMan
Пользователь
 
Регистрация: 01.04.2008
Сообщений: 58
По умолчанию Рисование...

Помогите разобрать логику...
Нарисовал в окне график какой-то функции. Теперь хочу сделать, чтобы при нажатии на кнопку дорисовывался новый график, и не удалялся старый... Как это сделать??
HunterMan вне форума Ответить с цитированием
Старый 21.04.2008, 22:19   #2
B_N
Новичок
Джуниор
 
Регистрация: 18.01.2008
Сообщений: 1,720
По умолчанию

Можно рисовать не в окно, а в битмап, а потом уже из него в окно. Объясните подробнее, что хотите сделать, будет проще советовать.
B_N вне форума Ответить с цитированием
Старый 22.04.2008, 06:33   #3
HunterMan
Пользователь
 
Регистрация: 01.04.2008
Сообщений: 58
По умолчанию

Есть материнское окно с менюшками.... и есть дочерние окно, в котором должно производится рисование графиков. При создании дочернего окна в процедуре этого окна я пишу код, который рисует оси координат, подписи... Теперь мне нада добавить график, после того как процедура главного окна обработает данные введеные пользователем.
По идее нада послать сообщение WM_PAINT дочернему окну, и написать код который, нарисует график. Если бы он был один, то я бы просто перерисовал бы все вместе с осями, но плюс еще график. Но у меня графиков может быть 3,4,5... и все совмещены вместе и при етом выводится могут в разном порядке, в зависимости от того, что хочет получить пользователь.
HunterMan вне форума Ответить с цитированием
Старый 22.04.2008, 07:55   #4
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
По идее нада послать сообщение WM_PAINT дочернему окну, и написать код который, нарисует график.
А зачем его принудительно посылать? Просто открой окно, а в WM_PAINT отрисовывай графики.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 22.04.2008, 14:08   #5
B_N
Новичок
Джуниор
 
Регистрация: 18.01.2008
Сообщений: 1,720
По умолчанию

Цитата:
Сообщение от HunterMan Посмотреть сообщение
Есть материнское окно с менюшками.... и есть дочерние окно, в котором должно производится рисование графиков. При создании дочернего окна в процедуре этого окна я пишу код, который рисует оси координат, подписи... Теперь мне нада добавить график, после того как процедура главного окна обработает данные введеные пользователем.
По идее нада послать сообщение WM_PAINT дочернему окну, и написать код который, нарисует график. Если бы он был один, то я бы просто перерисовал бы все вместе с осями, но плюс еще график. Но у меня графиков может быть 3,4,5... и все совмещены вместе и при етом выводится могут в разном порядке, в зависимости от того, что хочет получить пользователь.
Вы знаете, такая гора вариантов, причем относящихся не столько к WinAPI, сколько к алгоритму, что даже не знаешь, с чего начать. Можно понаставить в обработчике WM_PAINT условий введено/не введено и рисовать графики в них, можно завести список указателей на функции, которые рисуют графики и вызывать их "по списку" в WM_PAINT, можно, если это действительно долго, рисовать всё это в битмэп, а его выводить в окно, но лучше сделать это на втором этапе, когда "всё заработает". Собственно, неясно даже, что это за функции. Единственное, что можно сказать наверняка, это то, что не нужно никуда посылать WM_PAINT, для этого есть InvalidateRect.
B_N вне форума Ответить с цитированием
Старый 22.04.2008, 16:36   #6
HunterMan
Пользователь
 
Регистрация: 01.04.2008
Сообщений: 58
По умолчанию

А как сделать так, чтобы контекст устройства не передавать Windows? Мы же вконце пишем EndPaint(hwnd,&ps); .... И по идее контекст возвращается в начальное состояние. Т.е. если снова же обьявить контекст етого же окна HDC hdc=BeginPaint(hwnd,&ps); то оно же будет заново рисовать и придется перерисовывать все с осями.
А есть ли вариант как-то запомнить, что уже построено и достроить к нему новое?
HunterMan вне форума Ответить с цитированием
Старый 22.04.2008, 17:36   #7
B_N
Новичок
Джуниор
 
Регистрация: 18.01.2008
Сообщений: 1,720
По умолчанию

Цитата:
Сообщение от HunterMan Посмотреть сообщение
А как сделать так, чтобы контекст устройства не передавать Windows? Мы же вконце пишем EndPaint(hwnd,&ps); .... И по идее контекст возвращается в начальное состояние. Т.е. если снова же обьявить контекст етого же окна HDC hdc=BeginPaint(hwnd,&ps); то оно же будет заново рисовать и придется перерисовывать все с осями.
А есть ли вариант как-то запомнить, что уже построено и достроить к нему новое?
Вы не совсем правильно представляете этот процесс. Контекст это объект ОС, необходимый именно для рисования, в окне в данном случае. Его нужно освобождать после того, как мы нарисуем, что хотим. ОС нигде не держит содержимое окон - его должны перерисовывать процессы, владеющие окнами, каждый раз, как это необходимо, скажем, после того, как окно появилось из-под другого окна или после явного вызова InvalidateRect. Но всё, что нужно рисовать вполне можно запомнить в картинке, для ускорения процесса, например. Об этом я Вам и говорю.

Для этого нужно
1. Создать битмап. Скажем, при создании окна.
Код:
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
	HWND hWnd;
	RECT rcClient;
	HDC hDC, hMemDC;
	HBITMAP hOldBmp;
	HBRUSH hTmpBrush;

	hInst = hInstance; // Store instance handle in our global variable

	hWnd = CreateWindow(szWindowClass, szTitle, WS_SYSMENU | WS_MINIMIZEBOX,
		CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, NULL, NULL, hInstance, NULL);

	if (!hWnd) return FALSE;

	hDC = GetDC(hWnd);
	GetClientRect(hWnd, &rcClient);

	hDrawingBitmap	= CreateCompatibleBitmap(
								hDC, 
								rcClient.right - rcClient.left, 
								rcClient.bottom - rcClient.top);

	hMemDC = CreateCompatibleDC(hDC);

	hOldBmp = (HBITMAP)SelectObject(hMemDC, hDrawingBitmap);

	hTmpBrush = CreateSolidBrush(RGB(100,191, 255));
	FillRect(hMemDC, &rcClient, hTmpBrush);
	DeleteObject(hTmpBrush);
	
	SelectObject(hMemDC, hOldBmp);
	ReleaseDC(hWnd, hMemDC);

	ShowWindow(hWnd, nCmdShow);
	UpdateWindow(hWnd);

	return TRUE;
}
2. Нарисовать в этом битмапе всё, что вздумается и когда вздумается.
Код:
//............................
		case WM_COMMAND:
			wmId    = LOWORD(wParam); 
			wmEvent = HIWORD(wParam); 
//............................
				case ID_DRAWRECTANGLE:
					{
						RECT rcClient;
						HDC hDC, hMemDC;
						HBITMAP hOldBmp;
						HBRUSH hTmpBrush, hOldBrush;
						
						hDC = GetDC(hWnd);
						GetClientRect(hWnd, &rcClient);
						hMemDC = CreateCompatibleDC(hDC);

						hOldBmp = (HBITMAP)SelectObject(hMemDC, hDrawingBitmap);

						hTmpBrush = CreateHatchBrush(HS_FDIAGONAL, RGB(0, 255, 0));
						hOldBrush = (HBRUSH)SelectObject(hMemDC, hTmpBrush);

						Rectangle(
							hMemDC, 
							rcClient.right >> 1, 
							rcClient.bottom >> 1, 
							rcClient.right, 
							rcClient.bottom);

						SelectObject(hMemDC, hOldBrush);
						DeleteObject(hTmpBrush);

						SelectObject(hMemDC, hOldBmp);
						DeleteDC(hMemDC);
						ReleaseDC(hWnd, hDC);
						InvalidateRect(hWnd, NULL, FALSE);
					}
					break;
//............................
//............................
3. Выводить нужную часть (для ускорения процесса) этого битмапа при обработке WM_PAINT
Код:
//............................
		case WM_PAINT:
			{
				HDC hTmpDC;
				RECT rcClient;
				HBITMAP hTmpBmp;
						
				hdc = BeginPaint(hWnd, &ps);
				GetClientRect(hWnd, &rcClient);
				hTmpDC = CreateCompatibleDC(hdc);
				hTmpBmp = (HBITMAP)SelectObject(hTmpDC, hDrawingBitmap);
				
				BitBlt(
					hdc,
					ps.rcPaint.left,
					ps.rcPaint.top,
					ps.rcPaint.right - ps.rcPaint.left,
					ps.rcPaint.bottom - ps.rcPaint.top,
					hTmpDC, 
					ps.rcPaint.left,
					ps.rcPaint.top,
					SRCCOPY);

				SelectObject(hTmpDC, hTmpBmp);
				DeleteDC(hTmpDC);
				EndPaint(hWnd, &ps);
			}
			break;
//............................
Смотрите пример в аттаче.
Вложения
Тип файла: rar DIBDemo.rar (227.5 Кб, 75 просмотров)
B_N вне форума Ответить с цитированием
Старый 29.04.2008, 16:24   #8
HunterMan
Пользователь
 
Регистрация: 01.04.2008
Сообщений: 58
По умолчанию

SelectObject(hTmpDC, hTmpBmp);
DeleteDC(hTmpDC);
EndPaint(hWnd, &ps);

Раскажите, пожалуйста, что делает код в конце работы с контекстом совместимой памяти: SelectObject(hTmpDC, hTmpBmp);

Возникла проблема, что при дорисовывании нового графика, ему скажем нада побольше размах осей...значит нада дорисовать оси и вырисовать все графики при новых осях. Я для осей и каждого нового графика делаю новый контекст памяти совместимой с устройством. Потом по надобности в этих контекстах изменяю оси, графики как мне нада... В цыкле сообщений все контексты памяти пробую накладывать друг на друга функцией BitBlt(...) таким образом:

BitBlt(hdcMem3....hdcMem1...);
BitBlt(hdcMem3....hdcMem2...);

Вот одна беда, почему-то они не совмещаются а перекрывают друг друга... Перепробовал вроде все возможные значения последнего параметра функции dwRop, которые описаны в msdn. Может как-то по другому стоит мыслить для решения проблемы?
HunterMan вне форума Ответить с цитированием
Старый 29.04.2008, 18:03   #9
B_N
Новичок
Джуниор
 
Регистрация: 18.01.2008
Сообщений: 1,720
По умолчанию

Не понимаю, зачем Вам столько битмапов? Вполне можно рисовать в один, то, что я предлагал в основном "для красоты" и на тот случай если графики строятся достаточно долго, чтобы их рисовать по WM_PAINT. Комбинировать картинки не сложно, только это часто зависит от характера самих изображений, но тот код, что Вы привели, ровным счётом ни о чём не говорит.
B_N вне форума Ответить с цитированием
Старый 30.04.2008, 22:07   #10
HunterMan
Пользователь
 
Регистрация: 01.04.2008
Сообщений: 58
По умолчанию

Не...Битмамп один. Я создаю несколько контекстов памяти, рисую в них и потом все переношу в етот битмап...я так понимаю, то что делается.
Вобщим вопрос в том, что када копируется из котекста памяти в битмап рисунок, то битмап затирается со всем предидущим, что в нем было. А мне нада чтобы как минимум не затиралось, а налаживалось...

Можна канешно делать как вы советуете все последовательно, но тада там очень много перещетов будет делать программа, для того лиш чтобы оси перестроить... А я хочу свести лишние общеты к минимуму. И для етого все ето делаю.


И код я привел, чтобы по возможности понятнее было откуда оно взято... Я думал его хватит. Меня интересует что делает в конце строка:

SelectObject(hTmpDC, hTmpBmp);

ето из вашего же примера выше.
HunterMan вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
рисование в TImage Rusl92 Общие вопросы Delphi 8 02.05.2008 20:23
Рисование на экране... Roberto Win Api 3 07.04.2008 07:35
Рисование вTImage Rusl92 Компоненты Delphi 27 02.04.2008 14:18
Рисование в Chart SunKnight Общие вопросы Delphi 3 07.02.2008 09:16
рисование изолиний Alar Паскаль, Turbo Pascal, PascalABC.NET 0 30.10.2006 14:17