Задался тут вопросом о программной смене темы в 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
#include
#include
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.