Как-то печально обстоят дела с отображением анимации на устройствах под управлением Windows Mobile. Искал решение на .NET Compact Framework, нашел на Stack Overflow. Там предлагают писать собственный контрол, который будет делить изображение на кадры и отображать их с заданной периодичностью. Там в ответах ссылка на статью в MSDN. Собственно, везде это решение рекомендуют, но мне оно как-то не очень понравилось ввиду того, что позволяет отображать только специально подготовленное изображение, что во многих случаях очень неудобно.

А вот для тех, кто пишет ПО для Windows Mobile на C++ с wxWinCE эта проблема решается намного проще, с помощью wxAnimationCtrl. Вобще никаких лишних телодвижений делать не надо:

void wxAnimateMobileMainFrame::OnOPENClick( wxCommandEvent& event )
{
	wxFileDialog * dlg = new wxFileDialog(this, wxFileSelectorPromptStr, wxEmptyString,
		wxEmptyString, _("GIF Files (*.gif)|*.gif"));
	if(dlg->ShowModal() == wxID_OK)
	{
		m_AnimationCtrl->LoadFile(dlg->GetPath());
		m_AnimationCtrl->Play();
	}
	dlg->Destroy();
}

Из полезных возможностей:

  • Загрузка GIF-изображений с любым количеством кадров
  • Поддержка различных интервалов задержки для различных кадров
  • Циклическое воспроизведение (прописывается в самом GIF-файле)

Оказывается, все-таки, для некоторых задач C++ пользовать удобнее (хотя все равно для меня остается загадкой почему в .NET CF этого функционала нет).

Исходный код примера можно загрузить здесь.

Previous ArticleNext Article
Технический директор IT-Dimension, компании-разработчика кросс-платформенного программного обеспечения

This post has 3 Comments

3
  1. под мобайл/СЕ успешно работает GDI+ которое умеет парсить гифы, так что написать свой контрол который показывает гифы не составит труда… или вы думаете вх либа по другому как-то работает?

    З.Ы. можно и ручками распарсить

  2. Ммм? Оно действительно работает по-другому как-то, точнее, загружает GIF-файлы с помощью своего Image Handler’а (который не только под Win работает), а потом wxAnimationCtrl по таймеру их руками-то и отображает, только в отличии от предложенного для .NET CF варианта с константным интервалом таймера, там интервал берется для каждого кадра из файла как прописано, т.е. более “правильный” вариант получается.

  3. в любом случае оно прасит анимириованный-гиф файл, иначе никак, в net CF или просто поленились это сделать или посчитали что это можно сделать и самому (я склоняюсь ко 2-му варианту), кстати и в .NET анимированный гифы вроде не работают

Leave a Reply

Your email address will not be published. Required fields are marked *

Q.

Qt для платформы S60

Совсем недавно в блоге разработчиков Qt появилась информация о том что доступна Technology Preview версия Qt для устройств на платформе S60.

На данный момент доступны модули:

  • QtCore – all the non-Gui classes
  • QtGui – painting and widgets
  • QtNetwork – TCP, HTTP and all that
  • QtTest – unit testing

Анонсирована поддержка устройств S60 3.1 и выше.

Загрузить Qt for S60 можно здесь.

Дополнительную информацию о Qt for S60 можно узнать здесь.

Также на YouTube можно найти видео-ролик с демонстрацией работы Qt на устройствах S60:

Р.

Работаем с LED-индикаторами устройства под управлением Windows Mobile

Для того чтобы управлять LED-индикаторами устройства, в Windows Mobile предусмотрено специальное API:

BOOL WINAPI NLedSetDevice(UINT nDeviceId, void* pInput);

Первый параметр, nDeviceID указывает на то, какие данные передаются в параметре pInput. Для того чтобы установить состояние LED-индикатора, параметр nDeviceID должен иметь значение NLED_SETTINGS_INFO_ID, а в качестве параметра pInput необходимо передать указатель на структуру NLED_SETTINGS_INFO, содержащую информацию о новом состоянии LED-индикатора.

