Aug
16

Странности с dropdown-окном в wxComboBox/wxChoice в Windows Mobile

После долгого перерыва решил снова заняться разработкой для Windows Mobile – доработать программу-переводчик, использующую Google Translate. В программе используется wxChoice cо списком языков. Так как поддерживаемых языков довольно много, то общая высота списка wxChoice получается много больше чем высота экрана КПК. В результате получаем что-то подобное:

Ошибка в вычислении размера dropdown-окна в wxComboBox/wxChoice

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

Перепробовав разные комбинации SetSize()/SetInitialSize()/SetMinSize()/SetMaxSize() нашел вот какое решение:

Если установить размер клиентской области для wxChoice после появления окна, то изменения применяются и получаем нормальный размер выпадающего списка. Если это делать при создании формы, то изменения не применяются.

bool wxGoogleTranslateClientApp::OnInit()
{    
	wxGoogleTranslateClientMainFrame* mainWindow = new wxGoogleTranslateClientMainFrame( NULL );
	mainWindow->Show(true);
	// Очень плохое решение, но только оно и работает
	mainWindow->m_SourceLanguageChoice->SetClientSize(
		mainWindow->m_SourceLanguageChoice->GetClientSize().GetWidth(), 120);
	mainWindow->m_ResultLanguageChoice->SetClientSize(
		mainWindow->m_ResultLanguageChoice->GetClientSize().GetWidth(), 120);
    return true;
}

В результате получаем вот такой результат:
wxComboBox/wxChoice Dropdown Size Problem Fixed

Mar
13

Как создать фигурное окошко в Windows Mobile

И вот еще один небольшой пример, демонстрирующий создание окна непрямоугольной формы в Windows Mobile с библиотекой wxWinCE.

Для реализации подобной штуки нам, прежде всего, необходима форма со стилем wxFRAME_SHAPED, без этого стиля ничего не получится.

Ну а затем нужно выполнить вот такой финт ушами:

  • Создать изображение (черно-белое)
  • Создать для него контекст устройства
  • Нарисовать что-либо (черные пикселы станут прозрачными, белые – видимыми)
  • Создать регион из изображения (wxRegion)
  • Указать форме регион для отображения
void wxMobileTransparencyMainFrame::ChangeShape()
{
	int width(0), height(0);
	// Получаем размер окна
	GetClientSize(&width, &height);
	// Создаем изображение
	wxBitmap bitmap(width, height);
	// Создаем Device Context для изображения
	wxMemoryDC mdc(bitmap);
	// Заполняем черным цветом
	mdc.SetBackground(*wxBLACK_BRUSH);
	mdc.Clear();
	// Устанавливаем кисть белого цвета
	mdc.SetPen(*wxWHITE_PEN);
	wxPoint center(width/2, height/2);
	int radius = wxMin(width, height)/2;
	// Рисуем круг в центре
	mdc.DrawCircle(center, radius);
	// Устанавливаем кисть черного цвета
	mdc.SetPen(*wxBLACK_PEN);
	mdc.SetBrush(*wxBLACK_BRUSH);
	// Рисуем
	mdc.DrawCircle(center.x - radius/3, center.y-radius/4, radius/6);
	mdc.DrawCircle(center.x + radius/3, center.y-radius/4, radius/6);
	mdc.DrawEllipticArc(center.x-radius/3, center.y+radius/4, 
		2 * radius / 3, radius/2, 
		180, 360);
	// Освобождаем Device Context
	mdc.SelectObject(wxNullBitmap);
	// Создаем новый регион
	m_Region = new wxRegion(bitmap, *wxBLACK);
#if defined(__WXWINCE__)
	// Для wxWinCE метод SetRegion() ничего не делает, просто возвращает false.
	// Поэтому приходится устанавливать регион вручную
	HRGN hRgn = (HRGN)m_Region->GetHRGN();
	::SetWindowRgn((HWND)GetHWND(), hRgn, FALSE);
#else
	int offset = GetSize().GetHeight()-GetClientSize().GetHeight();
	m_Region->Offset(0, offset);
	// Устанавливаем регион
	SetShape(*m_Region);
#endif
}

Создаем окно непрямоугольной формы в Windows Mobile
Скачать исходник: Создаем окно непрямоугольной формы в Windows Mobile

Mar
11

Как сменить тему в Windows Mobile программно

Как сменить тему в 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.

Mar
09

