Как сменить тему в Windows Mobile программноЗадался тут вопросом о программной смене темы в Windows Mobile. Оказывается это не так просто, как может показаться. Информация с MSDN’овских форумов и из самой MSDN мягко говоря не соответствует действительности. В Интернете полно топиков с подобными вопросами, но вменяемый результат выудить оттуда тоже почти нереально.

После нескольких часов мучений получил вроде вполне рабочий результат. А результатом, собственно, стал небольшой класс для установки и получения темы для Windows Mobile.

Но перед тем, как мы перейдем к рассмотрению примера, давайте, все же, определимся с последовательностью действий:

  • Имя файла текущей темы находится в реестре по адресу “HKEY_CURRENT_USER\Software\Microsoft\Today\Skin”
  • Первым шагом для смены темы в Windows Mobile является запуск утилиты \Windows\wcrload.exe c параметрами /noui /nouninstall /delete 0 “путь_к_файлу_темы.tsk” (кавычки нужны для того, чтобы правильно обрабатывались пути с пробелами. Это важно!).
  • Затем надо удалить в реестре значение по адресу “HKEY_LOCAL_MACHINE\Software\Microsoft\Color\BaseHue” иначе после применения темы изменится только фоновая картинка в Today, а цветовая схема останется прежней (тоже долго искал почему не применяется тема полностью, это тоже важный момент).
  • Затем надо удалить значение в реестре по адресу “HKEY_CURRENT_USER\Software\Microsoft\Today\UseStartImage”.
  • После этого нужно прописать прописать путь к файлу темы в реестре по адресу “HKEY_CURRENT_USER\Software\Microsoft\Today\Skin”.
  • И последнее, что нужно сделать, это разослать всем окнам сообщение об изменении настроек системы с помощью ::PostMessage(HWND_BROADCAST, WM_WININICHANGE, 0xF2, 0)

А теперь пример:

#ifndef _MOBILE_THEME_SWITCH_H
#define _MOBILE_THEME_SWITCH_H

#include <wx/wx.h>
#include <wx/filename.h>
#include <wx/msw/registry.h>

class MobileThemeSwitch
{
public:
	static wxString GetTheme()
	{
		wxString result;
		do 
		{
			wxRegKey key(wxRegKey::HKCU, wxT("Software\\Microsoft\\Today"));
			if(!key.Exists()) break;
			if(!key.Open(wxRegKey::Read)) break;
			const wxString skinValueName(wxT("Skin"));
			if(!key.HasValue(skinValueName)) break;
			if(!key.QueryValue(skinValueName, result)) break;
		} 
		while (false);
		if(result.IsEmpty()) result = _("default");
		return result;
	}
	static bool SetTheme(const wxString & value)
	{
		wxRegKey  * key(NULL);
		do 
		{
			wxString wceLoadFileName = wxT("\\Windows\\wceload.exe");
			if(!wxFileExists(wceLoadFileName)) 
			{
				wxLogDebug(_("'wceload.exe' does not exist"));
				break;
			}
			wxString commandLine = wxString::Format(
				wxT("%s /noui /nouninstall /delete 0 \"%s\""),
				wceLoadFileName.GetData(),
				value.GetData());
			long execResult = wxExecute(commandLine, wxEXEC_SYNC);
			if(execResult != 0)
			{
				wxLogDebug(_("'wceload.exe' returned error (%l)"), execResult);
				break;
			}
			key = new wxRegKey(wxRegKey::HKLM, wxT("Software\\Microsoft\\Color"));
			if(!key->Exists())
			{
				wxLogDebug(_("'Software\\Microsoft\\Color' registry key does not exist"));
				break;
			}
			if(!key->Open(wxRegKey::Write))
			{
				wxLogDebug(_("Unable to open registry key 'Software\\Microsoft\\Color'"));
				break;
			}
			const wxString baseHueValueName(wxT("BaseHue"));
			if(key->HasValue(baseHueValueName))
			{
				key->DeleteValue(baseHueValueName);
			}
			key->Close();
			wxDELETE(key);
			key = new wxRegKey(wxRegKey::HKCU, wxT("Software\\Microsoft\\Today"));
			if(!key->Exists())
			{
				wxLogDebug(_("'Software\\Microsoft\\Today' registry key does not exist"));
				break;
			}
			if(!key->Open(wxRegKey::Write))
			{
				wxLogDebug(_("Unable to open registry key 'Software\\Microsoft\\Today'"));
				break;
			}
			const wxString useStartImageValueName(wxT("UseStartImage"));
			if(key->HasValue(useStartImageValueName))
			{
				key->DeleteValue(useStartImageValueName);
			}
			const wxString skinValueName(wxT("Skin"));
			if(!key->SetValue(skinValueName, value))
			{
				wxLogDebug(_("Unable to change value 'Skin' in 'Software\\Microsoft\\Today'"));
				break;
			}
			key->Close();
			wxDELETE(key);
			::PostMessage(HWND_BROADCAST, WM_WININICHANGE, 0xF2, 0);
			return true;
		} 
		while (false);
		wxDELETE(key);
		return false;
	}
};