struct NLED_SETTINGS_INFO {
UINT LedNum;
INT OffOnBlink;
LONG TotalCycleTime;
LONG OnTime;
LONG OffTime;
INT MetaCycleOn;
INT MetaCycleOff;
};
  • LedNum – содержит индекс LED-индикатора (zero-based).
  • OffOnBlink – содержит новое состояние индикатора (0 – выключен, 1 – включен, 2 – мигающий
  • TotalCycleTime – длительность цикла мерцания в миллисекундах
  • OnTime – длительность включенного состояния индикатора при мерцании
  • OffTime – длительность выключенного состояния индикатора при мерцании
  • MetaCycleOn – количество ON-циклов
  • MetaCycleOff – количество OFF-циклов

Вобще описание назначения последних двух полей структуры вводит меня в недоумение. В MSDN по этому поводу всего две скупые фразы “Number of on blink cycles.” и “Number of off blink cycles.” без какого-либо дальнейшего пояснения.

Для того чтобы получить количество LED-индикаторов в системе можно воспользоваться функцией NLedGetDeviceInfo:

BOOL WINAPI NLedGetDeviceInfo(UINT nInfoId, void* pOutput);

В качестве первого параметра необходимо передать значение NLED_COUNT_INFO_ID, в качестве второго параметра – указатель на структуру NLED_COUNT_INFO, которая, в случае успешного завершения работы функции, будет содержать количество индикаторов.

Ну вот, с теоретической частью закончили, теперь перейдем к рассмотрению простенького примера. А в качестве примера у нас будет небольшая библиотека-обертка над описанным выше API.

wxMobileLED.h

#ifndef _WX_MOBILE_LED_H
#define _WX_MOBILE_LED_H

class wxMobileLEDImpl;

class wxMobileLED
{
	wxMobileLEDImpl * m_Impl;
public:
	wxMobileLED();
	~wxMobileLED();
	size_t GetCount();
	bool SetLED(size_t index, bool value, bool blink = false);
};

#endif

wxMobileLED.cpp

#include "wxMobileLED.h"
#if defined(__WXWINCE__)
#include "wxMobileLEDImplWinCE.h"
#else
#endif

wxMobileLED::wxMobileLED()
{
	m_Impl = 
#if defined(__WXWINCE__)
		new wxMobileLEDImplWinCE;
#else
		NULL;
#endif
}

wxMobileLED::~wxMobileLED()
{
	if(m_Impl) delete m_Impl;
}

size_t wxMobileLED::GetCount()
{
	if(m_Impl)
	{
		return m_Impl->GetCount();
	}
	return 0;
}

bool wxMobileLED::SetLED(size_t index, bool value, bool blink)
{
	if(m_Impl)
	{
		return m_Impl->SetLED(index, value, blink);
	}
	return false;
}

wxMobileLEDImpl.h

#ifndef _WX_MOBILE_LED_IMPL_H
#define _WX_MOBILE_LED_IMPL_H

class wxMobileLEDImpl
{
public:
	virtual size_t GetCount() = 0;
	virtual bool SetLED(size_t index, bool value, bool blink = false) = 0;
};

#endif

wxMobileLEDImplWinCE.h

#ifndef _WX_MOBILE_LED_IMPL_WINCE_H
#define _WX_MOBILE_LED_IMPL_WINCE_H

#include "wxMobileLEDImpl.h"

class wxMobileLEDImplWinCE : public wxMobileLEDImpl
{
public:
	virtual size_t GetCount();
	virtual bool SetLED(size_t index, bool value, bool blink = 0);
};

#endif

wxMobileLEDImplWinCE.cpp

#include "wxMobileLEDImplWinCE.h"
#include <windows.h>
#include <NLed.h>

size_t wxMobileLEDImplWinCE::GetCount()
{
#if defined(__WXWINCE__) && (UNDER_CE >= 0x500)
	NLED_COUNT_INFO count = {0};
	NLedGetDeviceInfo(NLED_COUNT_INFO_ID,&count); 
	return count.cLeds;
#else
	return 0;
#endif
}

bool wxMobileLEDImplWinCE::SetLED(size_t index, bool value, bool blink)
{
#if defined(__WXWINCE__) && (UNDER_CE >= 0x500)
	do
	{
		if(index >= GetCount()) break;
		NLED_SETTINGS_INFO info;
		ZeroMemory(&info, sizeof(NLED_SETTINGS_INFO));
		info.LedNum = index;
		info.OffOnBlink = value ? (blink ? 2 : 1) : 0;
		return (NLedSetDevice(NLED_SETTINGS_INFO_ID, &info) == TRUE);
	}
	while(false);
#endif
	return false;
}

Пример использования библиотеки:


wxMobileLED m_MobileLED;

...
void wxMobileLEDTestMainFrame::FillLEDList()
{
	size_t ledCount = m_MobileLED.GetCount();
	for(size_t i = 0; i < ledCount; i++)
	{
		int item = m_LEDList->Append(wxString::Format(wxT("LED %i"), i+1));
	}
}

void wxMobileLEDTestMainFrame::UpdateLEDs()
{
	for(size_t i = 0; i < m_LEDList->GetCount(); i++)
	{
		bool value = m_LEDList->IsChecked(i);
		if(!m_MobileLED.SetLED(i, value, m_BlinkCheckBox->GetValue()))
		{
			wxLogTrace(wxTraceMask(), _("Unable to turn LED #%i %s"), i, 
				value ? _("ON") : _("OFF"));
		}
	}
}

Исходный код примера для wxWinCE, а также исполняемый файл для Windows Mobile 6 можно взять здесь.

PS: Хотя описанное выше API предназначено для управления состоянием LED-индикаторов и на эмуляторе действительно управляет ими, но на реальном устройстве (ETEN Glofiish X800 под управлением Windows Mobile 6) включение/віключение индикатора с индексом 1 приводит к включению/віключению вибро. Мая шоке %).