DeepEdit!

Программирование баз данных на Oracle, техническая документация, литература, статьи и публикации

  • Увеличить размер шрифта
  • Размер шрифта по умолчанию
  • Уменьшить размер шрифта

Мультиплатформенность: Windows CE

Йост ван дер Слюйс (Joost van der Sluis)


USB-флэш-накопитель Lazarus уже подготовлен для использования с этим проектом. Если вы хотите использовать вашу собственную версию Lazarus, вы должны подготовить её и провести установку самостоятельно.

С помощью Lazarus можно создавать программы, которые могут быть скомпилированы для различных платформ. Одной из них является Windows Mobile, также известная как PocketPC или Windows CE. В этой статье рассказывается, как можно написать простое приложение для Windows Mobile, использующее GPS и встраиваемую базу данных SQLite. Я также расскажу, как можно отлаживать приложения и тестировать их с помощью эмулятора Windows Mobile от Microsoft.

Мультиплатформенность
Основное преимущество Lazarus - это поддержка разных платформ. Free Pascal, компилятор которого используется в Lazarus, может делать исполняемые файлы для нескольких платформ. В отличие от. Net, Free Pascal не делает чего-либо наподобие промежуточного исполняемого файла, который должен запускаться на фреймворке. Но каковы именно различия между платформами? Для Lazarus важны три аспекта: процессор, операционная система и используемый набор виджетов. Как это связано с мобильными телефонами, использующими Windows Mobile?
Процессор:
В мобильных телефонах могут использоваться различные типы процессоров. В большинстве аппаратов используют процессоры ARM, но есть ещё много разных видов процессоров. Процессоры ARM также могут использоваться с различными настройками, что может быть важно. Но, к счастью для телефонов на Windows Mobile всегда используется одно семейство ARM-процессоров с одними и теми же (основными) настройками.
Операционная система:
Lazarus называет Windows Mobile "WinCE" - это название старых версий этой операционной системы. Поддерживаются как минимум версии 5 и 6.
Набор виджетов (виджетсет)
"Виджетсет" представляет собой набор графических элементов управления (контролов), используемых для построения программ.
В Windows большинство программ по умолчанию используют набор виджетов Windows, но можно также строить программы и с использованием, например, виджетсета QT. QT и GTK являются самыми популярными наборами виджетов в Linux, а для OS/X есть Carbon и Cocoa.
В нашем случае мы хотим использовать Windows Mobile, её набор виджетов по умолчанию называется "WinCE". 

(Заметим, чтоо в этом случае название виджетсета соответствует старому названию операционной системы. Мы должны чётко представлять, где мы говорим о виджетсете, а где - об ОС). 

В связи с тем, что почти невозможно написать программу на самом мобильном телефоне, мы будем использовать кросс-компиляцию. Это означает, что для создания исполняемых файлов Windows CE мы
используем компьютер с ОС Windows. Для этого нам понадобятся "кросс­компилятор" и несколько дополнительных утилит.
На флэш-накопителе Lazarus от BlaisePascalMagazine всё это уже предустановлено. Если вы используете вашу собственную инсталляцию Lazarus, вам необходимо загрузить и установить кросс-компилятор для ARM/WinCE. (Lazarus-0.9.28.2-fpc-2.2.4-cross-arm-wince-win32.exe)
Начало работы
Теперь мы можем начать строить программу "Hello World" для Windows Mobile. Сначала создадим PC-версию, затем - версию для телефона. Запустите Lazarus и создайте новый проект. 
Сохраните программу, затем скомпилируйте и запустите её, чтобы протестировать на ПК. Если всё работает, мы можем настроить Lazarus для создания приложения WinCE.
В меню "Project" выберите "Project options ..." затем "Compiler Options". В этом экране мы выбираем, какой виджетсет использовать; здесь он называется "LCL Widget Type". Обратите внимание, что версии Lazarus, более поздние, чем версия на USB-флешке, имеют выпадающий список, в котором можно выбрать LCL Widget Type. Выберите "WinCE" и выделите в дереве узел "Code" ("Code Generation" в поздних версиях Lazarus).
Установите "Target OS" в WinCE и процессор 

