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

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

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

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 28.11.2022, 08:07   #31
apofioz
Форумчанин
 
Регистрация: 22.01.2014
Сообщений: 313
По умолчанию

Цитата:
Сообщение от macomics Посмотреть сообщение
Иначе новый текст будет нарисован поверх старого.
Это не самое страшное, как-то работает, но, как мне кажется, не совсем так, как надо, текст пролетает один раз едва заметно, и всё. Я так понимаю это зависит от переменной StartTime. Если так, то, по идее, если переменная pos в функции DrawPopUpText() стала >= 0, то StartTime = GetTickCount() нужно задать новое значение. Если я правильно уловил суть ваших рассуждений.

Почему вас не смутил цикла:
Код:
for (unsigned int i = 0; i < Animation[0].uiLenString; ++i)
		{
			DrawPopUpText(hdc, memDC,
				Animation[0].textPos.x, Animation[0].textPos.y,
				Animation[0].startTime,
				Animation[0].chString,
				Animation[0].uiLenString);
		}
Если я на данный момент работаю лишь с одним объектом TextAnimation?!

Как сделать так чтобы текст медленнее выплывал и более плавно? Это зависит от частоты вызова таймера или от частоты обновления кадра (GetTickCount() + StartTime) / 10;
Я, думаю, что в задании имелось ввиду нечто другое. Не снизу вверх, а слева направо)) Хотя уже без разницы как... хоть как-нибудь.

Последний раз редактировалось apofioz; 28.11.2022 в 08:09.
apofioz вне форума Ответить с цитированием
Старый 28.11.2022, 12:53   #32
macomics
Участник клуба
 
Регистрация: 17.04.2022
Сообщений: 1,833
По умолчанию

Нет. Я не просто так писал в комментариях про скорость. Там у вас делитель какой? 10? Вот его и увеличивайте.

Для того, чтобы текст всплывал по символам надо задать функцию, которая будет вычислять разницу между предыдущим символом и текущим в пикселях, а в функции DrawPopUpText для рисования использовать цикл по символам и рисовать каждый отдельно со своей координатой y вычисляемой функцией из координаты предыдущего символа и разницы nowTime - startTime (где nowTime = GetTickCount(), лучше не вызывать многократно GetTickCount при воспроизведении в одной строке, чтобы не рассинхронизировать анимацию).

Если не понятно, тогда так. Разница GetTickCount - StartTime за 1 секунду увеличивается на 1000. Вам надо пройти расстояние в 20 пикселей (примерно = высота текста в пикселях). Тогда 1000 / 20 = 50 мс/пиксель, чтобы анимация длилась 1 секунду. 50 мс/пиксель это 20 кадров в секунду. Если укажите 100, тогда анимация строки будет длиться уже 2 секунды, а 1 пиксель будет прибавляться каждый 3 кадр (т.к. скорость снизится до 10 кадров в секунду).

Последний раз редактировалось macomics; 28.11.2022 в 13:08.
macomics вне форума Ответить с цитированием
Старый 28.11.2022, 13:12   #33
apofioz
Форумчанин
 
Регистрация: 22.01.2014
Сообщений: 313
По умолчанию

Цитата:
Сообщение от macomics Посмотреть сообщение
Нет. Я не просто так писал в комментариях про скорость.
Но текст не выплывает снизу, как вы предполагали, а просто появляется и уплывает вверх, эффект так себе, если честно. Я думал, что он будет как бы из-под нижней границы нарастать, нарастать, а а затем полностью показавшись, уходит под верхнюю границу. Надуюсь ясно объяснил.


Цитата:
Сообщение от macomics Посмотреть сообщение
Для того, чтобы текст всплывал по символам надо
Тут хоть бы с одним разобраться, зачем мне лишние усложнения.
apofioz вне форума Ответить с цитированием
Старый 28.11.2022, 13:14   #34
macomics
Участник клуба
 
Регистрация: 17.04.2022
Сообщений: 1,833
По умолчанию

