SystemTray FAQ, C / C + +, Програмування, статті

Hаиболее часті запитання по SystemTary

Лев Серебряков (Lev Serebryakov),
2:5030 / 219.33 @ fidonet або lev@spb.runnet.ru

Частина 0. Про що.

Даний спіcок питань і відповідей на них містить найбільш поширені запитання щодо використання у своїх програмах для Microsoft Windows 95 і Microsoft Windows NT 4.0 можливості оболонки, званої System Tray.

Частина 1. Коментар.

Я хочу поблагадоріть:
Andy Nicks (2:5031 / 16.2 @ Fidonet), Kirill Pushkin (2:5030 / 219.19), а так само програмістів петербурзької фірми "ПРОМТ", без цих людей навряд чи я б написав цей FAQ.

Будь-які побажання, поправки, уточнення приймаються!
Розповсюдження – вільний!

Частина 2. Версії.

Частина 3. Зміст.

Частина 4. Власне FAQ.

Q1: Що таке System Tray? Про що йдеться?

A1: Якщо Ви в операційній ситеме Windows'95 або Windows NT 4.0 користуєтеся оболонкою Explorer, то праворуч на TaskBar'е Ви повинні були бачити "поглиблену" область в якій, звичайно, поміщаються годинник, перемикач клавіатури, регулятор гучності і деякі інші утиліти. Вони зображуються маленькими іконками і для них існують ToolTip'и як для кнопок ToolBar'ов. При клацанні або двічі клацнути по такій іконці програма зазвичай виконує дію за замовчуванням, а при натисканні правою кнопкою показує Pop-Up меню.
Hа рівні оболонки System Tray це додаток, що підтримує вікно, яке ви бачите як "поглиблену" область і деякий сервіс для роботи з цим вікном.

Q2: Як мені перенести свою програму на Tray?

A2: Це типовий питання програміста, пише якусь утиліту, що працює в Background під час всієї роботи операційної системи (в DOS такі утиліти робилися TSR-програмами). Але питання поставлене не коректно.
Зазвичай ставив це питання програміст має на увазі приблизно наступне: "Моя програма працює [майже] весь час в мінімізованому стані і дуже шкода місця під її кнопку на TaskBar'е. Як мені зробити, що б при мінімізації [старті | весь час] моя програма представлялася іконкою на System Tray'е і відповідала на повідомлення миші від цієї іконки? "
Відповідь на це питання складається з кількох частин. Дивись наступні питання і відповіді на них.

Q3: Що таке ікона на System Tray?

A3: Відповідь на це питання пояснює некоректність питання 2. Іконка на Tray'е це просто картинка, а не вікно якоїсь програми (дослідження системи за допомогою Microsoft Spy + + for Windows 95 показує, що це не вікно взагалі). System Tray відстежує події миші над іконкою і, в разі потреби, показує ToolTip для цієї іконки. Так само він відсилає повідомлення про всіх діях миші над іконкою вікна, яке помістило іконку на Tray.
Таким чином, не можна помістити програму на Tray. Будь-яка програма може додати стоько іконок на Tray, скільки їй необхідно. При цьому головне вікно програми не зобов'язана зникати або мінімізіроватся – прикладом може служити Microsoft Internet Mail, поміщаються іконку "конверт" на Tray в разі появи нових листів.

Q4: Як додати іконку на Tray?

A4: Для роботи з SystemTray існує всього одна функція. Ось її Сі-прототип:

WINSHELLAPI BOOL WINAPI Shell_NotifyIcon(
DWORD dwMessage, // message identifier
PNOTIFYICONDATA pnid // pointer to structure
);

Ця функція описана в заголовному файлі Win32-SDK "shellapi.h", включається в програму при включенні "windows.h". Параметр dwMessage може приймати одне з трьох значень: NIM_ADD, NIM_DELETE, NIM_MODIFY. Для додавання іконки він повинен бути встановлений в NIM_ADD.
Параметр pnid має тип PNOTIFYDATA, який описаний як:

typedef struct _NOTIFYICONDATA { // nid
DWORD cbSize;
HWND hWnd;
UINT uID;
UINT uFlags;
UINT uCallbackMessage;
HICON hIcon;
char szTip[64];
} NOTIFYICONDATA, *PNOTIFYICONDATA;

Поля структури NOTIFYICONDATA мають наступний зміст:

cbSize – Розмір структури, повинен бути sizeof (NOTIFYICONDATA).
hWnd – Дескриптор вікна, яке отримуватиме події миші над іконкою.
uID – Унікальний ідентифікатор іконки. Ідентифікатор повинен бути унікальним у межах вікна – обробника, переданого в hWnd.
uFlags – Бітове поле, що визначає яке з наступних полів несе дійсну інформацію. Може бути одним з наступних значень: NIF_ICON, NIF_MESSAGE, NIF_TIP або їх OR-комбінацією.
uCallbackMessage – Повідомлення, що передається вікна – обробникові при подіях миші. Бажано отримувати номер повідомлення викликом RegisterWindowMessage(), Але допускаються і значення WM_USER + N, де N> 0.
hIcon – Дескриптор іконки, що поміщається на Tray.
szTip – Текст для ToolTip'а, якщо szTip [0] = 0x00, то ToolTip'а не буде.

Таким чином, для додавання іконки на Tray необхідно заповнити примірник структури NOTIFYICONDATA і викликати функцію Shell_NotifyIcon() з параметром NIM_ADD і покажчиком на заповнений примірник структури.
При додаванні іконки необхідно заповнити поля cbSize, hWnd, uID, uFlags, uCallbackMessage, hIcon. Поле szTip можна залишити порожнім, якщо вам не потрібен ToolTip. Поле uFlags повинно містити як мінімум NIF_MESSAGE | NIF_ICON.