('Target CPU Family") 

в ARM.
Нажмите OK для сохранения изменений, а затем перекомпилируйте
программу. Если всё прошло успешно, теперь у вас есть приложение "Hello World" для WinCE. Вы можете попробовать его запустить, но вам это не удастся. Программа, скомпилированная для процессора ARM, не будет работать на Intel Pentium. Для проверки программы вы должны
скопировать её в Windows Mobile-телефон и запустить на нём.

Эмулятор Windows Mobile
Конечно, весьма неудобно копировать приложение на телефон каждый раз, когда нужно проверить скомпилированные изменения в программе. Для быстрой проверки лучше используйте Windows Mobile Emulator. Эта программа от Microsoft эмулирует мобильный телефон с процессором ARM, на котором можно запускать несколько образов с несколькими операционными системами. Этот эмулятор и образы можно загрузить с сайта Microsoft. Найдите "Windows Mobile Emulator Images" и выберите версию "Professional" Windows Mobile, иначе не будет поддержки сенсорного экрана.


После установки в меню "Пуск" появится новый пункт "Windows Mobile 6 SDK" с подпунктом "Standalone Emulator Images", содержащим список образов различных версий Windows Mobile. Выберите один из них и запустите. Вы увидите телефон с запущенной Windows.
В меню File > Configure можно установить "общедоступный каталог" (shared map). Установите его для каталога, в котором вы сохранили проект Lazarus. Эта "Общая папка" теперь доступна на симулируемом телефоне как дополнительная карта памяти. На телефоне выберите "Программы" в
меню "Пуск" и запустите Проводник. Теперь выберите "Карта памяти" в верхнем левом углу. Вы видите все файлы проекта и исполняемый файл нашей программы Hello world. Нажмите на пиктограмму программы, и ваш телефон скажет "hello".

Удалённая отладка
Итак, теперь мы умеем вносить изменения в программу, компилировать её и показывать результат в эмуляторе. Но сейчас мы хотим ещё и отлаживать приложения. Внутри себя Lazarus использует отладчик "gdb". Чтобы отлаживать приложения WinCE, необходима специальная версия gdb, которую можно загрузить с веб-сайта Free Pascal.
(ftp://ftp.freepascal.org/fpc/contrib/cross/)
Скачайте архив gdb-6.4-win32-arm-wince.zip и распакуйте его файлы в новый каталог. Теперь нужно настроить Lazarus, чтобы он использовал эту версию gdb для отладки приложений. Это делается в настройках IDE, (Environment>Options) на вкладке "Debugger". Установите в Debugger path путь с именем файла (gdb.exe) той версии, которую вы только что извлекли.
GPS
До сих пор мы были заняты только настройкой всякой ерунды. Теперь начнём писать приложения. Мы хотим создать приложение, которое определяет местоположение телефона с помощью GPS и сохраняет эту информацию в локальной базе данных. Чтение GPS может осуществляться через прямое подключение к COM-порту, на котором "сидит" GPS, но в Windows CE есть также библиотека (gpsapi.dll), которая может использоваться для получения данных от GPS. (Эта библиотека включена в WinCE, начиная с версии 5.) Это "GPS Intermediate Driver", который мы используем в этой статье. Сначала мы должны сделать структуры и функции этой DLL доступными для нашей программы. Добавьте в код приложения следующее определение:

Для удалённой отладки gdb использует ActiveSync (в Windows XP) или "Центр устройств Windows Mobile" (в Windows Vista или Windows 7). Если у вас нет такого инструмента, его следует установить. Если после установки что-то не работает, перезагрузите компьютер. После перезагрузки перезапустите образ Windows Mobile. Теперь вам нужен "Диспетчер эмулятора устройства" (Device Emulator Manager), который можно найти в секции "Windows Mobile 6 SDK\Tools" меню "Пуск". Когда Device Emulator Manager запустится, Вы увидите GUID (случайную строку), обозначающую мобильный телефон, работающий в эмуляторе. Щёлкните правой кнопкой мыши на GUID и выберите "cradle". Это вызовет "подключение телефона к компьютеру".
Теперь запустите ActiveSync или "Центр устройств Windows Mobile" и убедитесь, что он подключается к эмулируемому мобильному телефону. (Если соединение не произошло, выберите "DMA" в настройках соединения Windows Mobile Device Center и перезапустите Device Center.)

Рисунок 5

Если связь между ActiveSync/Центром устройств и эмулируемым телефоном имеется, мы можем начать отладку. Вернитесь в Lazarus и установите точку останова на строку, в которой открывается окно сообщения.
Запустите программу, используя удалённый отладчик (F9). Если удалённый отладчик не выбран, возникнет ошибка, что приложение не подходит для Windows.
Но теперь приложение запускается на телефоне. Хотя вам нужно чуть потерпеть. Необходимо немного времени. Когда программа запустится, нажмите на кнопку, и Lazarus приостановит программу на точке останова. По нажатию F9 программа продолжится, ведя себя так же, как обычно при отладке приложений.
Важно знать, что происходит при удалённой отладке приложений. На телефоне создаётся каталог с названием "\gdb". Затем программа, которая должна быть запущена на телефоне, копируется в этот каталог и запускается. После этого отладчик подключается к запущенному приложению. Заметим, однако, что, если файл с таким именем уже существует на телефоне, программа не копируется. Это означает, что если вы измените программу, перекомпилируете её и запустите снова, на телефоне всё ещё будет старая версия приложения. Поэтому перед отладкой новой версии следует удалить приложение из каталога "\gdb\". Одна из причин низкой скорости отладки в том, что копирование файла в память телефона занимает много времени. Можно ускорить этот процесс, исключив отладочную информацию из исполняемого файла при линковке приложения и разместив её в отдельном файле. Это приводит к уменьшению размера исполняемого файла, поэтому на его копирование уходит меньше времени. Вы можете найти опцию размещения отладочной информации в отдельном файле в Compiler Options, на вкладке Link. (Use
external gdb debug symbols file (-Xg)).
const
gps_version_1        = 1;
gps_max_satellites = 12; gps_max_prefix_name = 16; gps_max_friendly_name = 64;
type
Tgps  fix quality      =   (gps  fix quality unknown, gps fix quality gps, gps fix quality dgps );
Tgps fix selection =  ( gps fix selection unknown, gps fix selection auto, gps fix selection manual );
Tgps  fix type        =   ( gps  fix unknown,
gps_fix_2Dgps_fix_3D);
TGPS_Position = record dwVersion:  DWord; dwSize:  DWord;
dwValidFields:  DWord;
dwFlags :  DWord;
stUTCTime:  Windows.SYSTEMTIME;
dblLatitude:  doubledblLongitude:  doubleflSpeed:  cfloat; flHeading:  cfloatdblMagneticVariation:  double;
flAltitudeWRTSeaLevel cfloat; flAltitudeWRTEllipsoid: cfloat;
FixQuality:   Tgps_fix_qualityFixType:  Tgps_fix_type; SelectionType:  Tgps_fix_type; flPositionDilutionOfPrecision:  cfloat; flHorizontalDilutionOfPrecision:  cfloat; flVerticalDilutionOfPrecision:  cfloat;
dwSatelliteCount: DWORD;
rgdwSatellitesUsedPRNs:
array[0..gps_max_satellites - 1]  of cdouble
dwSatellitesInView: DWORD;
rgdwSatellitesInViewPRNs:
array[0..gps_max_satellites - 1]  of cdoublergdwSatellitesInViewElevation:
array[0..gps_max_satellites - 1]  of cdoublergdwSatellitesInViewAzimuth:
array[0..gps_max_satellites - 1]  of cdoublergdwSatellitesInViewSignalToNoiseRatio:
array[0..gps_max_satellites-1]      of cdoubleFillup:  array[0..287]  of byte; end;
TGPS_Device = record dwVersion: DWORD; dwSize: DWORD; dwServiceState: DWORD; dwDeviceState: DWORD;
ftLastDataReceived    Windows.FILETIME;
szGPSDriverPrefix:  array[0..gps_max_prefix_name - 1]
of WChar;
szGPSMultiplexPrefix:  array[0..gps_max_prefix_name - 1]
of WChar;
szGPSFriendlyName:  array[0.. gps_max_friendly_name - 1]
of WChar; Fillup: array[0..114] of byte; end;
Константы содержат некоторые постоянные значения. TGPS_Position - это запись, в которой хранится местоположение. TGPS_Device содержит информацию о GPS-устройстве. Массив Fillup в TGPS_Position и TGPS_Device обходит ошибку в нескольких версиях Windows CE. Опишем это позже. Как видите, используются типы FileTime и SystemTime. Эти типы являются специфическими для Windows, поэтому Вы должны добавить модуль Windows в секцию uses. Это приведёт к тому, что приложение не будет компилироваться для ОС не-Windows. Впрочем, для нашего Windows-приложения это не проблема. Далее следует добавить модуль ctypes.
Данный модуль добавляет несколько типов, используемых в языке C, на котором был написан API GPS. GPSAPI.DLL имеет четыре функции для взаимодействия с GPS. Чтобы мы могли использовать эти функции в Pascal-программе, они должны быть определены первыми:

{$IFDEF WINCE}
function GPSOpenDevice( hNewLocationData,
hDeviceStateChange:  PtrInt;  szDeviceName :  PWideChar; dwFlage:  DWord):  PtrInt;  cdecl; external  'gpsapi.dll' Name  'GPSOpenDevice';
function GPSCloseDevice( hGPSDevice: PtrInt): DWord;
cdecl; external  'gpsapi.dll'  Name  'GPSCloseDevice';
function GPSGetPosition( hGPSDevice: PtrInt; var pGPSPosition: TGPS_Position;
dwMaximumAge,  dwFlags:  DWord):  DWord;  cdecl; external  'gpsapi.dll'  Name  'GPSGetPosition';
function GPSGetDeviceState(var pGPSDevice: TGPS_Device): DWord;  cdecl; external  'gpsapi.dll' Name 'GPSGetDeviceState';

{$ENDIF WINCE}

Определения включены в блоки $IFDEF, чтобы указать компилятору, что этот код должен компилироваться только для WinCE. Такие определения используются в языке Free Pascal при написании кода, различного для разных операционных систем. Существуют разные определения для всех операционных систем, процессоров и виджетсетов. Здесь мы используем определение, чтобы убедиться, что код по-прежнему компилируется на системе, на которой GPSAPI.DLL не доступна. Таким образом мы можем использовать эту программу и на обычном РС, хотя в этом случае GPS работать не будет.
Теперь мы хотим видеть GPS-координаты вместо "Hello World". Добавим private-функцию ConnectGPS:

function TForm1. ConnectGPS:  Boolean; var
res:     DWORD; begin

{$IFDEF WINCE}

result        := false;
fgpshandle       := GPSOpenDevice(0,  0,  nil,  0); if fgpshandle = 0 then begin
MessageDlg('Fout',   'Activating the GPS failed.',
mtError,   [mbOK],  0); exit; end;
result  := true;

{$ENDIF WINCE} 

end;
GPSOpenDevice устанавливает соединение с GPS и при необходимости включает GPS. К форме должна быть добавлена private-переменная fgpshandle типа PtrInt. Этот обработчик используется для считывания данных с GPS и его закрытия. Сообщение об ошибке говорит само за себя.
Теперь мы можем заменить код, показывающий "Hello World", чем-то более полезным:

procedure TForm1. Button1Click( Sender:  TObject); var
pGPSPosition: TGPS_Position; res:     DWORD; begin

{$IFDEF WINCE}

If  (fgpshandle<>0)  or ConnectGPS then begin
FillByte( pGPSPosition, sizeof( pGPSPosition), 0); pGPSPosition.dwVersion  := gps_version_1pGPSPosition.dwSize:= 376;  

// 344

res  := GPSGetPosition(fgpshandle,pGPSPosition,10000,0);
if res <> ERROR_SUCCESS then
begin
MessageDlg('Fout', Format('Reading the GPS failed.
Foutcode %d',[res]),
mtError,
mbOK], 0);
exit; end else
MessageDlg('Success',  Format('Longitude:  %g, Latitude:  %g.
Satelites: %d:%d.',
pGPSPosition. dblLongitude, pGPSPosition. dblLatitude, pGPSPosition. dwSatelliteCount, pGPSPosition. dwSatellitesInView]),
mtError,
mbOK], 0);
end;