Цитата:
Сообщение от apofioz Посмотреть сообщение
Но текст не выплывает снизу, как вы предполагали, а просто появляется и уплывает вверх, эффект так себе, если честно. Я думал, что он будет как бы из-под нижней границы нарастать, нарастать, а а затем полностью показавшись, уходит под верхнюю границу. Надуюсь ясно объяснил.
Покажите весь код. Должно быть как раз: Я думал, что он будет как бы из-под нижней границы нарастать, нарастать. Чтобы он еще и вверх уплывал, тогда это надо чуть модифицировать, но принципиально ничего не изменится.
macomics вне форума Ответить с цитированием
Старый 28.11.2022, 13:20   #35
apofioz
Форумчанин
 
Регистрация: 22.01.2014
Сообщений: 313
По умолчанию

Цитата:
Сообщение от macomics Посмотреть сообщение
Покажите весь код.
Код:
#include<windows.h>
#include<tchar.h>

//#include "Counter.h"


#define ID_TIMER 1

struct TextAnimation
{
	POINT textPos;
	DWORD startTime;
	TCHAR chString[128];
	UINT  uiLenString;
};

BOOL RegClass(WNDPROC proc, LPCTSTR szName, UINT brBackground);

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

TCHAR szMainClass[] = TEXT("_ClassName_");
TCHAR szTitle[] = TEXT("Pop up Text");

SIZE sz;
RECT rcUpdata;

void DrawPopUpText(HDC hdc, HDC memDC, int iXStart, int iYStart, DWORD StartTime, LPCTSTR lpString, UINT uiLenStr)
{
	GetTextExtentPoint32(memDC, lpString, uiLenStr, &sz);

	SetRect(&rcUpdata, 0, 0, sz.cx, 2 * sz.cy + 5);

	FillRect(memDC, &rcUpdata, (HBRUSH)GetStockObject(WHITE_BRUSH));

	int pos = 5 + sz.cy - (GetTickCount() - StartTime) / 60;

	TextOut(memDC, 0, min(pos, 0), lpString, uiLenStr);

	BitBlt(hdc, iXStart, iYStart, sz.cx, sz.cy, memDC, 0, 0, SRCCOPY);

}

HINSTANCE hInstance = NULL;

int WINAPI _tWinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
	MSG msg = { };
	HWND hwnd = NULL;
	hInstance = hInst;

	if (!RegClass(WndProc, szMainClass, COLOR_WINDOW))
		return 0;

	if (!(hwnd = CreateWindow(szMainClass, szTitle,
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT,
		CW_USEDEFAULT, CW_USEDEFAULT,
		0, (HMENU)NULL, hInstance, 0)))
	{
		return 0;
	}

	ShowWindow(hwnd, nCmdShow);
	UpdateWindow(hwnd);

	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return msg.wParam;
}

BOOL RegClass(WNDPROC proc, LPCTSTR szName, UINT brBackground)
{
	WNDCLASS wc = { };
	wc.style = CS_VREDRAW | CS_HREDRAW;
	wc.cbClsExtra = wc.cbWndExtra = 0;
	wc.hInstance = hInstance;
	wc.lpfnWndProc = proc;
	wc.lpszClassName = szName;
	wc.lpszMenuName = (LPCTSTR)NULL;
	wc.hbrBackground = (HBRUSH)(brBackground + 1);
	wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);

	return (RegisterClass(&wc) != 0);
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	static HDC hdc, memDC;
	static HBITMAP hBitmap;
	static TextAnimation Animation[2];
	//const int STRINGSIZE = lstrlen(lpString);
	PAINTSTRUCT ps;
	switch (msg)
	{
	case WM_CREATE:
	{
		Animation[0].textPos = { 120, 120 };
		Animation[0].startTime = GetTickCount();
		_tcscpy_s(Animation[0].chString, 128,
			TEXT("Hi! How are you?"));
		Animation[0].uiLenString = lstrlen(Animation[0].chString);

		

		SIZE sz;
		hdc = GetDC(hwnd);
		memDC = CreateCompatibleDC(hdc);
		GetTextExtentPoint32(hdc, Animation[0].chString, Animation[0].uiLenString, &sz);
		hBitmap = CreateCompatibleBitmap(memDC, sz.cx,
			2 * sz.cy + 5);

		//----
		Animation[1].textPos = { Animation[0].textPos.x + sz.cx + 20, 120 };
		Animation[1].startTime = Animation[0].startTime /*GetTickCount()*/;
		_tcscpy_s(Animation[1].chString, 128,
			TEXT("User 2 60%"));
		Animation[1].uiLenString = lstrlen(Animation[1].chString);


		SelectObject(memDC, hBitmap);

		ReleaseDC(hwnd, hdc);
		SetTimer(hwnd, ID_TIMER, 10, NULL);
		DeleteObject(hBitmap);

		return 0;
	}
	case WM_TIMER:
	{
		InvalidateRect(hwnd, NULL, FALSE);
		return 0;
	}
	case WM_PAINT:
	{
		hdc = BeginPaint(hwnd, &ps);
		for (unsigned int i = 0; i < 2/*Animation[0].uiLenString*/; ++i)
		{
			DrawPopUpText(hdc, memDC,
				Animation[i].textPos.x, Animation[i].textPos.y,
				Animation[i].startTime,
				Animation[i].chString,
				Animation[i].uiLenString);
		}

		EndPaint(hwnd, &ps);
		return 0;
	}
	case WM_DESTROY:
	{
		KillTimer(hwnd, ID_TIMER);
		DeleteDC(memDC);
		PostQuitMessage(0);
		return 0;
	}
	}
	return DefWindowProc(hwnd, msg, wParam, lParam);
}
apofioz вне форума Ответить с цитированием
Старый 28.11.2022, 13:30   #36
apofioz
Форумчанин
 
