В прошлый раз я рассказывал о том как собрать библиотеку wxWinCE для разработки приложений для Windows Mobile.

Сегодня мы поговорим о том, как начать программировать с использованием этой библиотеки и как создать простейшее приложение для Windows Mobile с ее помощью.

Итак, что у нас уже должно быть: собранная библиотека wxWinCE, создана переменная окружения WXWIN, которой присвоен путь к дистрибутиву wxWinCE, файлы статических библиотек размещены в папках:

  • $(WXWIN)/lib/evc_armv4_lib для платформы PocketPC 2003
  • $(WXWIN)/lib/evc_armv4t_lib для платформы Windows Mobile 6

Для начала нам необходимо создать новый проект. Для этого в Visual Studio выбираем пункт меню File -> New -> Project… В диалоговом окне создания нового проекта переходим в раздел Visual C++ -> Smart Device и указываем тип проекта Win32 Smart Device Project.

В мастере настройки свойств проекта выбираем платформы, для которых нам необходимо собрать наше приложение.

В разделе Application Settings выбираем тип проекта Windows Application и в Additional Options устанавливаем маркер на Empty Project.

Жмем Finish.

В созданный проект добавляем новый cpp-файл и пишем в нем следующее:

#include <wx/wx.h>

class wxWinCETestMainFrame : public wxFrame
{
protected:
	void OnExit(wxCommandEvent & event)
	{
		Close();
	}
public:
	wxWinCETestMainFrame()
		: wxFrame(NULL, wxID_ANY, _("wxWinCE Test"))
	{
		wxMenuBar * menuBar = new wxMenuBar;
		wxMenu * fileMenu = new wxMenu;
		fileMenu->Append(wxID_EXIT, _("Exit"));
		menuBar->Append(fileMenu, _("File"));
		SetMenuBar(menuBar);

		Connect(wxID_EXIT, wxEVT_COMMAND_MENU_SELECTED, 
			wxCommandEventHandler(wxWinCETestMainFrame::OnExit));
	}
};

class wxWinCETestApp : public wxApp
{
public:
	virtual bool OnInit()
	{
		wxWinCETestMainFrame * frame = new wxWinCETestMainFrame;
		SetTopWindow(frame);
		frame->Show();
		return true;
	}
};

IMPLEMENT_APP(wxWinCETestApp)

Открываем окно свойств проекта, переходим в раздел C/C++ -> General и в список каталогов для поиска заголовочных файлов (Additional Include Directories) добавляем следующие значения:

  • Для платформы PocketPC 2003
    • Debug
      • $(WXWIN)\include
      • $(WXWIN)\lib\evc_armv4_lib\winced
    • Release
      • $(WXWIN)\include
      • $(WXWIN)\lib\evc_armv4_lib\wince
  • Для платформы Windows Mobile 6
    • Debug
      • $(WXWIN)\include
      • $(WXWIN)\lib\evc_armv4t_lib\winced
    • Release
      • $(WXWIN)\include
      • $(WXWIN)\lib\evc_armv4t_lib\wince

В разделе Linker -> General в свойстве Additional Library Directories дописываем путь к статическим библиотекам wxWinCE:

  • $(WXWIN)\lib\evc_armv4_lib для платформы PocketPC 2003
  • $(WXWIN)\lib\evc_armv4t_lib для платформы Windows Mobile 6

В разделе C/C++ -> Code Generation устанавливаем свойство Enable C++ Exceptions в No (то же значение что и в проекте самой библиотеки wxWinCE) и для каждой конфигурации каждой платформы значение свойства Runtime Library устанавливаем в то значение, которое оно имеет в проекте библиотеки wxWinCE. Значение обоих этих свойств у нашего проекта и у проекта библиотеки должны быть одинаковыми.

В разделе C/C++ -> Preprocessor значение свойства Preprocessor Definitions для каждой конфигурации для каждой платформы устанавливаем то, которое оно имеет в проекте библиотеки wxWinCE. Лучше всего значение этого свойства скопировать с одного проекта в другой.

Теперь нам необходимо добавить в проект файл ресурсов (.rc) и в нем прописать следующее:


#include <wx/msw/wx.rc>