#endif

Скачать исходный код примера + исполняемый файл для Windows Mobile 6.0.

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

Leave a Reply

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

w.

wxYahooMaps – Библиотека для работы с Yahoo! Maps Image API

Странная вещь получается. А ведь нету нормальных библиотек для С++, работающих с online-сервисами карт. Все популярные сервисы предоставляют API для .NET, а С++, как мне кажется, незаслуженно обделяют своим вниманием.
И вот пару дней назад решил восполнить этот пробел. Выбор пал на сервис Yahoo! Maps, а если быть точным, то Yahoo! Map Image API, которое позволяет получить изображение карты, сформировав определенным образом REST (Representational State Transfer) запрос.

Ознакомиться с механизмом работы сервиса можно здесь. Сильно подробно описывать не буду, скажу только что смысл заключается в формировании URL, открыв который мы получим XML-файл с адресом изображения карты.

Необходимым условием для работы с Yahoo! Map Image API является наличие у приложения уникального идентификатора (Application ID), получить который можно здесь (кстати, я уже писал ранее что Maps API для Google Android тоже требует Application ID).

Итак, wxYahooMaps. Что это такое и как это работает: это wxWidgets-based библиотека, которая позволяет по указанным координатам (широта + долгота) или названию местности (улица/город/штат/почтовый код) получить изображение карты, в центре которого будет искомая точка. Библиотека загружает карты асинхронно и поддерживает многопоточную загрузку, что иногда бывает очень удобным.

Для того чтобы начать пользоваться wxYahooMaps достаточно выполнить несколько простых действий:

Создать объект класса wxYahooMap (желательно чтобы это был член класса формы или приложения, т.е. был доступен на протяжении всей работы программы):


wxYahooMap * m_YahooMap;

...

m_YahooMap = new wxYahooMap(this);

К форме, которая должна получать уведомления о состоянии процесса загрузки карт добавить обработчик события EVT_YAHOO_MAP_STATUS:


BEGIN_EVENT_TABLE( wxYahooMapsTestMainFrame, wxFrame )
...
EVT_YAHOO_MAP_STATUS(wxID_ANY, wxYahooMapsTestMainFrame::OnYahooMapStatus)
END_EVENT_TABLE()

void wxYahooMapsTestMainFrame::OnYahooMapStatus(wxYahooMapStatusEvent & event)
{
	if(event.GetInt() == 0)
	{
		wxBitmap * bmp = event.GetBitmap();
		if(bmp)
		{
			// Здесь работаем с изображением карты
			// После этого изображение надо удалить
			wxDELETE(bmp);
		}
	}
	else
	{
		// Обработать ошибку
	}
}

Теперь для того чтобы загрузить изображение карты необходимо указать необходимые параметры поиска и вызвать метод wxYahooMap::StartDownload()

void wxYahooMapsTestMainFrame::OnGOBUTTONClick( wxCommandEvent & event )
{
	TransferDataFromWindow();
	m_YahooMap->SetApplicationID(m_AppID);
	m_YahooMap->SetUsePosition(m_UsePosition);
	m_YahooMap->SetPosition(wxRealPoint(m_Longitude, m_Latitude));
	m_YahooMap->SetStreet(m_Street);
	m_YahooMap->SetCity(m_City);
	m_YahooMap->SetState(m_State);
	m_YahooMap->SetZIPCode(m_ZIPCode);
	m_YahooMap->SetImageType(wxYahooMap::IntToYahooMapImageType(m_ImageType));
	m_YahooMap->SetImageSize(wxSize(m_ImageWidth, m_ImageHeight));
	m_YahooMap->SetZoomLevel(m_ZoomLevel);
	m_YahooMap->StartDownloading();
}

После окончания загрузки карты будет вызван обработчик события wxEVT_YAHOO_MAP_STATUS, в котором можно произвести необходимые действия с изображением карты. После этого обязательно необходимо очистить память, занятую объектом изображения.
В результате у нас должно получиться что-то вроде этого:

На данный момент библиотека wxYahooMaps оттестирована под:

  • Windows Vista
  • Windows XP
  • Windows Mobile 2003 (PPC)
  • Windows Mobile 6.0

Проводится тестирование под Mac OS и Linux.
Исходный код можно загрузить из SVN-репозитория на Google Code. Там же можно загрузить исполняемый файл примера для Windows XP/Vista.

PS: Если кто-либо из читателей блога желает помочь в развитии проекта, можно оставлять свои контакты в комментариях. На данный момент требуется помощь в реализации работы с геокодером Yahoo!.

Д.

Доступна регистрация в Windows Marketplace for Mobile

И вот, ура! Свершилось наконец-то. Microsoft открыла регистрацию в Windows Marketplace for Mobile и разработчики, которые пишут для Windows Mobile могут уже начать работать с этой площадкой продажи мобильных приложений. Вот уже смотрю на условия участия… Годовая подписка стоит эээ.. 67 фунтов. Как-то… немало. По сравнению с 25 долларами для Android Marker, цена довольно высокая.