Регистрация: 22.01.2014
Сообщений: 313
По умолчанию

Вот ещё, это мой набросок, я его не собирал, просто как идея, смысл вывод текста слева направо. В идеале он должен медленно нарастать из-за левой границы и дойдя до конца т.е. размер всего текста(возможно, плюс ещё пару символов) возвращаться к выводу заново.
Код:
struct TextAniamtion
{
	POINT textPos;        //позиция текста в окне приложения
	UINT  startTime;      //начальное время 
	TCHAR chString[128];   //строка для вывода
	UINT  uiSizeStringInByte;  //Размер строки в байтах
	SIZE  szSizeStringInPixels;  //Размер строки в пикселях
	UINT  uiCurrentPos;     //Текущая позиция, что бы многократно 
	                        //повторять вывод, если текущая позиция
							//больше размера строки по ширине 
							//строки, установить на начало вывода
	HDC   memDC;          //контекст памяти для каждого объекта свой
};

#define ID_PARENT_TIMER  1
#define ID_TEMP_TIMER    2

/*Попытался сделать вывода слева направо. Суть в том что */
void DrawPopUpText(HDC hdc, const TextAimation* ta, UINT taSize)
{
	SIZE sz;
	for(UINT i = 0; i < taSize; ++i)
	{
		GetTextExtentPoint32(ta[i].memDC, ta[i].chString, 
							 ta[i].uiSizeStringInByte, &sz);
		TextOut(ta[i].memDC, 0, 0, ta[i].chString, 
				ta[i].uiSizeStringInByte);
		BitBlt(hdc, ta[i].textPos.x, ta[i].textPos.y, 
					ta[i].uiSizeStringInPixels.cx, 
					ta[i].uiSuzeStringInPixels.cy, ta[i].memDC, 0, 0,
					SRCCOPY);
	}
}