{$ENDIF WINCE} 

end;

Вышеприведённый код сначала проверяет, доступен ли fgpshandle, и если нет, пытается создать соединение с GPS. При успехе этой операции инициализируется запись pGPSPosition. Она полностью очищается, а затем устанавливаются номер версии и размер записи. Как видите, размер записи задаётся явно. В принципе, это неправильно; по идее вместо 376 должно быть "SizeOf (pGPSPosition). Но проблема в том, что Windows CE 5 и 6 используют различные размеры pGPSPosition. Идея заключалась в том, что WinCE 6 будет обратно совместима с размером WinCE 5, но в некоторых версиях WinCE есть ошибка, нарушающая эту совместимость. Именно поэтому этот размер здесь является константой. Если данный размер неверен, программа выдаст ошибку с кодом 87. Если это произойдет, замените '376 'на '344' и попробуйте еще раз. Позже мы обсудим лучшее решение.
После инициализации записи pGPSPosition вызывается метод GPSPosition с четырьмя параметрами, сначала - fgpshandle, затем pGPSPosition, и далее -максимальный возраст ответа в милисекундах. Дело в том, что GPS передает информацию на телефон непрерывно. Может быть и так, что координаты были отправлены на телефон секунду назад. Если этот параметр возраста больше, чем 1000 (1 секунда), то вызов немедленно вернёт значение секундной давности. Четвёртый параметр всегда равен нулю.
После успешного вызова GPSGetPosition показывается окно сообщения (MessageBox) с GPS-координатами текущего местоположения. Далее вы можете видеть, сколько спутников используются для получения текущего местоположения (чем больше спутников, тем точнее результат), и общее число спутников, которое "видит" GPS.
Теперь мы можем проверить программу. Скомпилируйте приложение, запустите в эмуляторе и нажмите кнопку. Если вы получили сообщение об ошибке с ErrorCode 87, измените размер записи pGPSPosition. Если всё прошло нормально, вы увидите, что вы находитесь на экваторе, точно ниже Гринвич (0,0) и 0 найденных спутников. Не волнуйтесь, это вполне нормально, так как в вашем ПК или эмуляторе нет GPS- устройства. Но если это работает, скопируйте приложение на настоящий мобильный телефон и попробуйте на нём. Опять же вам скажут, что вы находитесь в позиции (0,0), но ещё пока нет никаких причин для паники. Если GPS был только что включён, нужно некоторое время для определения текущего местоположения. Если всё в порядке, второе число указывает количество спутников больше нуля. Нажмите на окно сообщения и оно исчезнет; откройте его ещё несколько раз. Вы увидите, что количество спутников увеличивается, и, наконец, он покажет также и местоположение. 

