Суббота, 19.07.2025, 12:55 Приветствую Вас Гость

On-line: Книги, учебники, статьи

Главная | Регистрация | Вход | RSS

Глава 5. Разрешение некоторых проблем программирования в Windows(1)

Глава 5. Разрешение некоторых проблем программирования в Windows

Признаться, данная глава стала для меня некоторым компромиссом. Вопросов программирования в Windows еще так много, что не хотелось бы их опускать. А если писать на каждый вопрос целую главу - книга станет непомерно большой. И я решил отвести на все оставшееся (но далеко не все, однако) одну главу, где постараюсь, насколько это возможно, подробно осветить ряд интересных вопросов. Глава будет построена в виде вопросов гипотетического собеседника и ответов на них Вашего покорного слуги. Итак, приступим.

I

В. Как сделать так, чтобы при минимизации окна значок его помещался бы на системную панель?

Эта проблема решается с использованием системной функции Shell_NotifyIcon. Причем решение это столь просто и прозрачно, что приходится удивляться тому, что большинство для этих целей привлекают какие-то библиотеки. Вот параметры этой функции:

  • 1-й параметр. Действие, которое необходимо произвести:
    • NIM_ADD equ 0h ; добавить иконку на системную панель
    • NIM_MODIFY equ 1h ; удалить иконку
    • NIM_DELETE equ 2h ; модифицировать иконку
  • 2-й параметр. Указатель на структуру, где содержится информация, необходимая для реализации указанного действия.
    NOTI_ICON STRUC
     cbSize DWORD ?
     hWnd DWORD ?
     uID DWORD ?
     uFlags DWORD ?
     uCallbackMessage DWORD ?
     hIcon DWORD ?
     szTip DB 64 DUP (?)
    NOTI_ICON ENDS
    
    • cbSize - размер структуры.
    • hWnd — дескриптор окна, куда будет посылаться сообщение (см. ниже)
    • uID - идентификатор иконки
    • uFlags - комбинация следующих флагов
      NIF_MESSAGE equ 1h; использовать поле hIcon
      NIF_ICON equ 2h; использовать поле uCallbackMessage
      NIF_TIP equ 4h; использовать поле szTip
    • uCallbackMessage - сообщение, которое приходит на окно, определяемое дескриптором
    • hWnd, в случае возникновения некого события вблизи иконки на системной панели. Значение сообщения должно быть больше, чем 1024. При приходе этого сообщения WPARAM содержит идентификатор иконки, a LPARAM - событие, т.е. то, что произошло с иконкой.
    • hIcon - дескриптор иконки.
    • szTip - текст всплывающей подсказки.

Давайте рассмотрим, как работает весь механизм. В случае минимизации окна на функцию окна приходит сообщение WM_SIZE. Причем wParam должен содержать значение SIZE_MINIMIZED. Вот тогда то и следует воспользоваться функцией Shell_NotifyIcon, которая поместит иконку на системную панель. Любые же события с мышью, когда ее курсор находится на иконке, вызовут приход на функцию окна сообщения uCallbackMessage, которое, естественно, мы сами и определи. При этом младшее слово wParam будет содержать идентификатор иконки, а по младшему слову lParam можно определить, что же приключилось (см. ниже). Ниже (Рис. 3.5.1) Вы увидите, как все это работает.

// файл tray.rc
// определение констант
#define WS_SYSMENU 0x00080000L
#define WS_MINIMIZEBOX 0x00020000L
#define WS_MAXIMIZEBOX 0x0001OOOOL
#define DS_3DLOOK 0x0004L

// идентификаторы
#define IDI_ICON1 1

// определили иконку
IDI_ICON1 ICON "ico1.ico"

//определение диалогового окна
DIAL1 DIALOG 0, 0, 250, 110
STYLE WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | DS_3DLOOK
CAPTION "Поместить иконку на системную панель"
FONT 8, "Arial"
{
}

