Упражнение 4, стр. от
Упражнение 4
Използване на SystemTray
-
Запознаване с една полезна възможност на потребителския интерфейс на Windows - добавяне и използване на икона в SystemTray (най-дясната област на лентата със задачи)
-
Запознаване с често използвания подход за предаване на параметри към функциите на Windows API - чрез структури
2Теоретична постановка 2.1Общи положения
Практически всяка функция, независимо от колко входни параметъра се нуждае и колко резултата трябва да върне и колко са сложни те, може да се реализира с единствен параметър - указател към структура. Всички необходими входни и изходни параметри могат да се дефинират като полета в структурата, с произволен брой и сложност. Този подход се използва много често в Windows API. Някои от полетата са входни и се попълват преди извикването на функцията. Други са изходни и носят информация след връщане от функцията. Някои полета могат да бъдат входно-изходни.
Често се използват две особени входни полета. В едното трябва да се зададе размера в байтове на структурата (това обикновено се налага от разширяването на възможностите на съответната функция с новите версии на Windows). Другото представлява битово поле (набор от флагове), показващо кои входни полета са валидни и/или кои изходни трябва да се попълнят.
За пример ще разгледаме API функцията, реализираща възможността за добавяне на икона към SystemTray.
Функцията е дефинирана така:
WINSHELLAPI BOOL WINAPI Shell_NotifyIcon
(
DWORD dwMessage, // идентификатор на съобщение
PNOTIFYICONDATA pnid // указател към структура
);
Функцията връща TRUE/FALSE в зависимост от това, дали е успяла.
Първият параметър може да бъде един от:
Останалата инфомация се предава към функцията чрез структурата NOTIFYICONDATA, дефинирана в API така:
typedef struct _NOTIFYICONDATA {
DWORD cbSize;
HWND hWnd;
UINT uID;
UINT uFlags;
UINT uCallbackMessage;
HICON hIcon;
char szTip[64];
} NOTIFYICONDATA, *PNOTIFYICONDATA;
-
cbSize Размер на структурата. Добре е да се използва sizeof(…), а не например 88 .
-
hWnd Манипулатор на прозорец, който да получава съобщения при действия с мишката върху иконата в SystemTray.
-
uID Идентификатор на иконата. Няма нищо общо с ресурсния идентификатор.
-
uFlags - Флагове, показващи кои полета в структурата са валидни. Може да е произволна комбинация от: NIF_ICON, NIF_MESSAGE и NIF_TIP, например NIF_ICON | NIF_MESSAGE | NIF_TIP
-
uCallbackMessage Съобщение, което да се изпрати на указания прозорец. Това трябва да бъде потребителско съобщение, а не някое от стандартните съобщения на Windows. За целта може да се дефинира константа:
#define WM_TRAY WM_USER+1
WM_USER е стандартна константа, указваща началото на стойностите, допустими за потребителски съобщения. При всяко действие с мишката върху иконата, Windows ще изпраща на указания прозорец това съобщение. При това wParam ще съдържа идентификатора на иконата (uID), а lParam - една от стойностите WM_MOUSEMOVE, WM_LBUTTONDOWN, WM_RBUTTONDOWN, WM_LBUTTONDBLCLK, WM_RBUTTONDBLCLK
-
hIcon Манипулатор на икона, която ще се добави към SystemTray. Може да се получи чрез функция LoadIcon(…).
-
szTip Текст, който да се появява при задържане на мишката над иконата.
Последните три полета не са задължителни. За всяко от тях, което е валидно при дадено извикване на функцията, трябва да се посочи съответния флаг.
Друга функция, която може да се използва в настоящето упражнение, реализира възможността за показване на падащо меню (така както става в Windows при щракване на десен бутон на мишката).
Функцията е
BOOL TrackPopupMenu(
HMENU hMenu, // Манипулатор на меню, което да се изведе
UINT uFlags, // Флагове, определящи позицията на менюто и поведението на
// функцията
int x, // Екранни координати, където да се изведе менюто
int y, //
int nReserved,// Запазено, трябва да е 0
HWND hWnd, // Манипулатор на прозореца, от който се създава менюто
CONST RECT *prcRect // Указва област от екрана, в която потребителят може
// да щрака с мишката, без менюто да се скрива. Ако е
// NULL, менюто се скрива при щракване извън него.
);
Функцията показва указаното меню. Работата й завършва след като потребителят избере команда или щракне извън указаната област (най-често извън менюто). При валиден избор функцията изпраща на указания прозорец съответно съобщение WM_COMMAND.
За полето uFlags може да се погледне в Help-а. Примерна добра стойност за това поле е TPM_BOTTOMALIGN | TPM_RIGHTALIGN.
Манипулатор на меню може да се получи например така:
HMENU popmenu=GetSubMenu(GetMenu(hWnd),0);
Така popupmenu указва първото падащо меню на прозореца (обикновено File).
3Задачи -
Да се състави програма, която добавя икона към SystemTray. При натискане на ляв клавиш върху иконата да се скрива или показва прозореца на програмата.
-
Иконата да променя вида си в зависимост от това дали прозорецът е видим или не.
-
При натискане на десен бутон върху иконата да се извежда меню.
4Указания -
Както и в досегашните упражнения може да се започне с "Typical Hello World Application".
-
ВАЖНА ЗАБЕЛЕЖКА:
След като AppWizard създаде скелета на програмата, трябва да се отвори файла stdafx.h и да се премахне от него реда:
#define WIN32_LEAN_AND_MEAN
Наличието му изключва "рядко използвани" (според Microsoft) неща от API. Към тях спада работата със SystemTray.
-
Удобно е обръщението към API функцията Shell_NotifyIcon() да се "скрие" в потребителска функция, например:
BOOL TrayMessage(HWND hwnd,DWORD dwMessage,HICON hIcon)
{
NOTIFYICONDATA tnd;
tnd.cbSize =sizeof(tnd);
tnd.hWnd =hwnd;
tnd.uID =100;
tnd.uFlags =NIF_TIP|NIF_ICON|NIF_MESSAGE;
tnd.uCallbackMessage =WM_TRAY;
tnd.hIcon =hIcon;
lstrcpy(tnd.szTip,"My tray icon");
return Shell_NotifyIcon(dwMessage,&tnd);
}
-
Функцията TrayMessage() трябва да се извика поне два пъти - веднъж за да покаже иконата в SystemTray, например в InitInstance() и втори път - за да я скрие, например при обработката на WM_DESTROY
-
Ресурси се зареждат със специални API функции. Например има функция
HICON LoadIcon(HINSTANCE hInst, LPCTSTR iconName)
Първият параметър е екземпляр на процеса. Той се получава като параметър в WinMain функцията. Вторият параметър е идентификатора на иконата. Той може да бъде символен низ или 16 битово цяло число, следвано от байт 0. За получаване на такова число, което и да е съвместимо с LPTSTR се използва макросът
LPTSTR MAKEINTRESOURCE(WORD resourceid);
Правилният начин на зареждане на икона, генерирана от AppWizard или друга, създадена от вас, е например:
HICON myicon=LoadIcon(hInst,MAKEINTRESOURCE(IDI_SMALL));
Използването на макроса MAKEINTRESOURCE се налага от факта, че IDI_SMALL всъщност е число (в това може да се убедите ако отворите файла RESOURCE.H). IDI_SMALL естествено може да се замени с идентификатор на икона, създадена от вас.
Има подобни функции - LoadMenu(...), LoadString(...), LoadCursor(...), LoadAccelerators(...) за зареждане съответно на меню, низ, курсор, горещи клавиши (функционални клавиши, Ctrl- комбинации)
-
Към видимостта на прозореца имат отношение следните API функции:
ShowWindow(hWnd,SW_SHOW)- показва прозорец
ShowWindow(hWnd,SW_HIDE)- скрива прозорец (за още възможности вж. Help-а)
IsWindowVisible(hWnd) - връща TRUE ако прозореца е видим, иначе-FALSE
Сподели с приятели: |