(Прогулка вне здания также поможет процессу.)

Чтобы тестировать GPS-приложения на эмуляторе, Microsoft разработала утилиту под названием "FakeGPS". Она является частью Windows Mobile SDK, но, чтобы установить этот SDK у Вас должен быть установлен Visual Studio. Однако можно также открыть Windows Mobile SDK в программе наподобие "7zip" и извлечь файл fakegps.cab. Скопируйте этот файл в эмулируемый телефон - это делается помещением его в один каталог с приложением, которое мы разрабатываем. В конце концов мы сделали этот путь видимым в эмуляторе как "карта памяти". Нажмите на "fakegps.cab" на телефоне, чтобы установить его. Затем найдите папку "Программы" на телефоне и запустите утилиту "FakeGPS". Включите FakeGPS, теперь Вы можете протестировать программу Lazarus на эмуляторе. Вы увидите, что он вернет выдуманные координаты; для проверки этого вполне достаточно.
Теперь - настоящее приложение
Теперь, когда мы научились считывать GPS-координаты, напишем настоящую программу. Делая это, мы должны учитывать, что мы разрабатываем ПО для мобильных телефонов с малым разрешением экрана, отличающимся на разных моделях аппаратов. При запуске форма всегда должна быть развёрнутой. Итак, установим свойство Form.WindowState в значение wsMaximized. Поместите на форму два TLabel с именами "lMessage" и "lMessagel. Для них обоих установите Align в Top и Alignment в taCenter. Установить стиль шрифта fsBold и дайте им подходящие заголовки, например, "Lazarus WinCE Demonstration" и "GPS demo". Установите BorderSpacingAround = 5. Также хорошо бы увеличить размер шрифта по умолчанию. Установите свойство формы font.size = l0, после чего этот размер будет установлен всем компонентам формы. (за 