; файл tray.inc
; константы
NIM_ADD equ 0h ; добавить иконку на системную панель
NIM_MODIFY equ 1h ; удалить иконку
NIM_DELETE equ 2h ; модифицировать иконку
NIF_MESSAGE equ 1h ; использовать поле hIcon
NIF_ICON equ 2h ; использовать поле uCallbackMessage
NIF_TIP equ 4h ; использовать поле szTip
FLAG equ NIF_MESSAGE or NIF_ICON or NIF_TIP

SIZE_MINIMIZED equ 1h
SW_HIDE equ 0
SW_SHOWNORMAL equ 1

; сообщение приходит при закрытии окна
WM_CLOSE equ 10h
WM_INITDIALOG equ 110h
WM_SIZE equ 5h
WM_LBUTTONDBLCLK equ 203h
WM_LBUTTONDOWN equ 201h

; прототипы внешних процедур
IFDEF MASM
 EXTERN ShowWindow@8:NEAR
 EXTERN LoadIconA@8:NEAR
 EXTERN lstrcpy@8:NEAR
 EXTERN Shell_NotifyIconA@8:NEAR
 EXTERN ExitProcess@4:NEAR
 EXTERN GetModuleHandleA@4:NEAR
 EXTERN DialogBoxParamA@20:NEAR
 EXTERN EndDialog@8:NEAR
 EXTERN SendDlgItemMessageA@20:NEAR
ELSE
 EXTERN ShowWindow:NEAR
 EXTERN LoadIconA:NEAR
 EXTERN lstrcpy:NEAR
 EXTERN Shell_NotifyIconA:NEAR
 EXTERN ExitProcess:NEAR
 EXTERN GetModuleHandleA:NEAR
 EXTERN DialogBoxParamA:NEAR
 EXTERN EndDialog:NEAR
 EXTERN SendDlgItemMessageA:NEAR
 ShowWindow@8 = ShowWindow
 LoadIconA@8 = LoadIconA
 lstrcpy@8 = lstrcpy
 Shell_NotifyIconA@8 = Shell_NotifyIconA
 ExitProcess@4 = ExitProcess
 GetModuleHandleA@4 = GetModuleHandleA
 DialogBoxParamA@20 = DialogBoxParamA
 EndDialog@8 = EndDialog
 SendDlgItemMessageA@20 = SendDlgItemMessageA
ENDIF

; структуры
; структура сообщения
MSGSTRUCT STRUC
 MSHWND DD ?
 MSMESSAGE DD ?
 MSWPARAM DD ?
 MSLPARAM DD ?
 MSTIME DD ?
 MSPT DD ?
MSGSTRUCT ENDS

; структура для функции Shell_NotifyIcon
NOTI_ICON STRUC
 cbSize DWORD ?
 hWnd DWORD ?
 uID DWORD ?
 uFlags DWORD ?
 uCallbackMessage DWORD ?
 hIcon DWORD ?
 szTip DB 64 DUP (?)
NOTI_ICON ENDS

; файл tray.asm
.386P
; плоская модель
.MODEL FLAT, stdcall
include tray.inc
; директивы компоновщику для подключения библиотек
IFDEF MASM
 includelib c:\masm32\lib\user32.lib
 includelib c:\masm32\lib\kernel32.lib
 includelib c:\masm32\lib\shell32.lib
ELSE
 includelib c:\tasm32\lib\import32.lib
ENDIF
;————————-----------------------------------------

; сегмент данных
_DATA SEGMENT DWORD PUBLIC USE32 'DATA'
 MSG MSGSTRUCT <?>
 HINST DD 0 ; дескриптор приложения
 PA DB "DIAL1",0
 NOTI NOTI_ICON <0>
 TIP DB "Пример использования функции"
 DB "Shell_NotifyIcon",0
_DATA ENDS

;сегмент кода

