Example WM_DEVICECHANGE

Everything else that doesn't fall into one of the other PB categories.
AZJIO
Addict
Addict
Posts: 1312
Joined: Sun May 14, 2017 1:48 am

Example WM_DEVICECHANGE

Post by AZJIO »

Example showing the connection and disconnection of a USB flash drive.

Code: Select all

EnableExplicit

#Windows_0 = 0
#SysTrayIcon_0 = 0
#Menu = 0

#TimerStart = 1
#TimeMSEC = 1400 ; таймер 400 миллисекунд

Enumeration
	#About
	#Exit
EndEnumeration


; #q$ = Chr(34)
#StartDisk = 2		 ; номер диска, от которого начинать вычисление, то есть диски "A" и "B" будут пропущены
Global ExeDir$ ; путь где располагается программа
Global hWin_0 ; дескриптор скрытого окна программы
Global h_ico_0 ; дескриптор иконки
Global h_ico_1 ; дескриптор иконки
Global h_ico_2 ; дескриптор иконки
Global drives_avail ; доступные диски в виде флагов
Global MarkFileName$ ; маркерный файл на диске, дающий диску особый статус использования
Global ActiveDiskMarked = 26 ; диск, на котором обнаружен файл-маркер, 26 - за гранью, так как диски от 0 до 25.

; Перед тем как выполнить какой либо код исключаем повторный запуск программы
; здесь USB459345 некая комбинация случайных символов, которая не может случайно использоваться кем-то и создать проблему запуска другой программе.
Define *a = CreateSemaphore_(#Null, 0, 1, "USB459345")
If *a And GetLastError_() = #ERROR_ALREADY_EXISTS
	CloseHandle_(*a)
	MessageRequester("","The program is already running") ; необязательно, но можно сообщить, что прога уже запущена, ну или вызвать батник обновления.
	End
EndIf

; Получаем переданный параметр программе (имя файла-маркера)
MarkFileName$ = ProgramParameter()
If Not Asc(MarkFileName$) ; если имя маркера не задан, то по умолчанию задаём... или завершение программы
	MarkFileName$ = "Soft"
; 	End
EndIf

ExeDir$ = GetCurrentDirectory()
drives_avail = GetLogicalDrives_()

Procedure Exit()
	RemoveSysTrayIcon(#SysTrayIcon_0)
	CloseWindow(#Windows_0)
	End
EndProcedure

Procedure About()
	MessageRequester("About", "Author AZJIO")
EndProcedure

Procedure Add_drive(Mask.l)
	Protected i, CurLetter$
	For i = #StartDisk To 25
		If ((Mask >> i) & 1) ; проверить каждый флаг
			CurLetter$ = Chr(i + 65)
; 			Реакция при вставке флешки, при наличии маркер-файла
			If FileSize(CurLetter$ + ":\" + MarkFileName$) >= 0
				ActiveDiskMarked = i
				AddSysTrayIcon(#SysTrayIcon_0, hWin_0, h_ico_0)
				AddWindowTimer(#Windows_0, #TimerStart, #TimeMSEC)
				Break ; выпрыгиваем найдя маркер-файл, не проверяя другие разделы физического диска
			EndIf
		EndIf
	Next
EndProcedure

Procedure Del_drive(Mask.l)
	Protected i, CurLetter$
	For i = #StartDisk To 25
		If ((Mask >> i) & 1) ; проверить каждый флаг
			CurLetter$ = Chr(i + 65)
; 			Реакция при извлечении флешки
			If ActiveDiskMarked = i
				ActiveDiskMarked = 26
				AddSysTrayIcon(#SysTrayIcon_0, hWin_0, h_ico_1)
				AddWindowTimer(#Windows_0, #TimerStart, #TimeMSEC)
			EndIf
		EndIf
	Next
EndProcedure

Procedure WinCallback(hWnd, uMsg, wParam, lParam)
	Protected Result = #PB_ProcessPureBasicEvents, Mask, Drive.s,  *pDBHDR.DEV_BROADCAST_HDR, *pDBV.DEV_BROADCAST_VOLUME
	Protected tmp
	Select uMsg
; 		Case #WM_UNINITMENUPOPUP
; 			Debug "PopupMenu был закрыт."
; 		Case #WM_QUERYENDSESSION ; Событие завершение сеанса винды
; 			DeleteDirectory(GetEnvironmentVariable( "TEMP"), "", #PB_FileSystem_Recursive | #PB_FileSystem_Force) ; Очистка папки TEMP
; 			ProcedureReturn #True
	
		Case #WM_DEVICECHANGE ; Изменение при подключении внешних дисков.
			Result = #True
			Select wParam
				Case #DBT_DEVICEARRIVAL, #DBT_DEVICEREMOVECOMPLETE
					*pDBHDR.DEV_BROADCAST_HDR=lParam
					If *pDBHDR\dbch_devicetype = #DBT_DEVTYP_VOLUME
						*pDBV.DEV_BROADCAST_VOLUME=lParam
						Mask = *pDBV\dbcv_unitmask

						Select wParam
							Case #DBT_DEVICEARRIVAL
								; Debug Bin(drives_avail)
								; Debug Bin(Mask)
								tmp = drives_avail
								drives_avail | Mask
								If tmp <> drives_avail
									Add_drive(Mask)
								EndIf
							Case #DBT_DEVICEREMOVECOMPLETE
								drives_avail ! (Mask & drives_avail)
								Del_drive(Mask)
						EndSelect
					EndIf
			EndSelect
	EndSelect
	ProcedureReturn Result
EndProcedure


CatchImage(0, ?Icon0)
CatchImage(1, ?Icon1)

h_ico_0 = ImageID(0)
h_ico_1 = ImageID(1)

hWin_0 = OpenWindow(#Windows_0, 0, 0, 200, 20, "", #PB_Window_Invisible)
h_ico_2 = GetClassLongPtr_(hWin_0, #GCL_HICON)
AddSysTrayIcon(#SysTrayIcon_0, hWin_0, h_ico_2)
SysTrayIconToolTip(#SysTrayIcon_0, "Example")

CreatePopupMenu(#Menu)
MenuItem(#About, "About")
MenuItem(#Exit, "Exit")

BindMenuEvent(#Menu, #About, @About())
BindMenuEvent(#Menu, #Exit, @Exit())
SetWindowCallback(@WinCallback())


Repeat
	Select WaitWindowEvent()
		Case #PB_Event_Timer
			If EventTimer() = #TimerStart
				AddSysTrayIcon(#SysTrayIcon_0, hWin_0, h_ico_2)
				RemoveWindowTimer(#Windows_0, #TimerStart)
			EndIf
		Case #PB_Event_SysTray
			Select EventType()
				Case #PB_EventType_LeftClick, #PB_EventType_RightClick
					DisplayPopupMenu(#Menu, hWin_0)
			EndSelect
		Case #PB_Event_CloseWindow
			Exit()
	EndSelect
ForEver
Exit()


DataSection
	Icon0:
	IncludeBinary "0.ico"
	Icon0end:
	Icon1:
	IncludeBinary "1.ico"
	Icon1end:
EndDataSection