исключением компонентов, для которых размер шрифта был задан отдельно).

Также поместим на форму две кнопки и назовём их "bStop" и "bStart"; дадим им также соответствующие подписи. Разместите их в нижнем левом углу формы, как на рисунке 6, и установите akBottom и akLeft свойства Anchor в true, а остальные - в false. Теперь перетащите границу формы для изменения её размера и убедитесь, что всё
отмасштабировалось корректно вместе с формой. Это важно, потому что вполне возможно, что при запуске программы на телефоне вы не увидите ничего, так как все элементы управления разместились за пределами экрана. Наконец, поместим на форму TTimer. Чтобы проверить нашу работу, запустим программу на телефоне или в эмуляторе.
function TForm1 GetGPSPosition(var GPSPosition:
TGPS_Position): dword; var res :    DWORD; dtime: TDateTime; ttime: Windows systemtime;
begin

{$IFDEF WINCE}

FillByte( GPSPosition, sizeof( GPSPosition), 0);
GPSPosition.dwVersion  := gps_version_1; if fgpsposition_size    = 0 then begin
GPSPosition.dwSize  := 376; res   := GPSGetPosition
(fgpshandle,  GPSPosition,  500000, 0); if res=ERROR_INVALID_PARAMETER then begin
GPSPosition.dwSize:= 344; res   := GPSGetPosition
fgpshandle, GPSPosition, 500000, 0);
end;
end else begin
GPSPosition.dwSize:=fgpsposition_sizeres   := GPSGetPosition
fgpshandle, GPSPosition, 500000, 0);
end;
if res ERROR_SUCCESS then begin
if ( GPSPosition. dwSatelliteCount > 0)
then
begin
lMessage.Caption  := Format ('Last position:(%d)',
GPSPosition. dwSatelliteCount]);
lMessage1.Caption:= Format
('%g   %g', [ GPSPosition. dblLatitude, GPSPosition. dblLongitude]); end
else lMessage.Caption  := Format
('Wait for signal.  %D satellites.',
GPSPosition. dwSatellitesInView]);
end
else lMessage.Caption  := Format
('Error while reading GPS, error code %D.',[res]);
result  := res; 