Это очень важный шаг настройки проекта, но о нем очень часто забывают. Зачем же это нужно? Затем что файл wx/msw/wx.rc содержит описание некоторых ресурсов приложения, которые используются при создании строк меню и панелей инструментов. Если этот файл не включить в сборку, то при создании строк меню будут постоянно возникать ошибки.

После того, как мы добавили файл ресурсов, в свойствах проекта идем в раздел Resources -> General и в Additional Include Directories добавляем значение $(WXWIN)\include.

Ну вот, но этом настройка проекта завершена. Можно собирать наше приложение.

После того как приложение успешно собрано, мы должны получить что-то подобное:

Скриншот минимального приложения для wxWinCE
Скриншот минимального приложения для wxWinCE

Мы получили приложение с одной формой, у которой есть меню с единственным пунктом Exit, при выборе которого приложение закрывается.

Напоследок хотелось бы сказать вот что: процесс настройки проекта на первом этапе знакомства с wxWidgets может показаться довольно сложным, но так кажется только вначале. Сам же процесс написания кода, добавления новых компонентов на формы, создание обработчиков событий довольно прост, намного проще чем с использованием MFC, особенно если для создания графического интерфейса использовать DialogBlocks, о котором я расскажу в следующий раз.

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

This post has 53 Comments

53
  1. Еще раз собрал библиотеку и проект приложения по пунктам из твоих постов. Build log скинул на paste.org.ru. Ошибки те же , a в linker->general->additional library directories = “$(WXWIN)\lib\evc_armv4t_lib”
    Как именно нужно скормить линкеру lib файл?

Leave a Reply

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

А.

Анонс Windows Mobile API Usage Tool!

Разработчики из Windows Mobile Team в своем блоге анонсировали инструмент мониторинга использования API функций в приложениях для Windows Mobile – Windows Mobile API Usage Tool.
Windows Mobile API Usage Tool сканирует ваше приложение для Windows Mobile (в формате cab, msi, или просто бинарник), выполняет статический анализ (static analysis), и выдает отчет об использовании API и других системных ресурсов.
В дистрибутив также входит файл deprecated.txt, в котором содержится текущий список упраздненных (deprecated) функций для Windows Mobile. Можно также получить отчет об использовании этих функций в вашем приложении. Использование Windows Mobile API Usage Tool это эффективный способ проверить то, как ваше приложение будет себя вести если deprecated-функции будут удалены из Windows Mobile.
Windows Mobile API Usage Tool работает из командной строки и выдает результат в виде базы данных SQL Compact Edition (.sdf файл). При вызове с ключем /deprecated также генерируются несколько полезных отчетов.

К.