UINT uiElipse = 10;
const UINT ANIMZTIONSIZE = 1;
//....................................
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	PAINTSTRUCT ps;
	//TCHAR szString[] = TEXT("Interesting");
	static TextAniamtion taObjects[ANIMATIONSIZE];
	switch(msg)
	{
		
		case WM_CREATE:
		{
			if(!SetTimer(hwnd, ID_TIMER, uiElipse, NULL))
			{
				//MessageBox();
				
			}
			taObjects[0].textPos = { 20, 100};
			taObjects[0].startTime = GetickCount();
			_tcscpy_s(taObjects[0].chString, 128, TEXT("Strign One"));
			taObjects[0].uiSizeStringInByte = lstrlen(taObjects[0].chString);
			GetTextExtentPoint32(hdc, taObjects[0].chString, taObjects[0].uiSizeStringInByte, &sz);
			
			taObjects[0].uiSizeStringInPixels = sz;
			taObjects[0].uiCurrentPos = taObject[0].textPos.x;
			
			taObjects[0].memDC = CreateCompatibleDC(hdc);
			hBitmap = CreateCmpatibleBitmap(taObjects[0].memDC, sz.cx, sz.cy);
			
			SelectObject(taObjectp[0].memDC, hBitmap);
			
			DeleteObject(hBtmap);
			
			return 0;
		}
		case WM_PAINT:
		{
			HDC hdc = BeginPaint(hwnd, &ps);
			
			DrawPopUpText(hdc, taObjects, ANIMATIONSIZE);
			
			EndPaint(hwnd, &ps);
			return 0;
		}
		case WM_TIMER:
		{
			switch(wParam)
			{
				case ID_TAIMER:
				{
					for(int i = 0; i < ANIMATIONSIZE; ++i)
					{
						//Если строка была выведена полностью
						//Возвращаемся к исходной позиции и
						//Устанавливаем новое стартовое время(хотя
						//в установке этого значения есть сомнения)
						if(taObjects[i].currentPos > 
						   taObjects[i].uiSizeStringInPixels.cx)
						   {
								CurrentPos = taObjects[i].textPos.x;
								taObjects[i].startTime = GetTickCount();
						   }
						   //Новое значение времени для вычисления
						   //позиции, думаю, что тут нужно 
                                                   //переприсваивать текущее время значению 
						   //в поле структуры 
						   //taObjects[i].startTime = currentTime;
						   //хотя в этом есть сомнения.
						   //Возможно, это лишнее, хотел расчёт новой
						   //позиции сделать как у вас.
						UINT currentTime = GetTickCount();
						
						taObjects[i].currentPos = 2 + (currentTime - taObjects[i].startTime) / uiElipse;
						taObjects[i].startTime = currentTime;
					}
                                        InvalidateRect(hwnd, NULL, FALSE);
					break;
				}
			}
			return 0;
		}
		case WM_DESTROY:
		{
			for(int i = 0; i < ANIMATIONSIZE; ++i)
			{
				DeleteDC(taObjects[i].memDC);
			}
			KillTimer(hwnd, ID_TIMER1);
			PostQuitMessage(0);
			return 0;
		}
	}
	return DefWindowProc(hwnd, msg, wParam, lParam);
}

//.........................................................

Последний раз редактировалось apofioz; 28.11.2022 в 13:48.
apofioz вне форума Ответить с цитированием
Старый 28.11.2022, 14:08   #37
macomics
Участник клуба
 
Регистрация: 17.04.2022
Сообщений: 1,833
По умолчанию

Цитата:
Сообщение от apofioz Посмотреть сообщение
Код:
DrawPopUpText(hdc, memDC,
				Animation[i].textPos.x, Animation[i].textPos.y,
				Animation[i].startTime,
				Animation[i].chString,
				Animation[i].uiLenString);
Если уж объявили структуру описания анимации, тогда и передавайте сразу указатель на эту структуру как параметр функции. У меня столько параметров было из-за разных массивов.

Цитата:
Сообщение от apofioz Посмотреть сообщение
Код:
void DrawPopUpText(HDC hdc, HDC memDC, int iXStart, int iYStart, DWORD StartTime, LPCTSTR lpString, UINT uiLenStr)
{
	GetTextExtentPoint32(memDC, lpString, uiLenStr, &sz);

	SetRect(&rcUpdata, 0, 0, sz.cx, 2 * sz.cy + 5);

	FillRect(memDC, &rcUpdata, (HBRUSH)GetStockObject(WHITE_BRUSH));

	int pos = 5 + sz.cy - (GetTickCount() - StartTime) / 60;

	TextOut(memDC, 0, min(pos, 0), lpString, uiLenStr);

	BitBlt(hdc, iXStart, iYStart, sz.cx, sz.cy, memDC, 0, 0, SRCCOPY);

}
Размеры текста (GetTextExtentPoint32 и SetRect) можно сохранить как параметры в структуре описания анимации. Чтобы не заниматься лишними подсчетами каждый кадр.

Странно. Все проверил. Должен выплывать из под нижней границы, но останавливаться по достижении верхней.
macomics вне форума Ответить с цитированием
Старый 28.11.2022, 14:20   #38
apofioz
Форумчанин
 
Регистрация: 22.01.2014
Сообщений: 313
По умолчанию

