Delphi і Bluetooth. Частина 2 (исходники), Різне, Програмування, статті

В першій частині статті ми навчилися отримувати список локальних радіомодулів Bluetooth і пізнавати їх властивості. Тепер прийшов час отримати список пристроїв Bluetooth, які підключені до наших локальних радіомодуля.

Отримання списку пристроїв Bluetooth


Для отримання списку пристроїв Bluetooth нам знадобляться наступні функції (вони дуже схожі на функції, які використовуються для отримання списку локальних радіомодулів).

BluetoothFindFirstDevice 

Починає перерахування пристроїв Bluetooth.

Оголошення функції:


function BluetoothFindFirstDevice(
const pbtsp : BLUETOOTH_DEVICE_SEARCH_PARAMS;
var pbtdi : BLUETOOTH_DEVICE_INFO): HBLUETOOTH_DEVICE_FIND; stdcall; 

Параметри:

pbtsp – Покажчик на структуру BLUETOOTH_DEVICE_SEARCH_PARAMS. Член dwSize цієї структури повинен містити розмір структури (встановлюється за допомогою SizeOf (BLUETOOTH_DEVICE_SEARCH_PARAMS)). Член hRadio повинен містити описувач локального радіомодуля, отриманий викликом функції BluetoothFindFirstRadio.
pbtdi – структура BLUETOOTH_DEVICE_INFO в яку буде повернута інформації про пристрій Bluetooth.

Значення, що повертаються: у разі успішного виконання функція поверне коректний описувач в якості результату. У випадку помилки буде повернуто 0. Для отримання коду помилки використовуйте функцію GetLastError.

BluetoothFindNextDevice

Знаходить наступне пристрій Bluetooth.

Оголошення функції:


function BluetoothFindNextDevice(
hFind : HBLUETOOTH_RADIO_FIND;
var pbtdi : BLUETOOTH_DEVICE_INFO): BOOL; stdcall; 

Параметри:

hFind – Описувач, який повернула функція BluetoothFindFirstDevice.
pbtdi – Структура BLUETOOTH_DEVICE_INFO, в яку буде поміщена інформацію про пристрій.

Значення, що повертаються: поверне TRUE, якщо пристрій знайдено. Поверне FALSE в разі відсутності пристрою. phRadio містить некоректний описувач. Використовуйте GetLastError для отримання коду помилки.


BluetoothFindDeviceClose 


Закриває описувач перерахування пристроїв Bluetooth.

Оголошення функції:


function BluetoothFindDeviceClose(
hFind : HBLUETOOTH_DEVICE_FIND): BOOL; stdcall;

Параметри:

hFind – Описувач, який повернула функція BluetoothFindFirstDevice.

Значення, що повертаються: поверне TRUE якщо описувач успішно закрито. Поверне FALSE в разі помилки. Для отримання коду помилки використовуйте GetLastError.

BluetoothGetDeviceInfo 


Повертає інформацію про зазначений пристрій Bluetooth.

Оголошення функції:


function BluetoothGetDeviceInfo(
hRadio : THandle
var pbtdi : BLUETOOTH_DEVICE_INFO): DWORD; stdcall;

Параметри:

hRadio – описувач локального радіомодуля Bluetooth.
pbtdi – структура BLUETOOTH_DEVICE_INFO, в яку возвразается інформація про пристрій. dwSize має дорівнювати розміру структури. addreess повинен містити адресу пристрою, про який хочемо отримати інформацію.

Значення, що повертаються: поверне ERROR_SUCCESS якщо виконано успішно і інформація занесена в структуру pbtdi. Решта значення – код помилки.

Володіючи цими знаннями, можна написати процедуру отримання інформації про пристрої Bluetooth.

procedure GetDevices(_hRadio: THandle);
var
DeviceInfo: PBLUETOOTH_DEVICE_INFO;
DeviceSearchParams: BLUETOOTH_DEVICE_SEARCH_PARAMS;
DeviceFind: HBLUETOOTH_DEVICE_FIND;
begin
/ / Ініціалізація структури BLUETOOTH_DEVICE_SEARCH_PARAMS
with DeviceSearchParams do begin
dwSize := SizeOf(BLUETOOTH_DEVICE_SEARCH_PARAMS);
fReturnRemembered: = true; / / Повернути запомненние
hRadio := _hRadio
end;