Кросс-платформенная разработка — Windows Mobile и Windows (.NET Compact Framework, C#)

В этот раз статья от Андрея Коновалова о том, как сделать мультиплатформенный проект в Visual Studio с использованием .NET Compact Framework.
Не так много разработчиков осознают, что разрабатывая приложения для платформы Windows Mobile с использованием Compact Framework, у них существуют шансы собрать это же приложение под десктоп версию Windows! Я и сам об этом долгое время только задумывался, предполагая, что подобная возможность есть, но не рассматривал её как нечто, хоть сколько-нибудь реальное.

Существует несколько важных аспектов, которые нужно понимать, чтобы успешно организовать кросс-платформенную сборку. Я потратил прилично времени, собирая обломки знаний в разных местах сети, причём местами было настолько нетривиально, что решил поделиться с хабрасообществом тонкостями.

Во-первых, во-вторых, в-третьих…

Во-первых, необходимо изначально создавать приложение для Windows Mobile (т.е. это основная платформа). Это действительно важно. Причин несколько, но основная заключается в том, что Compact Framework на то и компактный, что там существенно меньше классов и свойств у классов. Т.е. совместимость с десктопом есть, но односторонняя, т.е. только в сторону десктопа.

Во-вторых, нужно понимать, что отличия в приложении всё-таки будут и их придётся программировать отдельно. Например, стандартное меню, находящееся внизу на Windows Mobile автоматически перемещается наверх, и там Cancel и More выглядят не очень привлекательно. Далее, на десктопе в принципе нет InputPanel. Т.е. по сути нужно быть готовым к инструкциям компилятору #if #else #endif.

В-третьих, надо также готовиться к тому, что будут некоторые ограничения, касающиеся дизайна форм. А именно, нельзя открывать форму визуальным редактором при десктопе, выбранном в качестве текущего таргета — сразу же в *.Designer.cs налетит множество свойств, не поддерживаемых мобильным фреймворком — придётся откатывать.

В-четвёртых, придётся вручную править *.csproj файлы и видеть в Solution Explorer-е жёлтые треугольники — это нормально 🙂

В пятых, не все сборки и неймспесы на 100% работают на десктопе. Например, я совершенно не уверен в том, что SQL Server Compact собирается на десктопе. Не проверял, поэтому не обещаю. Точно знаю, что с SQLite всё хорошо (хотя и придётся попотеть немного).

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

Попробуем разобраться с основными тонкостями.

Desktop Target

Начнём с того, что у нас должен быть некоторый проект, созданный для Compact Framework. Создадим новый таргет через Build->Configuration Manager:

Windows Mobile and Windows - Configuration ManagerПосле этого добавим символ условной компиляции в свойствах проекта:

Windows Mobile and Windows - Project SettingsНачало положено. Посмотрим теперь, что делать, чтобы обеспечить подключение правильных сборок в нужном таргете. По умолчанию в нашем csproj файле нет никаких разделений по таргетам:

 <ItemGroup>
  <Reference Include="mscorlib" />
  <Reference Include="System" />
  <Reference Include="System.Data" />
  <Reference Include="System.Drawing" />
  <Reference Include="System.Windows.Forms" />
  <Reference Include="System.Xml" />
 </ItemGroup>

Чтобы иметь полный контроль, необходимо организовать примерно следующий финт:

<ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
  <Reference Include="mscorlib">
   <Private>False</Private>
  </Reference>
  <Reference Include="Microsoft.WindowsMobile, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
   <SpecificVersion>False</SpecificVersion>
   <HintPath>..\..\..\..\..\Program Files\Windows Mobile 6 SDK\Managed Libraries\Microsoft.WindowsMobile.dll</HintPath>
  </Reference>
  <Reference Include="Microsoft.WindowsMobile.Status, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
   <SpecificVersion>False</SpecificVersion>
   <HintPath>..\..\..\..\..\Program Files\Windows Mobile 6 SDK\Managed Libraries\Microsoft.WindowsMobile.Status.dll</HintPath>
  </Reference>
  <Reference Include="Microsoft.WindowsCE.Forms">
   <Private>True</Private>
  </Reference>
  <Reference Include="System" />
  <Reference Include="System.Data">
   <Private>False</Private>
  </Reference>
  <Reference Include="System.Windows.Forms" />
  <Reference Include="System.Drawing" />
  <Reference Include="System.Data.SQLite, Version=1.0.60.0, Culture=neutral, PublicKeyToken=1fdb50b1b62b4c84, processorArchitecture=MSIL">
   <Private>True</Private>
   <HintPath>..\..\..\..\..\Program Files\SQLite.NET\bin\CompactFramework\SQLite.Interop.060.DLL</HintPath>
  </Reference>
 </ItemGroup>

 <ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Desktop|AnyCPU' ">
  <Reference Include="mscorlib">
   <Private>False</Private>
   <HintPath>C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscorlib.dll</HintPath>
  </Reference>
  <Reference Include="System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=x86">
   <HintPath>C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll</HintPath>
  </Reference>
  <Reference Include="System.Windows.Forms">
   <HintPath>C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Windows.Forms.dll</HintPath>
  </Reference>
  <Reference Include="System.Drawing">
   <HintPath>C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Drawing.dll</HintPath>
  </Reference>
  <Reference Include="System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=x86" />
  <Reference Include="System.Data.SQLite, Version=1.0.60.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=x86">
   <Private>True</Private>
   <HintPath>..\..\..\..\..\Program Files\SQLite.NET\bin\System.Data.SQLite.DLL</HintPath>
  </Reference>
 </ItemGroup>

Как видно, мы разделяем блоки ItemGroup по таргетам и указываем разные пути до сборок. Признаюсь, что именно здесь я возился дольше всего в моём проекте. Правильные версии выдирались прямо из сообщений об ошибках компиляции 😉 Т.е. компилятор ругался, что не находятся такие-то нужные сборки и я подставлял правильные значения. И именно здесь я несколько раз порывался бросить всё, т.к. гуглятся подобные ошибки очень плохо.

В результате хитрых манипуляций с csproj файлом получается такая ерунда в Solution Explorer:
Windows Mobile and Windows - Warnings
Это нормально, т.к. Visual Studio не совсем пригодна к таким извращениям (хотя и позволяет их в итоге).

#if #endif

Когда сборки подключаются правильные, мы имеем возможность для каждой платформы использовать тот максимум, который каждая из платформ поддерживает. Напомню, однако, что автоматическая кодогенерация дизайнера форм нам тут всё портит. Поэтому необходимо, по возможности, сначала всё надизайнить, а потом уже править только руками — ведь при перегенерации *.Designer.cs, студия не сохраняет наши правки и добавления #if endif участков.

Немного хитрый момент. Мой проект поддерживает как QVGA, так и VGA разрешение, однако, в Designer.cs у форм свойство ClientSize всегда соответствует QVGA разрешению. На десктопе же иметь окно размером 240х268 как-то неправильно, особенно, когда есть VGA-скин. Поэтому в конструкторе после InitializeComponent() я помещаю участок условной компиляции:

Size vertSize = new Size(480, 560);
Size horisSize = new Size(640, 480);
[…]
InitializeComponent();
#if Desktop
this.ClientSize = vertSize;
this.FormBorderStyle = FormBorderStyle.Fixed3D;
this.MaximizeBox = false;
this.MouseWheel += new MouseEventHandler(MainController_MouseWheel);
#endif

Как видно, у меня объявлено две переменные типа Size. Зачем это нужно? Просто-напросто, у меня по F9 происходит переключение ClientSize, для эмуляции смены ориентации экрана. Полезно, когда необходимо протестировать OnResize. Да и в конце концов, есть же нетбуки с 800х480, для них ландшафтная ориентация — единственно возможная, чтобы всё поместилось на экране 🙂

Также видно, что MouseWheel тоже обрабатывается только на десктопе.

System.Diagnostics.Conditional

Есть удобный способ указывать, для какого таргета собирать некоторый метод:

[Conditional("Desktop")]
public void SomeDesktopMethod()
{
}

В данном способе хорошо то, что вызовы данного метода могут существовать в коде, но при наличии данного атрибута, вызовы будут просто проигнорированы на других таргетах! Альтернатива с использованием #if #endif предполагает, что везде, где нужен вызов, необходимо проставить проверку, чтобы компилировать или не компилировать вызов на нужной платформе.

Отладка на десктопе

Существует два способа отладки. Первый (неудобный) заключается в том, мы идём в bin\Desktop\, запускаем exe-файл и потом в студии говорим Debug — Attatch to process. Этот способ сначала кажется единственно возможным. Но! Есть мега-хак, неофициальный и неподдерживаемый способ (который, тем не менее, работает как в VS2005, так и в VS2008). Способ следующий:

  • В студии открыть Tools/Options, далее в дереве выбрать Device Tools/Devices.
  • В выпадающем меню выбрать платформу, для которой необходимо организовать отладку на десктопе. Это будет необходимо повторить для всех платформ, где необходимо.
  • Далее нужно выбрать любой из эмуляторов и нажать [Save As…]. Удобно назвать копию “My Computer”.
  • Теперь надо закрыть студию и открыть %USERPROFILE%\Local Settings\Application Data\Microsoft\CoreCon\1.0\conman_ds_platform.xsl файл в текстовом редакторе.
  • В файле необходимо найти элемент, соответствующий свежесозданному “дивайсу”
  • Далее добавляем следующую строку — true сразу после тега .
  • Сохраняем conman_ds_platform.xsl и перезапускаем студию

Ну вот, теперь нам доступен отладчик и все вкусности десктопной отладки.

Заключение

Чтож, в статье перечислены основные подводные камни, с которыми я столкнулся в процессе сборки своего проекта под Windows. Далее всё было делом техники — ловил исключения и разбирался в их причине. Среди них были не найденные пути, которые, очевидно, на десктопе отличаются и т.д., но это всё уже было ничто, по сравнению с начальными проблемами.

PS. Почти всё, что описано выше, я выстрадал в результате долгих поисков, и вот, в самом конце, когда я искал способ отладки на десктопе, я натолкнулся на шикарную статью Дениела Моса о кросс-платформенной компиляции для Compact Framework 🙂 Моя статья ни в коем случае не является переводом, однако, не могу не дать на неё ссылку.

Оригинал статьи на Хабре.