Цитата:
Сообщение от macomics Посмотреть сообщение
Если уж объявили структуру описания анимации, тогда и передавайте сразу указатель на эту структуру как параметр функции.
Это не проблема, а вот работа функции не так, как нужно это проблема.


Цитата:
Сообщение от macomics Посмотреть сообщение
Должен выплывать из под нижней границы, но останавливаться по достижении верхней.
Должен, но работает как раз наоборот при старте текст уже вывелся, а затем, постепенно, заползает под верхнюю границу. Продемонстрировать не могу, к сожалению.

Я ещё пример выложил, может быть, он сработает, если, конечно его доработать?

Последний раз редактировалось apofioz; 28.11.2022 в 14:34.
apofioz вне форума Ответить с цитированием
Старый 28.11.2022, 14:59   #39
apofioz
Форумчанин
 
Регистрация: 22.01.2014
Сообщений: 313
По умолчанию

Вот чего удалось добиться на данный момент.
AnimationText.zip

Не совсем то, что надо, но уже лучше, нужно сделать вывод более плавным и сам вывод нужно сделать таким чтобы символы выводились как бы выползая слева направо. Пока что это не так.

Последний раз редактировалось apofioz; 28.11.2022 в 15:17.
apofioz вне форума Ответить с цитированием
Старый 28.11.2022, 15:13   #40
macomics
Участник клуба
 
Регистрация: 17.04.2022
Сообщений: 1,833
По умолчанию

Как вариант:
Код:
BitBlt(hdc, iXStart, iYStart + sz.cy, sz.cx, -sz.cy, memDC, 0, 0, SRCCOPY);
Вопрос. А что вычисляется функцией GetTextExtentPoint32. Какие значения? (возможно это не пиксели, а логические единицы - тогда значения будут отрицательные).

А зачем вам собственный bitmap для каждой анимации? Все можно сделать через один и тот же. Если лень считать размер текста, тогда просто увеличьте единственный bitmap до размеров окна.

Смотрите в чем смысл. У вас есть bitmap 800 x 600. У этого bitmap на экран (в окно) выводится только верхний левый кусочек размером sz.cx x sz.cy (видимая часть размером с текст). Вам для анимации текста на этом bitmap достаточно рисовать текст так, чтобы он задевал этот кусочек или был полностью в него вписан. Для этого на каждом кадре вычисляем новое значение положения текста на bitmap по y и уменьшаем его с течением времени. Таким образом текст будет вползать снизу в видимую часть bitmap. Это вы и увидите в окне.

Для запуска циклической анимации можно сразу в функции добавить:
Код:
void DrawPopUpText(HDC hdc, HDC memDC, int iXStart, int iYStart, DWORD &StartTime, LPCTSTR lpString, UINT uiLenStr, bool bCycle)
{
	GetTextExtentPoint32(memDC, lpString, uiLenStr, &sz);

	SetRect(&rcUpdata, 0, 0, sz.cx, 3 * sz.cy + 5);

	FillRect(memDC, &rcUpdata, (HBRUSH)GetStockObject(WHITE_BRUSH));

	int pos = 5 + 2 * sz.cy - (GetTickCount() - StartTime) / 60;

	TextOut(memDC, 0, min(pos, 0), lpString, uiLenStr);

	BitBlt(hdc, iXStart, iYStart, sz.cx, sz.cy, memDC, 0, sz.cy, SRCCOPY);

        if (pos < 0 && bCycle) StartTime = GetTickCount();
}
macomics вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Необходимо написать "таймер", который будет запускаться при нажатии кнопки "Start", приостанавливаться на "Pause", и сбрасываться на "Reset" billiejean78 JavaScript, Ajax 1 03.09.2021 08:58
Убрать папки "Pictures", "Music", "Видео", "Downloads" из "МОЙ КОМПЬЮТЕР" Бахтиёр1916 Windows 1 05.04.2017 12:53
Нужно пояснить/прокомментировать код программы, или коды функций "Добавить" "Удалить" "Обновить(редактировать" "Поиск" "Период") ZIRASS PHP 4 15.06.2016 14:23
Поиск компонента GroupBox с эффектом "спойлер" XerSon Компоненты Delphi 1 24.03.2011 09:59