_TEXT SEGMENT DWORD PUBLIC USE32 'CODE' START: ; получить дескриптор приложения PUSH 0 CALL GetModuleHandleA@4 MOV [HINST], EAX ;-------------------------------------- PUSH 0 PUSH OFFSET WNDPROC PUSH 0 PUSH OFFSET PA PUSH [HINST] CALL DialogBoxParamA@20 CMP EAX,-1 JNE KOL ; сообщение об ошибке KOL: ;-------------------------------------- PUSH 0 CALL ExitProcess@4 ;-------------------------------------- ; процедура окна ; расположение параметров в стеке ; [EBP+014Н] ; LPARAM ; [EBP+10Н] ; WAPARAM ; [EBP+0CH] ; MES ; [EBP+8] ; HWND WNDPROC PROC PUSH EBP MOV EBP,ESP PUSH EBX PUSH ESI PUSH EDI ;--------------- CMP DWORD PTR [EBP+0CH],WM_CLOSE JNE L1 PUSH 0 PUSH DWORD PTR [EBP+08H] CALL EndDialog@8 JMP FINISH L1: CMP DWORD PTR [EBP+0CH],WM_INITDIALOG JNE L2 JMP FINISH L2: CMP DWORD PTR [EBP+0CH],WM_SIZE JNE L3 CMP DWORD PTR [EBP+10H],SIZE_MINIMIZED JNE L3 ; здесь работа по установке иконки на системную панель MOV NOTI.cbSize,88 MOV EAX,DWORD PTR [EBP+8H] MOV NOTI.hWnd,EAX MOV NOTI.uFlags,FLAG MOV NOTI.uID,12 ; идентификатор иконки MOV NOTI.uCallbackMessage,2000 ; сообщение ; загрузить иконку из ресурсов PUSH 1 PUSH [HINST] CALL LoadIconA@8 ; скопировать текст всплывающего сообщения MOV NOTI.hIcon,EAX PUSH OFFSET TIP PUSH OFFSET NOTI.szTip CALL lstrcpy@8 ; поместить иконку PUSH OFFSET NOTI PUSH NIM_ADD CALL Shell_NotifyIconA@8 ; спрятать минимизированное окно PUSH SW_HIDE PUSH DWORD PTR [EBP+08H] CALL ShowWindow@8 JMP FINISH L3: ; сообщение от иконки на системной панели? CMP DWORD PTR [EBP+0CH],2000 JNE FINISH ; идентификатор нашей иконки? CMP WORD PTR [EBP+10H],12 JNE FINISH ; что произошло? двойной щелчок? CMP WORD PTR [EBP+14H],WM_LBUTTONDBLCLK JNE FINISH ; заполнить структуру MOV NOTI.cbSize,88 MOV EAX,DWORD PTR [EBP+8H] MOV NOTI.hWnd,EAX MOV NOTI.uFlags,NIF_ICON MOV NOTI.uID,12 ; идентификатор иконки MOV NOTI.uCallbackMessage,1000 ; сообщение ; удалить иконку PUSH OFFSET NOTI PUSH NIM_DELETE CALL Shell_NotifyIconA@8 ; восстановить окно PUSH SW_SHOWNORMAL PUSH DWORD PTR [EBP+08H] CALL ShowWindow@8 FINISH: MOV EAX,0 POP EDI POP ESI POP EBX POP EBP RET 16 WNDPROC ENDP _TEXT ENDS END START

Рис. 3.5.1. Демонстрация процедуры помещения иконки на системную панель.


Вход на сайт
Поиск
Календарь
«  Июль 2025  »
ПнВтСрЧтПтСбВс
 123456
78910111213
14151617181920
21222324252627
28293031
Архив записей
Наш опрос
Как Вам удобнее??
Всего ответов: 341
Мини-чат
Друзья сайта
  • Официальный блог
  • Сообщество uCoz
  • FAQ по системе
  • Инструкции для uCoz
  • Статистика

    Онлайн всего: 1
    Гостей: 1
    Пользователей: 0