Работа с Bluetooth в Delphi

Сначала мы вызываем функцию с pcServices=0 и pGuidServices=nil для того, чтобы получить количество сервисов, предоставляемых устройством. Потом выделяем память (SetLength()) и только затем вызываем функцию с реальными параметрами и получаем список сервисов. Еще важное замечание. В файле JwaBluetoothAPIs.pas параметр pbtdi имеет тип PBLUETOOTH_DEVICE_INFO, который раскрывается в BLUETOOTH_DEVICE_INFO. Заметьте, что это НЕ УКАЗАТЕЛЬ. Это не верно, так как в исходном виде функция требует именно указатель. По-этому, я ввел тип type__PBLUETOOTH_DEVICE_INFO = ^PBLUETOOTH_DEVICE_INFO Так что ИСПОЛЬЗУЙТЕ файл из примера, а не из исходной библиотеки. Иначе получите нарушение доступа к памяти. Комментарий к коду: Мы перечитываем информацию об устройстве, так как за время, пока мы любуемся программой, могли произойти различные события: устройство отключили, отменили авторизацию и т. п. А мы хотим иметь самую свежую информацию об устройстве. В принципе то, что описано выше, мы уже знали, кроме двух указанных функций. Давайте расширим возможности нашего приложения. Добавим функции запрета/разрешения обнаружения радиомодуля и запрета/разрешения подключения к нему. BluetoothEnableIncomingConnections и BluetoothEnableDiscoverable Поместим на форму компонент TactionList и изменим его свойства как показано в таблице. Свойство Значение Name ActionList Теперь два раза щелкнем по ActionList и в появившемся окне редактора свойств добавим две TAction со следующими свойствами: Свойство Значение Caption Connectable Name acConnectable Свойство Значение Caption Discoverable Name acDiscoverable На панель Panel добавим две TButton и установим свойства: Свойство Значение Action acConnectable Name btConnectable Свойство Значение Action acDiscoverable Name btDiscoverable Напишем вот такой обработчик события OnUpdate у acConnectable:

procedure TfmMain.acConnectableUpdate(Sender: TObject);
var
SelectedItem: TListItem;
SelectedNode: TTreeNode;
begin
SelectedNode := TreeView.Selected;
SelectedItem := ListView.Selected;
with TAction(Sender) do
begin
Enabled := Assigned(SelectedNode) and Assigned(SelectedItem) and (SelectedNode.ImageIndex = -1);
if Enabled then
if StrToBool(SelectedItem.SubItems[4])
then Caption := 'Not conn.'
else Caption := 'Connectable';
end;
end;
И то же самое напишем для обработчика события OnUpdate - acDiscoverable:
procedure TfmMain.acDiscoverableUpdate(Sender: TObject);
var
SelectedItem: TListItem;
SelectedNode: TTreeNode;
begin
SelectedNode := TreeView.Selected;
SelectedItem := ListView.Selected;
with TAction(Sender) do
begin
Enabled := Assigned(SelectedNode) and Assigned(SelectedItem) and (SelectedNode.ImageIndex = -1);
if Enabled then
if StrToBool(SelectedItem.SubItems[5])
then Caption := 'Not disc.'
else Caption := 'Discoverable';
end;
end;
Теперь обработчик события OnExecute для acConnectable:
procedure TfmMain.acConnectableExecute(Sender: TObject);
var
SelectedItem: TListItem;
begin
SelectedItem := ListView.Selected;
if Assigned(SelectedItem) then
if not BluetoothEnableIncomingConnections(Integer(SelectedItem.Data), TAction(Sender).Caption = 'Not conn.')
then MessageDlg('Unable to change Radio state', mtError, [mbOK], 0)
else TreeViewChange(TreeView, TreeView.Selected);
end;
Такой же обработчик напишем и для OnExecute - acDiscoverable:
procedure TfmMain.acConnectableExecute(Sender: TObject);
var
SelectedItem: TListItem;
begin
SelectedItem := ListView.Selected;
if Assigned(SelectedItem) then
if not BluetoothEnableDiscovery(Integer(SelectedItem.Data), TAction(Sender).Caption = 'Not disc.')
then MessageDlg('Unable to change Radio state', mtError, [mbOK], 0)
else TreeViewChange(TreeView, TreeView.Selected);
end;
Вывод окна свойств устройства Важно: Если Windows сам использует радиомодуль, то он не даст поменять статус, хотя и функция выполнится без ошибок! Здесь мы ввели две новые функции (выделены жирным): BluetoothEnableInfomingConnection - функция разрешает/запрещает подключения к локальному радиомодулю Bluetooth. Объявление функции:
function BluetoothEnableIncomingConnections(
hRadio : THandle;
fEnabled : BOOL): BOOL; stdcall;
Параметры: hRadio Handle радиомодуля, статус которого мы хотим изменить. Если 0, то меняем у всех. fEnabled TRUE – разрешаем подключения; FALSE – запрещаем. Возвращаемые значения: ·TRUE - если вызов успешен и статус изменен, ·FALSE - в противном случае. BluetoothEnableDiscovery - функция разрешает/запрещает обнаружение локального радиомодуля Bluetooth Объявление функции:
function BluetoothEnableDiscovery(hRadio : THandle; fEnabled : BOOL): BOOL; stdcall;
Параметры: hRadio Handle радиомодуля, статус которого мы хотим изменить. Если 0, то меняем у всех. fEnabled TRUE – разрешаем обнаружение; FALSE – запрещаем. Возвращаемые значения: ·TRUE - если вызов успешен и статус изменен, ·FALSE - в противном случае. Теперь давайте научимся выводить системное окно свойств устройства Bluetooth. Для этого добавим к ActionList еще один TAction вот с такими свойствами: Свойство Значение Caption Property Name acProperty Добавим на Panel кнопку TButton с такими свойствами: Свойство Значение Action acProperty Name btProperty Теперь напишем такой обработчик событий OnUpdate у acProperty:
procedure TfmMain.acPropertyUpdate(Sender: TObject);
var
SelectedNode: TTreeNode;
SelectedItem: TListItem;
begin
SelectedNode := TreeView.Selected;
SelectedItem := ListView.Selected;
TAction(Sender).Enabled := Assigned(SelectedNode) and
Assigned(SelectedItem) and
(SelectedNode.ImageIndex > 0);
end;
И обработчик OnExecute для нее же:
procedure TfmMain.acPropertyExecute(Sender: TObject);
var
Info: BLUETOOTH_DEVICE_INFO;
begin
Info := BLUETOOTH_DEVICE_INFO(ListView.Selected.Data^);
BluetoothDisplayDeviceProperties(Handle, Info);
end;
Важно: В исходном виде в файле JwaBluetoothAPIs функция BluetoothDisplayDeviceProperties объявлена не верно. Второй параметр должен быть указателем, а там он передается как структура. Я исправил функцию так, чтобы он передавался как var-параметр (по ссылке). Используйте модуль JwaBluetoothAPIs из этого примера, чтобы не возникало ошибок доступа к памяти. Важно: Ни в этой процедуре, ни ранее, ни далее я не провожу проверку ошибок, чтобы не загромождать код лишними подробностями. В реальном приложении НЕОБХОДИМО проверять возвращаемые функциями значения и указатели. И так, в этом коде есть новая функция, выделенная жирным шрифтом. BluetoothDisplayDeviceProperty - функция выводит стандартное окно свойств устройства Bluetooth. Объявление функции: function BluetoothEnableDiscovery(hwndParent : HWND;var pbtdi : PBLUETOOTH_DEVICE_INFO): BOOL; stdcall; Важно: В оригинале (см. примечание выше) функция выглядит вот так: function BluetoothEnableDiscovery(hwndParent : HWND;pbtdi : PBLUETOOTH_DEVICE_INFO): BOOL; stdcall; Это не верно, так как в документации Microsoft указано, что параметр pbtdi должен передаваться как указатель (что подразумевает запись PBLUETOOTH_DEVICE_INFO), но как я писал выше, этот тип ошибочен. Он не является указателем. Я изменил функцию так, как показано выше (так она и должна быть, если не менять определение типа). Параметры: hwndParent Handle родительского окна, которому будет принадлежать диалог свойств. Может быть 0, тогда родительским выбирается окно Desktop. pbtdi Указатель на структуру BLUETOOTH_DEVICE_INFO в которой содержится адрес требуемого устройства. Возвращаемые значения: ·TRUE - если вызов успешен ·FALSE - в противном случае (код ошибки можно узнать вызовом функции GetLastError). Выбор устройства Рассмотрим, как вызвать окно диалога выбора устройства. Добавим в наш проект на Panel еще одну кнопку TButton и установите ее свойства как в таблице: Свойство Значение Caption Select Name btSelect Напишем вот такой обработчик события OnClick у этой кнопки:
procedure TfmMain.btSelectClick(Sender: TObject);
var
ASelParams: BLUETOOTH_SELECT_DEVICE_PARAMS;
ASelParamsSize: dword;
begin
ASelParamsSize := SizeOf(BLUETOOTH_SELECT_DEVICE_PARAMS);
FillChar(ASelParams, ASelParamsSize, 0);
with ASelParams do
begin
dwSize := ASelParamsSize;
hwndParent := Handle;
fShowRemembered := True;
fAddNewDeviceWizard := True;
end;
BluetoothSelectDevices(@ASelParams);
BluetoothSelectDevicesFree(@ASelParams);
end
В этой части кода две новые функции. BluetoothSelectDevices - функция разрешает/запрещает обнаружение локального радиомодуля Bluetooth. Объявление функции: function BluetoothSelectDevices(pbtsdp : PBLUETOOTH_SELECT_DEVICE_PARAMS): BOOL; stdcall; Параметры: pbtsdp Описание смотрите ниже в описании структуры. Возвращаемые значения: Если функция вернула TRUE, то пользователь выбрал устройства. Pbtsdp^.pDevices будет указывать на корректные данные. После вызова необходимо проверить флаги fAuthenticated и fRemembered, что бы удостовериться в корректности данных. Для освобождения памяти используйте функцию BluetoothSelectDevicesFree, только если функция вернет TRUE. Вернет FALSE если вызов прошел не удачно. Используйте GetLastError для получения дополнительных сведений. Возможные ошибки: ERROR_CANCELLED Пользователь отменил выбор устройства. ERROR_INVALID_PARAMETER Параметр pbsdp равен nil. ERROR_REVISION_MISMATCH Структура, переданная в pbsdp неизвестного или неверного размера. Другие ошибки Win32 BLUETOOTH_SELECT_DEVICE_PARAMS Объявление:
BLUETOOTH_SELECT_DEVICE_PARAMS = record
dwSize : DWORD;
cNumOfClasses : ULONG;
prgClassOfDevices : PBlueToothCodPairs;
pszInfo : LPWSTR;
hwndParent : HWND;
fForceAuthentication : BOOL;
fShowAuthenticated : BOOL;
fShowRemembered : BOOL;
fShowUnknown : BOOL;
fAddNewDeviceWizard : BOOL;
fSkipServicesPage : BOOL;
pfnDeviceCallback : PFN_DEVICE_CALLBACK;
pvParam : Pointer;
cNumDevices : DWORD;
pDevices : __PBLUETOOTH_DEVICE_INFO;
end;
Члены: dwSize Должен быть равен размеру структуры (dwSize := SizeOf(BLUETOOTH_RADIO_INFO)) cNumOfClasses Входной параметр. Количество записей в массиве prgClassOfDevice. Если 0, то ищутся все устройства. prgClassOfDevices Входной параметр. Массив COD (классов устройств), которые необходимо искать. pszInfo Входной параметр. Если не nil, то задает текст заголовка окна выбора устройства. hwndParent Входной параметр. Handle родительского окна для диалога выбора устройства. Если 0, то родителем будет Desktop. fForceAuthentication Входной параметр. Если TRUE, то требует принудительной авторизации устройств. fShowAuthenticated Входной параметр. Если TRUE, то авторизованные устройства будут доступны для выбора. fShowRemembered Входной параметр. Если TRUE, то запомненные устройства будут доступны для выбора. fShowUnknown Входной параметр. Если TRUE, то неизвестные (неавторизованные и не запомненные) устройства будут доступны для выбора. fAddNewDeviceWizard Входной параметр. Если TRUE, то запускает мастер добавления нового устройства. fSkipServicesPage Входной параметр. Если TRUE, то пропускает страницу Сервисы в мастере. pfnDeviceCallback Входной параметр. Если не nil, то является указателем на функцию обратного вызова, которая вызывается для каждого найденного устройства. Если функция вернет TRUE, то устройства добавляется в список, если нет, то устройство игнорируется. pvParam Входной параметр. Его значение будет передано функции pfnDeviceCallback в качестве параметра pvParam. cNumDevices Как входной параметр – количество устройств, которое требуется вернуть. Если 0, то нет ограничений. Как выходной параметр – количество возвращенных устройств (выбранных). pDevices Выходной параметр. Указатель на массив структур BLUETOOTH_DEVICE_INFO. Для его освобождения используйте функцию BluetoothSelectDevicesFree.Важно: В оригинале этот параметр объявлен как PBLUETOOTH_DEVICE_INFO. По этому поводу здесь много комментариев. BluetoothSelectDevicesFree - функция должна вызываться, только если вызов BluetoothSelectDevices был успешен. Эта функция освобождает память и ресурсы, задействованные функцией BluetoothSelectDevices в структуре BLUETOOTH_SELECT_DEVICE_PARAMS. Объявление функции: function BluetoothSelectDevices(pbtsdp : PBLUETOOTH_SELECT_DEVICE_PARAMS): BOOL; stdcall; Параметры: pbtsdp Описание смотрите выше в описании структуры. Возвращаемые значения: ·TRUE - если вызов успешен, ·FALSE - нечего освобождать. Управление сервисами Для управления сервисами Microsoft Bluetooth API предоставляет функцию: BluetoothSetServiceState - включает или выключает указанный сервис для устройства Bluetooth. Система проецирует сервис Bluetooth на соответствующий драйвер.

Отправить комментарий

Проверка
Антиспам проверка
Image CAPTCHA
...