{$ENDIF}

end;
Этот код считывает и отображает GPS-координаты на экране. Если координаты ещё недоступны, будет показано предупреждение об отсутствии сигнала. Новшество здесь в том, что программа пытается установить соединение с dwSize: = 376 и, если это не получается, тогда с
dwSize: = 344. Затем нужный размер сохраняется и может быть использован в дальнейшем. Обратите внимание, что для этой работы
важно, чтобы размер фактической записи был как минимум не ниже, чем
значение, приведённое здесь.
Как говорилось ранее, TGPS_Position в Windows Mobile версии 5 имеет размер, который слишком мал для Windows Mobile 6. Но так как версия 6
во всех случаях не может обрабатывать формат версии 5, размер записи
увеличивается путём добавления неиспользуемого байтового массива
(TGPS_Position.Fillup). Таким образом, он будет работать на всех версиях. Теперь мы должны написать обработчики событий для кнопок и таймера:




Теперь добавим новую private-функцию для получения GPS-местоположения. Вот её код:

procedure TForm1. bStartClick( Sender: TObject); var
res:  DWord;
pGPS_Position    TGPS_Position; begin
if not ConnectGPS then Exit;
res := GetGPSPosition( pGPS_Position, False);
if res ERROR_SUCCESS then
begin
bStart. Enabled:=false; bStop. Enabled:=True; Timer1 Enabled:=true end;
end;
procedure TForm1. bStopClick( Sender: TObject); begin
Timer1. Enabled:=false; 

{$IFDEF WINCE}

GPSCloseDevice( fgpshandle); 

{$ENDIF WINCE} 

bStart. Enabled:=true; bStop. Enabled:=false; end;
procedure TForm1. Timer1Timer( Sender: TObject); begin
res := GetGPSPosition( pGPSPosition, true); end;

Теперь по нажатию кнопки "Пуск" программа попытается подключиться к GPS, и если это удастся, таймер активируется.
Таймер обеспечивает по истечении интервала (Timer1.Interval) проверку наличия новой GPS-информации. Эта информация отобразится на экране. Кнопкой Stop таймер деактивируется, после чего соединение с GPS разрывается.

Сохранение прогулки в парке
Допустим, мы хотим погулять в парке и сохранять наши координаты каждые 5 секунд. Для этого нужно использовать базу данных, но не такую,
для которой требуется устанавливать полный сервер баз данных. И она должна работать на Windows CE. Отличным решением будет SQLite
(www.sqlite.org).
Если вы хотите работать с SQLite, Вы должны разместить библиотеку
sqlite3.<ffl в одном каталоге с ™_        либо если он будет
использоваться всей системой, в c:\windows\system32. Попробуем вначале сделать эту работу на PC.
Здесь тоже используется 

{fIFDEF WINCE}. 

Сначала скачайте sqlite3.dll и поместите его в каталог System32.
Нам также необходим доступ к базе данных из Lazarus, поэтому
недостаточно просто поместить dll в каталог проекта. (В 

принципе возможно. Но в этом случае DLL также должна быть скопирована в один каталог с испоолняемым файлоом Lazarus.)

