Плагины для экрана Today
Экран Today – главный экран Windows Mobile, появляется сразу после загрузки системы. На экране Today представлена различная информация о текущем времени, напоминание о событиях, информация о владельце, количество новых сообщений, имя сотового оператора (для коммуникаторов и смартфонов) и т.д.
Элементы экрана Today можно отключать, менять порядок их расположения. У некоторых элементов может быть окно дополнительных настроек. Чтобы добраться для настроек плагинов, надо зайти в "Settings">"Today">"Items" (для русской версии "Настройка">"Сегодня">"Элементы")
Кроме того, сущеcтвует возможность подключать дополнительные программы в виде плагинов. Написанием такого плагина мы сейчас и займемся.
Плагины для Today оформляются в
виде DLL.
Эта DLL может экспортировать две
функции:
Функция инициализации плагина - обязательная:
-
HWND APIENTRY
InitializeCustomItem (
-
TODAYLISTITEM *ptli,
-
HWND hwndParent
- );
Функция должна создать окно для
будущего плагина. Входными параметрами является хэндл родительского
окна и структура описания плагина TODAYLISTITEM
-
- typedef struct
_TODAYLISTITEM {
-
TCHAR szName[MAX_ITEMNAME]; //
имя плагина
-
TODAYLISTITEMTYPE tlit; //
тип плагина
-
DWORD dwOrder; //
порядковый номер
-
DWORD cyp; // высота
плагина
-
BOOL fEnabled; // флаг
активности плагин
-
BOOL fOptions; // флаг
окна дополнительных настроек
-
DWORD grfFlags; //
дополнительные флаги
-
TCHAR szDLLPath[MAX_PATH]; //
путь к dll плагина
-
HINSTANCE hinstDLL; //
инстанс загруженной dll-ки
-
HWND hwndCustom; // хэндл
окна дополнительных настроек
-
BOOL fSizeOnDraw; //
зарезервировано
-
BYTE * prgbCachedData; //
указатель на пользовательские данные
-
DWORD cbCachedData; //
размер этих данных
-
} TODAYLISTITEMTYPE;
-
- И функция обработки сообщений
окна настроек - необязательная
-
BOOL APIENTRY
CustomItemOptionsDlgProc (
-
HWND hDlg,
- UINT message,
- UINT wParam,
- LONG lParam
- );
-
Это обычная функция
обработки сообщений окна, обычно в ней обрабатываются сообщения
WM_INITDIALOG (в нем происходит загрузка переменных в контролы) и
WM_COMMAND (обработка клавиши OK – сохранение параметров)
-
- Итак, поехали. Мы создадим
простой плагин без окна настроек, который что-нибудь выведет на
экран.
-
Создаем обычный Win32 Smart Device
проект/ В настройках проекат включаем опцию создания Dll.
-
- В полученный проект сразу же
добавляем def файл, в которм перечислены экспортируемые функции:
-
--- miniplugin.def ---
LIBRARY "miniplugin"
EXPORTS
InitializeCustomItem @240 NONAME
--- miniplugin.def
--- -
- Теперь создадим функицю
InitializeCustomItem
-
- HWND
InitializeCustomItem(TODAYLISTITEM *ptli, HWND hwndParent)
- {
-
g_hWnd =
CreateWindow(L"MyPlugin",L"MyPlugin",WS_VISIBLE
| WS_CHILD,
-
CW_USEDEFAULT,CW_USEDEFAULT,240,0,hwndParent,
NULL, g_hInst, NULL) ;
-
SetWindowLong(g_hWnd,
GWL_WNDPROC, (LONG) WndProc);
-
ShowWindow (g_hWnd,
SW_SHOWNORMAL);
-
UpdateWindow (g_hWnd) ;
- return g_hWnd;
-
}
-
- Как мы видим, в ней создается
экземпляр класса окна будущего плагина. Нам надо будет создать
функцию обработки сообщений этого окна
-
Добавим ее:
-
LRESULT CALLBACK WndProc (HWND
hwnd, UINT uimessage, WPARAM wParam, LPARAM lParam)
- {
-
switch (uimessage)
-
{
- //проверка необходимости
обновления окна плагина
-
case
WM_TODAYCUSTOM_QUERYREFRESHCACHE:
- {
-
TODAYLISTITEM *ptliItem;
-
ptliItem =
(TODAYLISTITEM*)wParam;
-
if ((NULL == ptliItem) ||
(WaitForSingleObject(SHELL_API_READY_EVENT, 0) == WAIT_TIMEOUT))
-
{
-
return FALSE;
-
}
-
if (0 == ptliItem->cyp)
-
{
-
ptliItem->cyp =
DRA::SCALEY(30);
-
return TRUE;
-
}
-
return FALSE;
-
}
-
- case WM_CREATE:
- break;
-
- // функция отрисовки
всякого
-
case WM_PAINT:
- {
-
PAINTSTRUCT ps;
-
RECT rect;
-
RECT myRect;
-
HDC hDC;
-
GetWindowRect(hwnd, &rect);
- hDC = BeginPaint(hwnd,
&ps);
-
SetBkMode(hDC,
TRANSPARENT);
-
- myRect.left = 0;
-
myRect.top =
DRA::SCALEY(2);
-
myRect.right = rect.right -
rect.left;
-
myRect.bottom = rect.bottom
- rect.top;
- LOGFONT lf;
-
HFONT hSysFont;
-
HFONT hFont;
-
hSysFont = (HFONT)
GetStockObject(SYSTEM_FONT);
-
GetObject(hSysFont,
sizeof(LOGFONT), &lf);
-
lf.lfHeight = (long) -((7.0
* (double)GetDeviceCaps(hDC, LOGPIXELSY) / 72.0)+.5);
-
hFont =
CreateFontIndirect(&lf);
-
HFONT hFontOld = (HFONT)
SelectObject(hDC, hFont);
-
COLORREF crText =
SendMessage(GetParent(hwnd), TODAYM_GETCOLOR, (WPARAM)
TODAYCOLOR_TEXT, NULL);
-
SetTextColor(hDC, crText);
-
DrawText(hDC, L"Hello
from Plugin =)", -1, &myRect, DT_LEFT);
-
SelectObject(hDC,
hFontOld);
-
DeleteObject(hFont);
-
EndPaint(hwnd,&ps);
-
}
-
return 0;
-
- case WM_DESTROY :
- return 0 ;
-
- // заливка области
плагина фоновым цветом
-
case WM_ERASEBKGND:
-
TODAYDRAWWATERMARKINFO dwi;
-
dwi.hdc = (HDC)wParam;
-
GetClientRect(hwnd,
&dwi.rc);
-
dwi.hwnd = hwnd;
-
SendMessage(GetParent(hwnd),
TODAYM_DRAWWATERMARK, 0,(LPARAM)&dwi);
-
return TRUE;
-
}
-
- return DefWindowProc
(hwnd, uimessage, wParam, lParam) ;
-
}
-
- По минимуму нам надо обработать
только сообщение WM_PAINT, но мы так же добавим обработку
WM_TODAYCUSTOM_QUERYREFRESHCACHE в которой мы укажем высоту
плагина и WM_ERASEBKGND, в которой попросим систему залить область
плагина фоновой картинкой.
-
- Минимальный плагин готов.
Теперь нужно его установить. Для этого сделаем следующее.
-
Скопируем полученную dll на девайс.
-
Создать ветку реестра в
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Today\Items с именем раздела,
совпадающего с именем нашего проекта
-
Внутри раздела создаем значения
типа DWORD Type=4. Enabled=1, Options=0 и строковое значение DLL в
котором укажем путь до нашей dll
-
Пошлем сообщение
SendMessage(HWND_BROADCAST,
WM_WININICHANGE, 0xF2, 0);.
- Если все сделано правильно, то
наш плагин появится на экране.
-
- Теперь научим наш плагин
реагировать на нажатие мышом. Для этого добавим обработчик сообщения
WM_LBUTTONUP
-
case WM_LBUTTONUP:
- {
-
int xPos = LOWORD(lParam);
- int yPos =
HIWORD(lParam);
-
TCHAR szText[200];
-
wsprintf(szText,L"Mouse
X=%d Y=%d",xPos,yPos);
-
MessageBox(0,szText,L"My
plugin", MB_OK | MB_ICONINFORMATION);
-
return 0;
-
}
-
- Таким образом можно
обрабатывать нажатия на разные участки плагина.
Кстати,
таким же образом можно обрабатывать нажатия на клавиши. Когда наш
плагин активен, то при нажатии на клавиши система посылает ему
сообщение WM_TODAYCUSTOM_USERNAVIGATION, обрабатывая которое, мы
можем получать коды нажатых клавиш. При нажатии на клавишу Enter
посылается сообщение WM_TODAYCUSTOM_ACTION. Добавим обработчики этих
сообщений в WndProc:
case
WM_TODAYCUSTOM_USERNAVIGATION:
{
int VirtKey = wParam;
// todo: use Virtual key
return TRUE;
}
case WM_TODAYCUSTOM_ACTION:
{
MessageBox(0,L"Return
pressed",
L"My
plugin", MB_OK | MB_ICONINFORMATION);
return 0;
}
-
- Кстати, чтобы плагин можно было
выделять, нужно создать в реестре DWORD параметр Selectability = 1
-
- Теперь настало время добавить
окно настроек. Для начала вносим в def файл проекта строку:
-
- CustomItemOptionsDlgProc @241 NONAME
-
- И описываем функцию обработки
сообщений окна настроек:
LRESULT
WINAPI CustomItemOptionsDlgProc(HWND hDlg, UINT message, WPARAM
wParam, LPARAM lParam)
{
static
TODAYLISTITEM *s_ptliItem = NULL;
switch
(message)
{
case
WM_INITDIALOG:
{
SHINITDLGINFO
shidi;
shidi.dwMask
= SHIDIM_FLAGS;
shidi.dwFlags
= SHIDIF_DONEBUTTON | SHIDIF_SIPDOWN |
SHIDIF_SIZEDLGFULLSCREEN;
shidi.hDlg
= hDlg;
SHInitDialog(&shidi);
s_ptliItem
= (TODAYLISTITEM*)lParam;
}
return
TRUE;
case
WM_COMMAND:
if
(LOWORD(wParam) == IDOK)
{
EndDialog(hDlg,
LOWORD(wParam));
return
TRUE;
}
break;
case
WM_DESTROY:
s_ptliItem
= NULL;
break;
}
- В файл ресурсов необходимо
вставить ресурс для диалога ID ресурса должен быть равен 500, иначе окно не будет активировано:
-
- IDD_TODAY_CUSTOM DIALOG
DISCARDABLE 0, 0, 140, 57
-
STYLE DS_CONTROL | WS_POPUP |
WS_VISIBLE | WS_CAPTION
-
EXSTYLE 0x80000000L
-
CAPTION "My Today
Settings"
-
BEGIN
-
LTEXT "MyToday
- Options",IDC_STATIC_TITLE,4,3,124,10
-
LTEXT
"Description of the options for your DLL go here.",
-
IDC_STATIC_DESC,5,18,124,16
-
END
-
- Не забудем также поменять
параметр Options в ветке реестра плагина на 1.
-
- Теперь при выборе кнопки
Options в настройках Today, мы увидит наше окно настроек:
-
Ну, собственно, и
все... Теперь мы умеем создавать плагины для Today. Правда наш плагин
пока не умеет самостоятельно устанавливаться на девайс, что не
позволит обычному юзеру правильно его использовать, поэтому самое
время научиться делать CAB файлы для установки.
-
|