Учимся скачивать файлы программно в Windows Mobile

Разработка приложений, использующих в своей работе сетевое взаимодействие или доступ к ресурсам Internet – это довольно популярная штука в наши дни. И в этот раз мы рассмотрим такую часто используемую задачу как загрузка файлов из Internet.

Для того чтобы скачать файл в C++ приложении с wxWinCE надо совсем немного кода. В простейшем случае для реализации однопоточной загрузки файла мы можем использовать класс wxURL, скормив ему адрес загружаемого ресурса.
читать далее…

Feb
14

Видео-урок: Работа с SQLite в Windows Mobile

Новый скринкаст о том как собрать минимальное приложение для Windows Mobile, работающее с базой данных SQLite.

Из видео можно узнать:

  • Как создать минимальное приложение для Windows Mobile с wxWinCE.
  • Собрать библиотеку SQLite3 для Windows Mobile 5.
  • Собрать библиотеку-обертку wxSQLite3 для работы с базами данных SQLite.
  • Создать базу данных SQLite.
  • Создать таблицы в базе данных SQLite.
  • Сделать выборку данных из таблицы.
  • Обработать исключения, возникающие при ошибках доступа к базам SQLite.
Feb
08

Работаем с журналом звонков в Windows Mobile

В этот раз я расскажу о том, как работать с журналом звонков на С++ в Windows Mobile.

Для доступа к журналу звонков Windows Mobile имеет такую вещь, как Phone API.

Непосредственно для наших целей необходима всего небольшая часть функций, доступных в рамках Phone API, а именно:

  • PhoneOpenCallLog – открывает журнал звонков для чтения и возвращает хэндл, использующийся впоследствии для доступа к записям журнала.
  • PhoneGetCallLogEntry – получает данные о записи журнала звонков и заполняет структуру CALLLOGENTRY этими данными
  • PhoneCloseCallLog – закрывает хэндл журнала звонков.

читать далее…

Dec
15

Пишем мобильную игру на wxWidgets

Введение

В этот раз речь пойдет о разработке мобильных приложений, а если быть точным, то мобильных игр, с библиотекой wxWidgets (порт wxWinCE).
О том, как собрать wxWidgets для разработки приложений для Windows Mobile я уже писал ранее здесь. Как создать простейшее приложение с wxWinCE, рассказано в этой статье.
Здесь и далее по тексту подразумевается, что читатель уже может самостоятельно создать простейшее приложение с wxWinCE, а также настроить параметры сборки для PocketPC и Smartphone.

Каркас приложения

Так случилось, что я решил попробовать себя в написании мобильных игр. После небольшого исследования пришел к выводу, что в простейшем случае для этой задачи вполне может подойти архитектура Документ/Представление (Document/View).
читать далее…

Dec
08

Отображаем анимированный GIF под Windows Mobile

Как-то печально обстоят дела с отображением анимации на устройствах под управлением 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 этого функционала нет).

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

Nov
25

Настраиваем средства разработки для Windows Mobile (C++/wxWinCE) в Linux

Благодаря стараниям Станислава Блинова у нас появилась возможность разрабатывать ПО для Windows Mobile в Linux, используя компилятор cegcc и библиотеку wxWidgets. О том как настроить средства разработки для Windows Mobile под Linux рассказано в ниже следующей статье:

Захотелось мне тут выяснить, насколько “умерла” бесплатная разработка софта под WinCE. Великий Гугель вывел меня на штуку под названием cegcc – кросс-компилятор, позволяющий собирать WinCE приложения под Линуксом. После возвращения из осадка, в который я выпал, узрев данный инструмент, я решил его проверить на практике.

читать далее…

Oct
31

Пишем мобильный клиент для Google Translate на C++

В этот раз я хочу рассказать о том как работать с еще одним online-сервисом, а именно с сервисом online-переводов Google Translate.

Для работы с этим сервисом у Google есть свой программный интерфейс, а именно AJAX Language API for Translation And Detection. Именно его мы и будем использовать.

Для того чтобы осуществить online-перевод текста необходимо сделать http-запрос к сервису переводов, доступному по адресу:

http://ajax.googleapis.com/ajax/services/language/translate

Параметры, которые необходимо передать сервису:

  • v=1.0 – версия сервиса
  • q=<sometext> – URL-encoded текст для перевода.
  • langpair=<source_language>%7C<result_language> – пара названий языков: исходного и результирующего

читать далее…


top