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

May
08

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

Для того чтобы установить соединение с Internet в Windows Mobile предусмотрен специальный программный интерфейс – Connection Manager API.
Пользоваться им довольно просто. И вот пример такого использования для C# и C++ приведен ниже:
читать далее…

May
07

Скажите “нет” GAPI – Все что вам нужно знать об AllKeys и обработке нажатия клавиш в Windows Mobile

Games API (GAPI) это технология, которая позволяла приложениям для Windows Mobile 2003 быстро отрисовывать графику на экране. В ней также были функции, которые позволяли получать сообщения о нажатии клавиш, даже для тех, которые обрабатываются операционной системой Windows Mobile самостоятельно.

Графическая составляющая GAPI была заменена на DirectShow (которая позволяла использовать аппаратное ускорение) в Windows Mobile 5.0. В тоже время поддерживалась совместимость с GAPI для того чтобы старые приложения продолжали работать.

Большая часть материалов по GAPI была упразднена в документации к Windows Mobile 6.1, в то же время функции для обработки ввода были оставлены и приложения могли запрашивать обработку нажатия всех клавиш. Совместимость приложений поддерживалась и для этой версии

Все это меняется в новой версии Windows Mobile, в Windows Mobile 6.5. В то же время некоторые устройства все еще могут поддерживать GAPI, но поддержка и тестирование GAPI более не является необходимостью для производителей устройств и для мобильных операторов. Это значит что если приложение требует GAPI, оно может вызвать непредсказуемое поведение на устройствах с Windows Mobile 6.5.

Другим важным изменением является тот факт что для приема в Windows Marketplace for Mobile и для сертификации Designed for Windows Mobile необходимо чтобы приложение не зависело от GAPI.

Для замены функционала, предоставляемого GAPI, новая функция для работы с клавиатурой была введена в публичное API. Это функция AllKeys(). В этой ситуации с введением новой функции есть одна классная штука – она была доступна и ранее наряду с GAPI b на самом деле это API функция, оберткой над которой GAPI и являлась. Это значит что миграция на AllKeys() lолжна быть довольно простой и обратную совместимость можно будет поддерживать без проблем.

Миграцию на AllKeys() можно осуществить очень просто – заменой

  • GXOpenInput() на AllKeys(TRUE).
  • GXCloseInput() на AllKeys(FALSE).

Функция AllKeys() поддерживается для Windows Mobile 2003 и выше. Определена в Winuser.h

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

// process checkbox

case IDC_ALL_KEYS_CHECK_BOX:

if (g_AllKeys == true)
{
    // Allow the OS to intercept some button presses
     AllKeys(FALSE);
    g_AllKeys = false;
    // set button state
    SendMessage(hwndCtl,BM_SETCHECK, BST_UNCHECKED,0);
}
else
{
    // Do not allow os to intercept button presses
    AllKeys(TRUE);
    g_AllKeys = true;
    //set button state
    SendMessage(hwndCtl,BM_SETCHECK, BST_CHECKED,0);
} 

Всю эту интересность я узнал из поста в Windows Mobile Team Blog. Эта статья является вольным переводом исходной.

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 
#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.

Mar
09

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

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

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

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
28

Вышел Smart Device Framework 2.3

Разработчики OpenNETCF выпустили новую версию библиотеки Smart Device Framework, которая содержит множество полезных классов, значительно упрощающих разработку приложений для Windows Mobile на платформе .NET. Есть бесплатная версия Smart Device Framework. По большому счету из недостатков бесплатной версии по сравнению с платными можно назвать отсутствие интеграции с Visual Studio и дизайнером форм.

Набор классов, судя по описанию на сайте, у всех версий аналогичный. Отсутствие поддержки для бесплатной версии меня, например, особо не пугает.

Ваша реклама на коробках салфеток: салфетки антисептические. Гостиничная продукция и многое др.

top