/ / Ініціалізація структури BLUETOOTH_DEVICE_INFO
FillChar(DeviceInfo, SizeOf(PBLUETOOTH_DEVICE_INFO), 0);
DeviceInfo.dwSize := SizeOf(PBLUETOOTH_DEVICE_INFO);

/ / Починаємо пошук
DeviceFind := BluetoothFindFirstDevice(DeviceSearchParams, DeviceInfo);
if (DeviceFind <> 0) then begin
repeat
/ / Щось зробити з отриманими даними

/ / Ініціалізація структури BLUETOOTH_DEVICE_INFO
FillChar(DeviceInfo, SizeOf(PBLUETOOTH_DEVICE_INFO), 0);
DeviceInfo.dwSize := SizeOf(PBLUETOOTH_DEVICE_INFO);
/ / Знаходимо наступне пристрій
until (not BluetoothFindNextDevice(DeviceFind, DeviceInfo));

/ / Закриваємо пошук
BluetoothFindDeviceClose(DeviceFind);
end;
end; 

Нам залишилося навчитися отримувати список сервісів, що надаються віддаленою пристроєм і управляти локальними радіомодулями. Так само, необхідно розібратися, як же все-таки передаються дані між різними пристроями Bluetooth.

Ми створимо програму, яка допоможе нам узагальнити отриману інформацію і покаже, як використовувати нові функції, які тут будуть описані. Перш, ніж ми приступимо, давайте визначимося в термінах. Microsoft у своїй документації вводить два терміни: Radio і Device. Radio – це локальний радіомодуль Bluetooth (USB-брелок, інтегроване рішення, загалом те, що встановлено на вашому комп’ютері). Device – Це те пристрій Bluetooth з яким ви хочете обмінюватися інформацією. Будь то телефон, КПК, гарнітура або ще щось. Важливо розуміти, що якщо ми пишемо програму для PDA, то коли вона працює на PDA – його модуль Bluetooth буде Radio, а комп’ютер – Device. Якщо ж вона працює на комп’ютері, то комп’ютерний модуль – Radio, а PDA – Device.

Що ми знаємо


На жаль, документація Microsoft по Bluetooth API і роботі з Bluetooth настільки мізерна (у мене вийшло 50 сторінок в Word з оформленням), а прикладів вони взагалі не надають, що з неї дуже важко зрозуміти, як же все-таки працює ця технологія.

Коли я тільки починав вивчати цей предмет, я перерив весь Internet, але так нічого зрозумілого не знайшов.

Тому, тут мені хочеться дати найбільш повну і детальну інформацію про це питання, що б ви не зіткнулися з тією ж проблемою відсутності інформації.

І так, приступимо.

Створення проекту


Давайте створимо в Delphi новий проект і збережемо його під ім’ям BTWork, а модуль – під ім’ям Main. Головну і поки єдину форму, назвемо fmMain. Тема BTWork. Тепер нам знадобляться файл JwaBluetoothAPI.pas, JwaBtHDef.pas і JwaBthSdpDef.pas. Їх можна знайти в прикладах з попередніх частин або в бібліотеці BTClasses. Для того, щоб не тягнути з собою всі інші файли з JWA, давайте ці трохи виправимо. Знайдіть у них рядок uses JwaWindows і замініть JwaWindows на Windows. Далі видалити з них рядки