Q5: Я додав іконку на Tray, а як її там змінити?

A5: Після додавання іконки на Tray можна міняти саму іконку, ToolTip і повідомлення, що посилається вікна. Для цього необхідно заповнити примірник структури NOTIFYICONDATA і викликати функцію Shell_NotifyIcon() з параметром NIM_MODIFY і покажчиком на заповнений примірник структури.
При зміні іконки необхідно заповнити поля cbSize, hWnd, uID, uFlags і поля, що відповідають за параметри іконки, які ви хочете міняти. При цьому uFlags повинен містити комбінацію прапорів, що описує поля, які необхідно змінювати.

Q6: А як видалити іконку з Tray?

A6: Для видалення іконки ви повинні знати її ID і дескриптор вікна-обробника повідомлень.
Для видалення іконки з Tray треба викликати функцію Shell_NotifyIcon() з параметром NIM_DELETE і покажчиком на екземпляр структури NOTIFYICONDATA, У якого повинні бути заповнені такі поля: cbSize, hWnd, uID.

Q7: Як мені дізнатися про вплив миші на іконку, що знаходиться на Tray?

A7: При додаванні іконки на Tray ви вказували вікно – обробник повідомлення і повідомлення (CallbackMessage). Тепер вікно, вказане вами буде за будь-яких подіях миші, що відбуваються над іконкою отримувати повідомлення, вказане при додаванні іконки. При цьому параметри lParam і wParam будуть задіяні наступним чином:
(UINT)wParam – Містить ID іконки, над якою відбулася подія
(UINT)lParam – Містить стандартне подія миші, таке як WM_MOUSEMOVE або WM_LBUTTONDOWN.
При цьому, інформація про клавіші зміни регістру, так само як і місця розташування події, що передаються при стандартних "справжніх" повідомленнях миші, втрачаються. Але положення курсору можна дізнатися функцією GetCursorPos (), а стан клавіш зміни регістру – функцією GetKeyState(), Описаних в winuser.h.

Q8: Багато програм показують Pop-Up меню при клацанні на їх іконці, вміщеній на Tray, як цього домогтися?

A8: Ви повинні обробляти повідомлення, вказане вами при додаванні іконки на Tray. При значенні (UINT)lParam, Що дорівнює WM_RBUTTONDOWN (Це звичайно дял Pop-Up меню по правій кнопці), або будь-якого іншого необхідного вам, ви повинні викликом функції GetCursorPos() отримати позицію курсору в момент події (навряд чи користувач встигне прибрати миша за час обробки повідомлення, особливо якщо він очікує меню), отримати вескріптор Pop-Up меню одним з багатьох способів (LoadMenu(), GetSubMenu(), CreateMenu(), І т.д.) і виконати наступний код:

SetForegroundWindow(hWnd);
TrackPopupMenuEx (hMenu, TPM_HORIZONTAL | TPM_LEFTALIGN, x, y, hWnd, NULL);
DestroyMenu(hMenu);
PostMessage(hWnd,WM_USER,0,0);

де hWnd – Дескриптор вікна, яке буде обробляти команду меню, hMenu – Дескриптор меню, x і y – Позиція курсора. Для подробиць дивіться Win32 SDK Help по функції TrackPopupMenuEx.

Q9: Багато програм мінімізуючи, опиняються на Tray, як це зробити?

A9: Hа насправді, не "програма виявляється на Tray", а тільки іконка поміщається на Tray, а головне вікно програми ховається. Для досягнення такого результату вам треба обробляти повідомлення WM_SIZE, І при значенні wParam, Що дорівнює SIZE_MINIMIZED ви повинні виконати приблизно наступну послідовність дій: додати іконку на Tray і приховати вікно – викликати ShowIndow(hWnd, SW_HIDE).
Коли відбудеться дія, яка должго активувати вашу програму – WM_LBUTTONDBLCLK або WM_LBUTTONDOWN (Або те, що подобається вам), ви повинні видалити іконку і викликати ShowWindow(hWnd,SW_SHOW) або ShowWindow(hWnd,SW_SHOWMAXIMIZED).

Q10: Чи завжди все вищесказане буде працювати?

A10: Hі! Все вищенаписане працює тільки при використанні в операційних системах Windows 95 і Windows NT 4.0 оболонки Explorer, і при дозволеному System Tray. У випадку, якщо не відбувається запуску systray.exe (запускаетс автоматично Explorer'ом при старті) або використовується інша оболонка (DashBoard, Program Manager, File Manager), Функція Shell_NotifyIcon() повертатиме при виклику FALSE і не виконувати ніяких дій.
Ще раз повторю: System Tray – це можливість оболонки, а не операційної системи!

Q11: А чи є офіційна інформація з System Tray?

A11: Так, є. Є маленький приклад в Win32 SDK: SDKRoot \ Samples \ Win32 \ Win95 \ TrayNot \ *.*
Hу і звичайно опис в документації функції Shell_NotifyIcon() і структури NOTIFYICONDATA.
Так само можна подивитися Microsoft Knowledge Base:
PSS ID Number: Q128129
PSS ID Number: Q134237
PSS ID Number: Q139408

Q12: Як зробити пункт "за умовчанням" в Pop-Up меню виділеним?

A12: Взагалі-то, це питання не відноситься до System Tray, а відноситься до меню. Але можна відповісти і на нього. Встановлюється пункт "за умовчанням" в будь-якому меню функцією API SetMenuDefaultItem(HMENU hMenu, UINT uItem, UINT fByPos), Подробиці – у Win32 SDK документації. Пункт "За замовчуванням" не впливає на роботу меню – це чисто інтерфейсне виділення пункту меню напівжирним (bold) шрифтом.

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


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

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

Ваш отзыв

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

*

*