Теперь разместите на форме компоненты TSQLite3Connection, TSQLTrasaction и TSQLQuery с вкладки SQLdb. Свяжите TSQLTransaction.Connection и
TSQLQuery.Connection с TSQLite3Connection. Установите TSQL3Connection.Transaction в TSQLTransaction.
Поместите компоненты TDataSource с вкладки "Data Access" и TDBGrid с
вкладки "Data Controls".
Свяжите TDatasource.Dataset с TSQLQuery и соедините DBGrid и TDataSource через свойство DBGrid.DataSource.
Наконец задайте компоненту TSQLQuery следующий запрос (SQL):  'select * from coordinates;'.
Теперь задайте DatabaseName для TSQLite3Connection. DatabaseName - это
всего лишь имя файла, в котором хранятся данные. В моем случае это 'h:\src\pgg-wince\gpsdata.sdb'. Вы можете проверить корректность установки и настройки SQLite, установив свойство Connected
в true. Так как не требуется дополнительных инструментов для создания
таблиц, мы создаем таблицу.
Добавим private-метод TForm1 InitialiseDB (код чуть ниже). Этот код сначала проверяет, активен ли TSQLQuery. Если нет, производится подключение к БД. Затем он проверяет, существует ли таблица.

procedure TForm1. InitialiseDB; var sl:  TStringList;  i:  integer; begin
if SQLQuery1. Active then Exit;
SQLite3Connection1.Open; sl  := TStringList. Create; try
SQLite3Connection1. GetTableNames( sl); if not sl. Find('coordinates',  i)  then begin
SQLite3Connection1. ExecuteDirect ('create table coordinates(LocalTime datetime, GPSTime datetime,  longitude real,  latitude
real);');
SQLTransaction1. CommitRetaining; end; finally
sl. Free; end;
SQLQuery1 Open; end;
Для сохранения таблицы подтвердим транзакцию. Теперь можно открыть запрос. Добавьте вызов этой функции в событие OnCreate формы, чтобы обеспечить открытие таблицы при запуске программы.
Для проверки и создания этой простой базы данных и таблицы
скомпилируем приложение на PC. Зайдите в Compiler > Options и установите widgettype в Win32/Win64.
Код, который должен быть создан, должен быть для процессора i386, и вы должны также выбрать Operating System Win32. Запустите программу в отладчике... и вы увидите, что она не работает.
Это потому, что отладчик настроен на отладку приложений для
ARM-процессоров, удаленно, на мобильном телефоне. Зайдите в настройки (environment'  -> IDE Options -> debugger) и
установите Debugger path к стандартному отладчику Win32 

(/a%ar«s\mingii\bin\gdk exe).

Если такой файл есть, можно установить свойство Active компонента TSQLQuery в true. Тогда поля, добавленные в таблицу, станут видимыми в
сетке. Для масштабирования сетки с размером формы на телефоне установите BorderSpacing.Around = 5  и BorderSpacing.Bottom = 40.
Установите ReadOnly в   а также options.dgEditing и
options.dgIndicator в false. Установите AutoFillColumns в true.
Это ещё не все. Чтобы корректного отображать столбцы на маленьком экране, свойства каждого столбца должны быть выставлены вручную. Дважды щелкните на сетке и нажмите три раза на кнопку "Add", чтобы добавить три столбца. Выберите первый столбец, установите
fieldname='LocalTime' и DisplayFormat='hh:mm:ss', чтобы отображалось только время, без даты.
Вы также можете дать столбцу подходящий заголовок. Настройте остальные два столбца
чтобы отображались "latitude" и "longitude", с DisplayFormat =   '#0.#######'.
Итак, мы настроили все компоненты и идём дальше. Теперь надо позаботиться о сохранении местоположений в базе данных.

function TForm1 GetGPSPosition(var GPSPosition:
TGPS_Position; StoreDB: boolean): dword; var
res :     DWORD; dtime: TDateTime;
ttime: Windows. systemtime; dist: double;
begin

{$IFDEF WINCE}


lMessage.Caption:=Format('Laatste positie:   (%d)',
GPSPosition. dwSatelliteCount]);
lMessage1.Caption:=Format('%g %g',
GPSPosition. dblLatitude, GPSPosition. dblLongitude]); if StoreDB then begin
SQLQuery1 First; SQLQuery1 insert;
SQLQuery1.FieldByName('localtime').AsDateTime   := now;
if GPSPosition. stUTCTime. Year<>0 then
begin
ttime   := GPSPosition.stUTCTimedtime:=
ComposeDateTime(EncodeDate
ttime. Year, ttime. Month, ttime. Day),
EncodeTime( ttime. Hour, ttime. Minute, ttime. Second, ttime. Millisecond)); SQLQuery1.FieldByName('gpstime').AsDateTime:= dtime; end;
SQLQuery1.FieldByName('latitude').AsFloat:= GPSPosition. dblLatitude;
SQLQuery1.FieldByName('longitude').AsFloat:=
GPSPosition. dblLongitude;
SQLQuery1 Post; end; end else
lMessage.Caption:=Format
('Wachten op verbinding.  %D satelieten.',
GPSPosition. dwSatellitesInView]);
Помимо нового параметра, другими новшествами в этом коде являются переменные dtime и ttime, а также часть кода, в которой новая запись добавляется в базу. В базе данных, помимо координат, сохраняется время, в которое эти координаты были измерены GPS-устройством.
Это время должно быть преобразовано в TDateTime. Если StoreDB = false, данные в БД не сохраняются, и если GPS-время некорректно, запись также не сохраняется.
Теперь нам нужно лишь добавить значение StoreDB в два места, в которых вызывается функция GetGPSPosition.
В обработчике событий кнопки Start это значение должно быть "false". В таймере StoreDB должен быть "true".
После этих изменений верните в настройках компилятора генерацию приложений Windows CE/ARM.
Затем нужно изменить TSQLite3Connection.DatabaseName, так как каталог, заданный в настоящее время, скорее всего отсутствует на мобильном телефоне.
Простейшим способом является установка имени БД без пути, например, 'gpsdata.sdb'.
Но разница с тем, что мы привыкли видеть на ПК с Windows, в том, что файл сохранится не в текущий каталог, а в каталог "My Device" ("Моё устройство").
Этот каталог является главным (корневым) каталогом устройства. Это происходит из-за того, что Windows CE не имеет чего-либо наподобие каталога по умолчанию.
Измените DatabaseName, скомпилируйте приложение и запустите его на эмуляторе или на телефоне.
Вы немедленно получите сообщение об ошибке, так как на телефоне пока ещё нет файла sqlite3.dll.
Но на самом деле здесь всё не так просто, как кажется.
Sqlite3.dll, который мы использовали ранее, построен для процессора Intel Pentium и для операционной системы Windows.
В связи с этим мы должны скачать версию sqlite3.dll для ARM/WinCE. Проще всего загрузить его с FTP FreePascal
(ftp://ftp.freepascal.org/fpc/contrib/    файл: arm-wince-sqlite322.zip).
Извлеките файл в каталог с вашей программой и запустите программу снова. Примечание: если программа работает в отладчике, его расположение - каталог '\gdb'.
Когда программа запущена, нажмите на кнопку "Start" и подождите, пока GPS получит подходящий сигнал. Сейчас можно видеть, каким образом текущее местоположение отображается в таблице и сохраняется в базе данных.
Однако при перезапуске приложения вы увидите, что таблица координат снова пуста.
Для сохранения данных добавим на форму кнопку "Save" и разместим её в нижнем правом углу. Установите Anchors.Right и Anchors.Bottom в true 

(остальные - в false). 

Добавьте в обработчик события OnClick следующий код:
Об авторе:
Йост ван дер Слюйс (Joost van der Sluis)
является членом команды разработчиков ядра Free Pascal. Он отвечает за DB-компоненты, большая часть которых написана им. Он является одним из основателей CNOC, компании, которая предоставляет коммерческую поддержку Free Pascal и Lazarus и организовавшей сайт www.lazarussupport.com .
CNOC пытается продвигать использование Lazarus в коммерческой среде и помогает переходу на Lazarus из Delphi.

procedure TForm1 bOpslaanClick Sender TObject); begin
SQLQuery1 ApplyUpdates (0); SQLTransaction1 CommitRetaining ; end ;
ApplyUpdates считывает все изменения в буфер обновления данных и записывает их в таблицу. CommitRetaining нужен для подтверждения этих
изменений.
Итак, мы закончили написание приложения для этой статьи. В него на самом деле можно добавить много интересных функций. Например, программа может измерять пройденное вами расстояние. Или что-то наподобие сервиса, записывающего, как часто и где Вы едете на машине.
Здесь рассказано лишь о базовых компонентах, а расширение программы -полностью в ваших руках.
Заключение
Мы выяснили, что разработка приложений для Windows Mobile - это не очень трудно. Большая часть работы - настройка всех необходимых инструментов. Кроме того, необходимо учитывать такие факторы, как использование правильной версии sqlite3.dll на вашем телефоне, и использование правильной версии отладчика. Если вы освоите эти моменты, для вас это будет "детской игрушкой".
 









jAntivirus