{$WEAKPACKAGEUNIT}
{$HPPEMIT “”}
{$HPPEMIT “#include “bluetoothapis.h””}
{$HPPEMIT “”}
{$I jediapilib.inc} 


І в файлі JwaBluetoothAPI видаліть все, що знаходиться між {$ IFDEF DYNAMIC_LINK} і {$ ELSE} разом з цими DEF. І в кінці цього файлі видаліть {$ ENDIF}.

Далі, в JwaBluetoothAPI.pas після implementation

uses
JwaWinDLLNames; Напишіть const
btapi = “irprops.cpl”; 

Хай вибачать нас хлопці, які цю бібліотеку писали!

Всі ці дії я робив для того, щоб зменшити архів прикладу. Та й не потрібно тягнути за собою багато зайвого. Хоча сама бібліотека вельми корисна. Один модуль JwaWindows чого вартий. Там дуже багато цікавого є. Ну да ладно – щось я відволікся.

Після того, як ми кастрували ці модулі, давайте додамо їх в наш проект. Готово?

У цьому додатку ми будемо отримувати список локальних радіомодулів, пристроїв, до них приєднаних, список сервісів, що надаються пристроями. Також ми повинні управляти радіомодулями і навчитися проходити авторизацію.

Приступаємо.

Оформлення головної форми
На головну форму помістимо компонент TPanel і встановіть наступні властивості:















Властивість Значення
Align alTop
Caption
Name Panel

Далі помістимо компонент TTreeView і встановіть властивості як в таблиці:

























Властивість Значення
Align alLeft
Cursor crHandPoint
HideSelection False
HotTrack True
Name TreeView
ReadOnly True

Правіше TTreeView помістимо TSplitter і встановимо такі його властивості:













Властивість Значення
Name Splitter
Width 5

І, нарешті, поміщаємо компонент TListView ще правіше TSplitter. Встановлюємо його властивості як в таблиці:








































Властивість Значення
Align alClient
ColumnClick False
Cursor crHandPoint
GridLines True
HideSelection False
HotTrack True
Name ListView
ReadOnly True
RowSelect True
ShowWorkAreas True
ViewStyle vsReport

На TPanel помістимо кнопку TButton.













Властивість Значення
Caption Refresh
Name btRefresh

Тепер ми готові писати програму.

Пишемо код


При старті нашої програми, бажано щоб відразу заповнювався TreeView. У ньому будуть показані модулі Bluetooth і пристрої, які до них підключені. Для цього в обробнику OnCreate форми fmMain напишемо такий код:

procedure TfmMain.FormCreate(Sender: TObject);
begin
btRefresh.Click;
end; 


А в обробнику OnClick кнопки btRefresh напишемо наступне:


procedure TfmMain.btRefreshClick(Sender: TObject);
var
RootNode: TTreeNode;
hFind: HBLUETOOTH_RADIO_FIND;
hDevFind: HBLUETOOTH_DEVICE_FIND;
FindParams: BLUETOOTH_FIND_RADIO_PARAMS;
SearchParams: BLUETOOTH_DEVICE_SEARCH_PARAMS;
SearchParamsSize: dword;
DevInfo: ^PBLUETOOTH_DEVICE_INFO;
DevInfoSize: dword;
hRadio: THandle;
RadioInfo: PBLUETOOTH_RADIO_INFO;
RadioInfoSize: dword;
RadioNode: TTreeNode;
Loop: integer;
DevNode: TTreeNode;
begin
with TreeView.Items do
begin
BeginUpdate;

/ / Очищаємо дерево
for Loop := 0 to Count – 1 do 
begin
if TreeView.Items[Loop].ImageIndex > 0 then
CloseHandle(TreeView.Items[Loop].ImageIndex);
if Assigned(TreeView.Items[Loop].Data) then
Dispose(TreeView.Items[Loop].Data);
end;
Clear;

/ / Коренева гілку в дереві
RootNode := Add(nil, “Bluetooth Radios”);
with RootNode do 
begin
Data := nil;
ImageIndex := -1;
end;

/ / Починаємо пошук локальних модулів Bluetooth
FindParams.dwSize := SizeOf(BLUETOOTH_FIND_RADIO_PARAMS);
hFind := BluetoothFindFirstRadio(@FindParams, hRadio);
if hFind <> 0 then begin
repeat
/ / Отримати інформацію про радіомодуля
New(RadioInfo);
RadioInfoSize := SizeOf(BLUETOOTH_RADIO_INFO);
FillChar(RadioInfo^, RadioInfoSize, 0);
RadioInfo^.dwSize := RadioInfoSize;
/ / Помилки не обробляємо!
BluetoothGetRadioInfo(hRadio, RadioInfo^);

/ / Додаємо радіо в дерево
RadioNode := AddChild(RootNode,
string(RadioInfo^.szName) + ” [” +
BTAdrToStr(RadioInfo^.address) + “]”);
with RadioNode do
begin
/ / Так як ми зберігаємо Handle, то не закриваємо його!
ImageIndex := hRadio; 
Data := RadioInfo;
end;

/ / Починаємо пошук пристроїв для знайденого радіомодуля.
SearchParamsSize := SizeOf(BLUETOOTH_DEVICE_SEARCH_PARAMS);
FillChar(SearchParams, SearchParamsSize, 0);
SearchParams.dwSize := SearchParamsSize;
SearchParams.fReturnRemembered := True;
SearchParams.hRadio := hRadio;

New(DevInfo);
DevInfoSize := SizeOf(BLUETOOTH_DEVICE_INFO);
FillChar(DevInfo^, DevInfoSize, 0);
DevInfo^.dwSize := DevInfoSize;

/ / Шукаємо перший
hDevFind := BluetoothFindFirstDevice(SearchParams, DevInfo^);
if hDevFind <> 0 then begin
repeat
/ / Додаємо в дерево
DevNode := AddChild(RadioNode,
string(DevInfo^.szName) + ” [” +
BTAdrToStr(DevInfo^.Address) + “]”);
with DevNode do 
begin
Data := DevInfo;
ImageIndex := -2;
end;

/ / Шукаємо наступне пристрій
New(DevInfo);
DevInfoSize := SizeOf(BLUETOOTH_DEVICE_INFO);
FillChar(DevInfo^, DevInfoSize, 0);
DevInfo^.dwSize := DevInfoSize;
until not BluetoothFindNextDevice(hDevFind, DevInfo^);

/ / Пошук пристроїв закінчено
BluetoothFindDeviceClose(hDevFind);
end;

/ / Знаходимо наступне радіо
until not BluetoothFindNextRadio(hFind, hRadio);

/ / Пошук радіомодулів закінчено
BluetoothFindRadioClose(hFind);
end;

EndUpdate;
end;

with TreeView do
begin
Selected := RootNode;
Items[0].Expand(True);
end;
end; 


В uses нашого модуля, який відноситься до головної формі, допишемо:


implementation / / Вже написано!
uses / / Дописати!
JwaBluetoothAPIs, Windows, SysUtils, Dialogs; 


Нижче додамо функцію:


/ / Перетворює адресу з внутрішнього формату (dword) в рядок,
/ / Прийняту для подання адрес пристроїв Bluetooth.
function BTAdrToStr(const Adr: BLUETOOTH_ADDRESS): string;
var
Loop: byte;
begin
Result := IntToHex(Adr.rgBytes[0], 2);
for Loop := 1 to 5 do
Result := IntToHex(Adr.rgBytes[Loop], 2) + ‘:’ + Result;
end; 

Тут хочу привести опис використовуваних структур, так як раніше я їх не описував:

BLUETOOTH_DEVICE_SEARCH_PARAMS

Оголошення:


BLUETOOTH_DEVICE_SEARCH_PARAMS = record
dwSize : DWORD;
fReturnAuthenticated : BOOL;
fReturnRemembered : BOOL;
fReturnUnknown : BOOL;
fReturnConnected : BOOL;
fIssueInquiry : BOOL;
cTimeoutMultiplier : UCHAR;
hRadio : THandle;
end; 

Члени:




























dwSize  Вхідний параметр. Повинен бути дорівнює розміру структури (dwSize: = SizeOf (BLUETOOTH_DEVICE _SEARCH_PARAMS))
fReturnAuthenticated  Вхідний параметр. Функція буде повертати пристрої, що пройшли авторизацію.
fReturnRemembered  Вхідний параметр. Функція буде повертати пристрою, вже запомненние раннє.
fReturnUnknown  Вхідний параметр. Функція буде повертати нові або невідомі пристрої.
fReturnConnected  Вхідний параметр. Функція буде повертати підключені пристрої.
fIssueInquiry  Вхідний параметр. Змушує функцію перевіряти пристрою.
cTimeoutMultiplier  Вхідний параметр. Тайм-аут для перевірки пристрою.
hRadio  Handle радіомодуля, для якого проводиться пошук пристроїв. Якщо 0, то перевіряються всі радіомодулі.

BLUETOOTH_DEVICE_INFO

Оголошення:


BLUETOOTH_DEVICE_INFO = record
dwSize : DWORD;
Address : BLUETOOTH_ADDRESS;
ulClassofDevice : ULONG;
fConnected : BOOL;
fRemembered : BOOL;
fAuthenticated : BOOL;
stLastSeen : SYSTEMTIME;
stLastUsed : SYSTEMTIME;
szName : array [0..BLUETOOTH_MAX_NAME_SIZE – 1] of WideChar;
end; 

Члени:































dwSize  Вхідний параметр. Повинен бути дорівнює розміру структури (dwSize: = SizeOf (BLUETOOTH_DEVICE_INFO))
Address  Адреса пристрою Bluetooth.
ulClassofDevice  Клас пристрою. Детальніше за класами дивіться в JwaBluetoothAPIs. Константи з префіксом COD_xxx.
fConnected  Якщо TRUE, то пристрій підключено / використовується
fRemembered Якщо TRUE, то пристрій раніше вже було знайдено (запомнено)
fAuthenticated  Якщо TRUE, то пристрій пройшло авторизацію (Авторизуватися)
stLastSeen  Дата і час останнього виявлення пристрою
stLastUsed  Дата і час останнього використання пристрою
szName  Назва пристрою (ім’я)

 BLUETOOTH_RADIO_INFO

Оголошення:


BLUETOOTH_RADIO_INFO = record
dwSize : DWORD;
address : BLUETOOTH_ADDRESS;
szName : array [0..BLUETOOTH_MAX_NAME_SIZE – 1] of WideChar;
ulClassofDevice : ULONG;
lmpSubversion : Word;
manufacturer : Word;
end; 

Члени:






















dwSize  Повинен бути дорівнює розміру структури (dwSize: = SizeOf (BLUETOOTH_RADIO_INFO))
Address  Адреса радіомодуля Bluetooth
szName  Ім’я радіомодуля
ulClassofDevice  Клас пристрою (див. вище)
lmpSubversion  Залежить від виробника
Manufacturer  Код виробника. Визначається константами BTH_MFG_Xxx. Більш повну інформацію про виробників можна отримати на сайті підтримки Bluetooth.

Далі напишемо ось такий обробник події OnChange для TreeView:


procedure TfmMain.TreeViewChange(Sender: TObject; Node: TTreeNode);
var
ASelected: TTreeNode;

procedure ShowRadios;
var
Info: PBLUETOOTH_RADIO_INFO;
CurNode: TTreeNode;
begin
/ / Будуємо стовпці
with ListView.Columns do 
begin
BeginUpdate;
with Add do Caption := “Address”;
with Add do Caption := “Name”;
with Add do Caption := “Class Of Device”;
with Add do Caption := “Manufacturer”;
with Add do Caption := “Subversion”;
with Add do Caption := “Connectable”;
with Add do Caption := “Discoverable”;
EndUpdate;
end;

/ / Заповнюємо список
with ListView.Items do 
begin
BeginUpdate;

CurNode := ASelected.GetFirstChild;

while Assigned(CurNode) do begin
Info := PBLUETOOTH_RADIO_INFO(CurNode.Data);

/ / Перечитати інформацію про радіомодуля
BluetoothGetRadioInfo(CurNode.ImageIndex, Info^);

with Add do 
begin
Data := Pointer(CurNode.ImageIndex);
Caption := BTAdrToStr(Info.address);
with SubItems do 
begin
Add(string(Info.szName));
Add(IntToStr(Info.ulClassofDevice));
Add(IntToStr(Info.manufacturer));
Add(IntToStr(Info.lmpSubversion));
// NEW FUNCTIONS!!!
Add(BoolToStr(BluetoothIsConnectable(CurNode.ImageIndex), True));
Add(BoolToStr(BluetoothIsDiscoverable(CurNode.ImageIndex), True));
end;
end;

CurNode := ASelected.GetNextChild(CurNode);
end;

EndUpdate;
end;
end;

procedure ShowDevices;
var
Info: ^PBLUETOOTH_DEVICE_INFO;
CurNode: TTreeNode;
begin
/ / Будуємо стовпці
with ListView.Columns do
begin
BeginUpdate;
with Add do Caption := “Address”;
with Add do Caption := “Name”;
with Add do Caption := “Class Of Device”;
with Add do Caption := “Connected”;
with Add do Caption := “Remembered”;
with Add do Caption := “Authenticated”;
with Add do Caption := “Last Seen”;
with Add do Caption := “Last Used”;
EndUpdate;
end;

/ / Заповнюємо список
with ListView.Items do 
begin
BeginUpdate;

CurNode := ASelected.GetFirstChild;

while Assigned(CurNode) do 
begin
Info := CurNode.Data;

/ / Перечитуємо інформацію про пристрій
/ / Так як передаємо покажчик, то вона автоматом
/ / Оновиться і в тому місці, де ми її зберігали
BluetoothGetDeviceInfo(ASelected.ImageIndex, Info^);

with Add do 
begin
Data := Info;
Caption := BTAdrToStr(Info^.Address);
with SubItems do 
begin
Add(string(Info^.szName));
Add(IntToStr(Info^.ulClassofDevice));
Add(BoolToStr(Info^.fConnected, True));
Add(BoolToStr(Info^.fRemembered, True));
Add(BoolToStr(Info^.fAuthenticated, True));
try / / stLastSeen може бути 0 і тоді тут помилка буде
Add(DateTimeToStr(SystemTimeToDateTime(Info^.stLastSeen)));
except
Add(‘’);
end;
try / / stLastUsed може бути 0 і тоді тут помилка буде
Add(DateTimeToStr(SystemTimeToDateTime(Info^.stLastUsed)));
except
Add(‘’);
end;
end;
end;

CurNode := ASelected.GetNextChild(CurNode);
end;

EndUpdate;
end;
end;

procedure ShowServices;
var
Info: __PBLUETOOTH_DEVICE_INFO;
ServiceCount: dword;
Services: array of TGUID;
hRadio: THandle;
Loop: integer;
begin
/ / Будуємо стовпці
with ListView.Columns do 
begin
BeginUpdate;
with Add do Caption := “GUID”;
EndUpdate;
end;

/ / Заповнюємо список
with ListView.Items do 
begin
BeginUpdate;

/ / Отримуємо розмір масиву сервісів
ServiceCount := 0;
Services := nil;
hRadio := ASelected.Parent.ImageIndex;
Info := ASelected.Data;
// NEW FUNCTION
BluetoothEnumerateInstalledServices 

(hRadio, Info, ServiceCount, nil);

/ / Виділяємо пам’ять
SetLength(Services, ServiceCount);

/ / Отримуємо список сервісів
BluetoothEnumerateInstalledServices 

(hRadio, Info, ServiceCount, PGUID(Services));

/ / Малюємо їх
for Loop := 0 to ServiceCount – 1 do
with Add do
Caption := GUIDToString(Services[Loop]);

/ / Очищаємо пам’ять
Services := nil;

EndUpdate;
end;
end;

begin
ASelected := TreeView.Selected;

/ / Очищаємо ListView
with ListView do 
begin
with Columns do
begin
BeginUpdate;
Clear;
EndUpdate;
end;

with Items do 
begin
BeginUpdate;
Clear;
EndUpdate;
end;
end;

/ / Заповнюємо інформацією
if Assigned(ASelected) then
case ASelected.ImageIndex of
-2: ShowServices;
-1: ShowRadios;
else
if ASelected.ImageIndex > 0 then ShowDevices;
end;
end; 

У цьому коді з’явилося три нові функції. Ось вони:

BluetoothIsConnectable – Визначає, чи можливе підключення до зазначеного радіомодуля.

Оголошення функції:


function BluetoothIsConnectable(const hRadio : THandle): BOOL; stdcall; 

Параметри:


hRadio – Handle радіомодуля, який ми перевіряємо. Якщо 0, то перевіряються всі радіомодулі.

Значення, що повертаються: поверне TRUE, якщо зазначений радіомодуль дозволяє вхідні підключення. Якщо hRadio = 0, то поверне TRUE, якщо хоча б один радіомодуль дозволяє вхідні підключення. Якщо вхідні підключення заборонені, то поверне FALSE.


BluetoothIsDiscoverable – Визначає, чи буде видно вказаний радіомодуль іншим при пошуку. Якщо проглядаються всі радіомодулі, то поверне TRUE якщо хоча б один дозволяє виявлення.

Оголошення функції:


function BluetoothIsDiscoverable(const hRadio : THandle): BOOL; stdcall; 

Параметри:


hRadio – Handle радіомодуля, який ми перевіряємо. Якщо 0, то перевіряються всі радіомодулі.

Значення, що повертаються: поверне TRUE, якщо зазначений радіомодуль дозволяє виявлення. Якщо hRadio = 0, то поверне TRUE, якщо хоча б один радіомодуль дозволяє виявлення. Якщо виявлення заборонено, то поверне FALSE.  


BluetoothEnumerateInstalledServices – Отримує список GUID сервісів, що надаються пристроєм. Якщо параметр hRadio = 0, то переглядає всі радіомодулі.

Оголошення функції:


function BluetoothEnumerateInstalledServices(
hRadio : THandle;
pbtdi : __PBLUETOOTH_DEVICE_INFO;
var pcServices : dword;
pGuidServices : PGUID): dword; stdcall; 

Параметри:


hRadio – Handle радіомодуля, який ми перевіряємо. Якщо 0, то перевіряються всі радіомодулі.
pbtdi – Покажчик на структуру BLUETOOTH_DEVICE_INFO, в якій описано проверяемое пристрій. Необхідно заповнити поля dwSize і Address.
pcServices – При виклику – кількість записів в масиві pGuidServices, повертає в цьому параметрі реальна кількість сервісів, що надаються пристроєм.
pGuidServices – Покажчик на масив TGUID, в який будуть записані GUID надаються пристроєм сервісом. Якщо nil і pcServices = 0, то в pcServices буде записано кількість сервісів. Необхідно виділити для pGuidServices пам’ять розміром не менш pcServices * SizeOf (TGUID).

Значення, що повертаються: поверне ERROR_SUCCESS, якщо виклик успішний і кількість сервісів в pcServices відповідає реальності. Поверне ERROR_MORE_DATA, якщо виклик успішний, але виділене кількість пам’яті (PcServices при виклику) менше, ніж кількість сервісів, що надаються. У випадку помилки – інші коди помилок Win32.


Примітки:

Подивіться на код отримання списку сервісів:


/ / Отримуємо розмір масиву сервісів
ServiceCount := 0;
Services := nil;
hRadio := ASelected.Parent.ImageIndex;
Info := ASelected.Data;
// NEW FUNCTION
BluetoothEnumerateInstalledServices(hRadio, Info, ServiceCount, nil);

/ / Виділяємо пам’ять.
SetLength(Services, ServiceCount);

/ / Отримуємо список сервісів
BluetoothEnumerateInstalledServices(hRadio, Info, ServiceCount, PGUID(Services)) 

Спочатку ми викликаємо функцію з pcServices = 0 і pGuidServices = nil для того, щоб отримати кількість сервісів, що надаються пристроєм.

Потім виділяємо пам’ять (SetLength ()) і тільки потім викликаємо функцію з реальними параметрами і отримуємо список сервісів.

Ще важливе зауваження. У файлі JwaBluetoothAPIs.pas параметр pbtdi має тип PBLUETOOTH_DEVICE_INFO, який розкривається в BLUETOOTH_DEVICE_INFO. Зауважте, що це НЕ ПОКАЖЧИК. Це не вірно, тому що в початковому вигляді функція вимагає саме покажчик. Тому, я ввів тип type __ PBLUETOOTH_DEVICE_INFO = ^ PBLUETOOTH_DEVICE_INFO

Так що ВИКОРИСТОВУЙТЕ файл з прикладу, а не з вихідної бібліотеки. Інакше отримаєте порушення доступу до пам’яті.

Коментар до коду: Ми перечитуємо інформацію про пристрій, так як за час, поки ми милуємося програмою, могли відбутися різні події: пристрій відключили, скасували авторизацію і т. п. А ми хочемо мати найсвіжішу інформацію про пристрій.

В принципі те, що описано вище, ми вже знали, окрім двох зазначених функцій.

Давайте розширимо можливості нашого застосування. Додамо функції заборони / дозволу виявлення радіомодуля і заборони / дозволу підключення до нього.


Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*