Для того чтобы управлять LED-индикаторами устройства, в Windows Mobile предусмотрено специальное API:
BOOL WINAPI NLedSetDevice(UINT nDeviceId, void* pInput);
Первый параметр, nDeviceID указывает на то, какие данные передаются в параметре pInput. Для того чтобы установить состояние LED-индикатора, параметр nDeviceID должен иметь значение NLED_SETTINGS_INFO_ID, а в качестве параметра pInput необходимо передать указатель на структуру NLED_SETTINGS_INFO, содержащую информацию о новом состоянии LED-индикатора.
struct NLED_SETTINGS_INFO { UINT LedNum; INT OffOnBlink; LONG TotalCycleTime; LONG OnTime; LONG OffTime; INT MetaCycleOn; INT MetaCycleOff; };
- LedNum – содержит индекс LED-индикатора (zero-based).
- OffOnBlink – содержит новое состояние индикатора (0 – выключен, 1 – включен, 2 – мигающий
- TotalCycleTime – длительность цикла мерцания в миллисекундах
- OnTime – длительность включенного состояния индикатора при мерцании
- OffTime – длительность выключенного состояния индикатора при мерцании
- MetaCycleOn – количество ON-циклов
- MetaCycleOff – количество OFF-циклов
Вобще описание назначения последних двух полей структуры вводит меня в недоумение. В MSDN по этому поводу всего две скупые фразы “Number of on blink cycles.” и “Number of off blink cycles.” без какого-либо дальнейшего пояснения.
Для того чтобы получить количество LED-индикаторов в системе можно воспользоваться функцией NLedGetDeviceInfo:
BOOL WINAPI NLedGetDeviceInfo(UINT nInfoId, void* pOutput);
В качестве первого параметра необходимо передать значение NLED_COUNT_INFO_ID, в качестве второго параметра – указатель на структуру NLED_COUNT_INFO, которая, в случае успешного завершения работы функции, будет содержать количество индикаторов.
Ну вот, с теоретической частью закончили, теперь перейдем к рассмотрению простенького примера. А в качестве примера у нас будет небольшая библиотека-обертка над описанным выше API.
wxMobileLED.h
#ifndef _WX_MOBILE_LED_H #define _WX_MOBILE_LED_H class wxMobileLEDImpl; class wxMobileLED { wxMobileLEDImpl * m_Impl; public: wxMobileLED(); ~wxMobileLED(); size_t GetCount(); bool SetLED(size_t index, bool value, bool blink = false); }; #endif
wxMobileLED.cpp
#include "wxMobileLED.h" #if defined(__WXWINCE__) #include "wxMobileLEDImplWinCE.h" #else #endif wxMobileLED::wxMobileLED() { m_Impl = #if defined(__WXWINCE__) new wxMobileLEDImplWinCE; #else NULL; #endif } wxMobileLED::~wxMobileLED() { if(m_Impl) delete m_Impl; } size_t wxMobileLED::GetCount() { if(m_Impl) { return m_Impl->GetCount(); } return 0; } bool wxMobileLED::SetLED(size_t index, bool value, bool blink) { if(m_Impl) { return m_Impl->SetLED(index, value, blink); } return false; }
wxMobileLEDImpl.h
#ifndef _WX_MOBILE_LED_IMPL_H #define _WX_MOBILE_LED_IMPL_H class wxMobileLEDImpl { public: virtual size_t GetCount() = 0; virtual bool SetLED(size_t index, bool value, bool blink = false) = 0; }; #endif
wxMobileLEDImplWinCE.h
#ifndef _WX_MOBILE_LED_IMPL_WINCE_H #define _WX_MOBILE_LED_IMPL_WINCE_H #include "wxMobileLEDImpl.h" class wxMobileLEDImplWinCE : public wxMobileLEDImpl { public: virtual size_t GetCount(); virtual bool SetLED(size_t index, bool value, bool blink = 0); }; #endif
wxMobileLEDImplWinCE.cpp
#include "wxMobileLEDImplWinCE.h" #include <windows.h> #include <NLed.h> size_t wxMobileLEDImplWinCE::GetCount() { #if defined(__WXWINCE__) && (UNDER_CE >= 0x500) NLED_COUNT_INFO count = {0}; NLedGetDeviceInfo(NLED_COUNT_INFO_ID,&count); return count.cLeds; #else return 0; #endif } bool wxMobileLEDImplWinCE::SetLED(size_t index, bool value, bool blink) { #if defined(__WXWINCE__) && (UNDER_CE >= 0x500) do { if(index >= GetCount()) break; NLED_SETTINGS_INFO info; ZeroMemory(&info, sizeof(NLED_SETTINGS_INFO)); info.LedNum = index; info.OffOnBlink = value ? (blink ? 2 : 1) : 0; return (NLedSetDevice(NLED_SETTINGS_INFO_ID, &info) == TRUE); } while(false); #endif return false; }
Пример использования библиотеки:
wxMobileLED m_MobileLED; ... void wxMobileLEDTestMainFrame::FillLEDList() { size_t ledCount = m_MobileLED.GetCount(); for(size_t i = 0; i < ledCount; i++) { int item = m_LEDList->Append(wxString::Format(wxT("LED %i"), i+1)); } } void wxMobileLEDTestMainFrame::UpdateLEDs() { for(size_t i = 0; i < m_LEDList->GetCount(); i++) { bool value = m_LEDList->IsChecked(i); if(!m_MobileLED.SetLED(i, value, m_BlinkCheckBox->GetValue())) { wxLogTrace(wxTraceMask(), _("Unable to turn LED #%i %s"), i, value ? _("ON") : _("OFF")); } } }
Исходный код примера для wxWinCE, а также исполняемый файл для Windows Mobile 6 можно взять здесь.
PS: Хотя описанное выше API предназначено для управления состоянием LED-индикаторов и на эмуляторе действительно управляет ими, но на реальном устройстве (ETEN Glofiish X800 под управлением Windows Mobile 6) включение/віключение индикатора с индексом 1 приводит к включению/віключению вибро. Мая шоке %).
Так и есть, ведь вибро – это индикатор с состоянием вкл/выкл.
На счет моста – несовсем, случай вырожденный, для других платформ он не определен. Достаточно было бы простого наследования.
Так же ж по поводу моста, планировалось же “на вырост”, чтобы еще под Linux дописать аналог.