Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Any way to detect Bluetooth device status?


  • Please log in to reply
2 replies to this topic
jbscout
  • Members
  • 22 posts
  • Last active:
  • Joined: 17 Apr 2011
Is there any program/APi/DLL to detect/control Bluetooth?

Specifically I want to be able to:
* detect if BT is enabled/disabled
* enable the BT adapter (so BT devices may connect)
* get a list of connected devices (or at least check that device X is connected via BT)

[WRONG]
The BT is an internal laptop device and therefore there is no 0x219 WM_DEVICECHANGE message (from <!-- m -->http://www.autohotke...MessageList.htm<!-- m -->).
[/WRONG]

Plus I want to see if the devices are already connected/enabled, not if they change. (Of course I could be too stupid to know how to use this correctly.)

From a search of the forums it appears that everything BT is either related to HIDs or Windows Mobile Phones. I want to check if a BT headset is connected to the laptop, not read data/keystrokes from it. Right now I am forced to pop-up a MsgBox asking the user to check and provide me with the info.
I'll still need a MsgBox to get the user to turn on their BT headphones (flip the headset's physical ON switch). But I am hoping to skip the 1st MsgBox and having the user right-click the BT system tray icon, hit "Turn Adapter On" etc.

Other suggestions for accomplishing this are appreciated.

Thanks

jbscout
  • Members
  • 22 posts
  • Last active:
  • Joined: 17 Apr 2011
I have answered my own question.
I'll publish the results here for anyone having this problem in the future.

Here is what I figured out:
1) By using a 3rd party tool (BluetoothView.exe v1.50 from <!-- m -->http://www.nirsoft.n...oth_viewer.html<!-- m -->), I can get an XML list of all Bluetooth devices associated with this PC.
1a) from this I can tell if the BT Adapter is turned on or not
1b) from this I can tell if a BT Device is connected or not.

2) I have no clue how to turn on/off the adapter or a device programmatically.

3) I can also use the WM_DEVICECHANGE message to see if the device status changes (although this isn't what my script needed).
However doing this requires that I know the GUID Windows gave the device on install. So, setting this up requires a good deal of trial and error to determine the proper GUID.

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
#Persistent
#SingleInstance force
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

/*
;==============================================================================
;========== What This Script Does  ============================================
;==============================================================================
; This script makes sure I turn on & setup my VoIP softphone for work.
; It checks that the Bluetooth Adapter is turned on and one of my Bluetooth headphones is connected to the PC.
; If so, it starts the VoIP softphone and nags you to set the corrcet option in the VoIP softphone
;
; Should be placed in the StartUp folder (%AppData%\Microsoft\Windows\Start Menu\Programs\Startup)
;
; REQUIRED:
;   * you need the tool BluetoothView.exe from http://www.nirsoft.net/utils/bluetooth_viewer.html
;   * you need the MAC address of the BT device you're trying to detect (run BluetoothView.exe from Windows to get this)
;
; CREDITS:
;   * NirSoft for the 3rd party tool
;   * fincs for the XML reader (http://www.autohotkey.com/forum/viewtopic.php?p=387245#387245)
;   * dmatch & Shaun4477 for showing me how to dynamically monitor adding/removing devices (which I ultimatly didn't use)  from http://www.autohotkey.com/forum/topic75475.html
;==============================================================================
*/




;==============================================================================
;========== Config Variables===================================================
;==============================================================================
; Times of Day/Days of the Week when this script will run
StartScriptTime=060000 ; hhmmss, start running the script (at work)
StopScriptTime=170000  ; hhmmss, stop running the script (off work)
RunScriptDays=23456 ; days of the week in which the script should run (e.g., Mon-Fri); 1 (Sun) and & 7 (Sat) are left out, so, no running the script.

; VoIP softphone info
VoipProcessName=eyeBeam.exe ; yes it is case sensative
VoipProgramFullPath := "C:\Program Files (x86)\CounterPath\eyeBeam 1.5\eyeBeam.exe"

; Bluetooth devices (listed in order of preference)
; You'll need to run the 3rd party tool (outside of this script) to get te MAC Address of each Bluetooth device you wish to test for.
; NB: Arrays in AHK are a series of sequentially numbered variables.  To change the Array order, change the array numbers (didn't find a automatic way to detect array size).
BT_Device_MAC_ArraySize=2
BT_Device_MAC_Array1=00:21:3c:54:31:31 ; Jawbone ICON 2 (new device for PC)
BT_Device_MAC_Array2=00:21:3c:43:b9:13 ; Jawbone ICON (old device for iPhone)

XMLFileName := "bluetooth_report.xml"
; XMLFileName := "bluetooth_report - Off.xml"
; XMLFileName := "bluetooth_report - On Disconnected.xml"
; XMLFileName := "bluetooth_report - On Connected 1.xml"


; -----------------------------------------------------------------------------
; Main Script
; -----------------------------------------------------------------------------

; Global variables
xmlData=""
DEBUG := false
OnExit, ExitSub

; Check Time of day and Day of Week are corrcet for the script to run
if (shouldScriptRun())
{
	TimeToWaitSecs := 5*60 ; let PC finish starting
	askToStart(%TimeToWaitSecs%)
	GoSub Main_StartMicHeadset
	GoSub Main_StartSoftPhone
	GoSub Main_ChangeAudioInput
	
	ExitApp
}
else
{
	infoMsgBox("You have established (in the config variables) that `nit is the wrong time of day or day of the week to run this script.", 15)
	; Sleep the script until it is time to work again (e.g., if I wake up early and start the PC before work starts)
	GoSub Main_GoToSleep ; really only sleeps the script until the next time of day (not day of week), a re-used piece of code
	; Reload script in order to get back to main IF statement (brutal but effective)
	GoSub Main_Reload
}
ExitApp

; -----------------------------------------------------------------------------
; Subroutines
; -----------------------------------------------------------------------------
shouldScriptRun()
{
	global DEBUG
	if (DEBUG) 
	{
		return true 
	}

	; define global variables (AHK can't see globals within a function unless declared)
	global StartScriptTime, StopScriptTime
	global RunScriptDays

	correctHour := shouldScriptRunHourBased(StartScriptTime, StopScriptTime)
	correctDay := shouldScriptRunDayBased(RunScriptDays)
	
	return (correctHour && correctDay)
}

shouldScriptRunHourBased(StartScriptTime=080000, StopScriptTime=170000)
{
	global DEBUG
	if (DEBUG) 
	{
		return true 
	}
	
	; default values
	shouldScriptRun := false
	ShortTimeNow := A_Hour A_Min A_Sec

	; adjust the timings depending on whether the stop period crosses midnight
	if( (StartScriptTime < StopScriptTime) ) ; stop period all in same day
	{
		shouldScriptRun := ( (StartScriptTime < ShortTimeNow) && (ShortTimeNow < StopScriptTime) )
	}
	else  ; period crosses midnight
	{
		shouldScriptRun := ( (StopScriptTime > ShortTimeNow) || (ShortTimeNow > StartScriptTime) )
	}
	
	return shouldScriptRun
}

shouldScriptRunDayBased(RunScriptDays=23456)
{
	global DEBUG
	if (DEBUG) 
	{
		return true 
	}
	
	; real (non-debug) script
	shouldScriptRun := InStr(RunScriptDays, A_WDay)

	return shouldScriptRun
}

isBTDeviceConnected(BTDeviceMACAddress = "00:21:3c:54:31:31")
{
	global xmlData
	returnResult := false
		debugMsgBox("isBTDeviceConnected", xmlData )

	; XPath
	xmlDoc := loadXML(xmlData)
	queryString = /bluetooth_devices_list/item[address="%BTDeviceMACAddress%"]/connected
	; queryString2 := "/bluetooth_devices_list/item[address=""00]/connected"
	; msgbox Checking BT %BTDeviceMACAddress% `n %queryString% `n %queryString2%
	queryResult := xmlDoc.selectSingleNode(queryString).text
	if(queryResult = "Yes")
	{
		returnResult := true
	}
	else
	{
		returnResult := false
	}
		debugMsgBox("isBTDeviceConnected", BTDeviceMACAddress "`n|" queryResult "| " returnResult)
	return %returnResult%
}

getBTDeviceNameByMACAddress(BTDeviceMACAddress = "00:21:3c:54:31:31")
{
	global xmlData
	returnResult := false

	; XPath
	xmlDoc := loadXML(xmlData)
	queryString = /bluetooth_devices_list/item[address="%BTDeviceMACAddress%"]/device_name
	queryResult := xmlDoc.selectSingleNode(queryString).text
		debugMsgBox("getBTDeviceNameByMACAddress", BTDeviceMACAddress "`n|" queryResult "| ")
	return %queryResult%
}

isBTAdapterTurnedOn()
{
	global xmlData
	returnResult := false

		debugMsgBox("isBTAdapterTurnedOn", xmlData )
	; XPath
	xmlDoc := loadXML(xmlData)
	queryResult := xmlDoc.selectSingleNode("/bluetooth_devices_list").hasChildNodes
	if( queryResult )
	{
		; if the the device list includes any devices, the adapter is turned on
		returnResult := true
	}
	else
	{
		; if the the device list includes no devices, the adapter is turned off (or maybe no devices are associated with this PC?  But that isn't my case)
		returnResult := false
	}
		debugMsgBox("isBTAdapterTurnedOn", "|" queryResult "| " returnResult)
	return %returnResult%
}

askToStart(timeoutSecs = 30)
{	
	MsgBox, 4,, Do you want AHK to start the VoIP softphone?, %timeoutSecs%
	IfMsgBox, Yes
	{
		return ; run rest of script
	}
	IfMsgBox, TIMEOUT ; same as Yes
	{
		return ; run rest of script
	}
	IfMsgBox, No
	{
		ExitApp ; quit the app
	}			
	return
}

createBluetoothXMLFile(XMLFileName)
{
	ProgramToRun_exePath=C:\Users\jbscout\My Dropbox\Programs\BluetoothView.exe ; http://www.nirsoft.net/utils/bluetooth_viewer.html
	ProgramToRun_processName=BluetoothView.exe
	
	; msgbox Checking that %ProgramToRun_processName% isn't running
	Process, Wait, %ProgramToRun_processName%, 10 ; check to see if program is running (err==0, not running; err=PID if running), wait X seconds
	{
		If (ErrorLevel <> 0) ; If it is running, PID if running
		{
			Process, Wait, %ProgramToRun_processName%, 30 ; wait 30 seconds for the running process to close
			{
				If (ErrorLevel <> 0) ; If it is running, PID if running
				{
					Process, Close, %ProgramToRun_processName%  ; and now shutdown/kill the process if it is running 
				}
			}
		}
	}
	
	; msgbox About to run %ProgramToRun_exePath%
	wasFileXMLFileCreationSuccessfull := false
	TimeBeforeProgramRun := A_Now
	IfExist, %ProgramToRun_exePath% ; check that the program actually exists
	{
		RunWait, %ProgramToRun_exePath% /sxml %XMLFileName%
		{
			; msgbox Checking that %XMLFileName% exists
			Loop, 60 ; arbitrary loop timeout fail-safe
			{
				IfExist, %XMLFileName%
				{
					FileGetTime, XMLFileTime, %XMLFileName%
					if(TimeBeforeProgramRun < XMLFileTime) ; confirm that the XMLFIle was newly created/modified
					{
						wasFileXMLFileCreationSuccessfull := true
						break
					}
					else 
					{
						; an old file exists, wait and see if the new file has been created in the interm
						Sleep 1000
					}
				}
				else
				{
					; wait and see if the new file has been created in the interm
					Sleep 1000
				}
			}
			Process, Close, %ProgramToRun_processName%  ; and now shutdown/kill the process if it is running 
		}
	}
	return	wasFileXMLFileCreationSuccessfull
}

readBluetoothXMLFile(XMLFileName)
{
	global xmlData
	
	FileRead, xmlDataTmp, %XMLFileName%
	if not ErrorLevel  ; Successfully loaded.
	{
		xmlData := RegExReplace(xmlDataTmp, "%_", "precentage_")  ; the "%_detection" tag causes XML errors; replace the % carachter
		; msgbox % xmlData

		return true
	}
	else
	{
		msgbox, 0, , File read error %ErrorLevel% `n %XMLFileName%
		
		return false
	}
}

loadXML(ByRef data)
{
   o := ComObjCreate("MSXML2.DOMDocument.6.0")
   o.async := false
   o.loadXML(data)
   return o
}

debugMsgBox(mbxTitle, mbxText)
{
	global DEBUG
	
	if (DEBUG)
	{
		MsgBox, 0, %mbxTitle%, %mbxText%
	}
	return
}

infoMsgBox(mbxText, mbxTimeout=0)
{
	if ( mbxTimeout > 0 )
	{
		MsgBox, 0,, %mbxText%, %mbxTimeout%
	}
	else
	{
		MsgBox, 0,, %mbxText%
	}
	return
}

reloadableMsgBox(mbxText)
{
	SetTimer, MsgBox_ChangeButtonNames, 50 ; Changes the button names to something better (changes them very fast)
	MsgBox, 5,, %mbxText% 
	SetTimer, MsgBox_ChangeButtonNames, Off ; Should have already been turned off in the label/subroutine, but ...
	IfMsgBox, Retry
	{
		; Reload script in order to get back to main IF statement (brutal but effective)
		GoSub Main_Reload
		return ; run rest of script
	}
	IfMsgBox, Cancel
	{
		ExitApp ; quit the app
	}			
	return
}

; -----------------------------------------------------------------------------
; Labels
; -----------------------------------------------------------------------------
Main_StartBlueTooth:
	if isBTAdapterTurnedOn()
	{
		infoMsgBox("Bluetooth Adapter is running.", 5)
	}
	else
	{
		reloadableMsgBox("Please turn on the Bluetooth Adapter.")
	}
return

Main_StartMicHeadset:
	; Load BT status via 3rd party tool/exe
	infoMsgBox("Creating Bluetooth XML File.", 5)
	createBluetoothXMLFile(XMLFileName)
	infoMsgBox("Reading Bluetooth XML File.", 5)
	readBluetoothXMLFile(XMLFileName)

	; Check each BT device in a predefined array to see if at least one of them is connected
	areAnyBTDevicesConnected := false
	Loop %BT_Device_MAC_ArraySize%
	{
		if ( isBTDeviceConnected(BT_Device_MAC_Array%A_Index%) ) 
		{
			areAnyBTDevicesConnected := true
			BTDeviceAddress := BT_Device_MAC_Array%A_Index%
			BTDeviceName := getBTDeviceNameByMACAddress(BT_Device_MAC_Array%A_Index%)
			mbxString = A device is connected.`n`nName: %BTDeviceName%`nMAC Address: %BTDeviceAddress%
			infoMsgBox(mbxString, 5)
			return
		}
	}
	; if nothing is connected take remedial action
	if( !areAnyBTDevicesConnected )
	{
		GoSub Main_StartBlueTooth
		reloadableMsgBox("Please connect a Bluetooth Headset.")
	}
return



Main_StartSoftPhone:
	Process, Wait, %VoipProcessName%, 10 ; check to see if program is running (err==0, not running; err=PID if running), wait X seconds
	{
		If (ErrorLevel = 0) ; If it is not running, PID if running
		{
			Run,%VoipProgramFullPath%
			Sleep, 3000 ; give it time to start before moving on
		}
		else
		{
			; MsgBox, 4,, VoIP softphone is running.
		}
	}
return

Main_ChangeAudioInput:
	; figure out how to do this programatically at some point
	infoMsgBox("Have you set the VoIP softphone to the correct audio settings?")
return

Main_GoToSleep:
	; setup some timing variables
	startScriptDate := A_Year A_Mon A_MDay   ; YYYYMMDD format, example 20090206 = Feb 6 2009
	startTimeFull := startScriptDate StartScriptTime
	ShortTimeNow := A_Hour A_Min A_Sec
	if (ShortTimeNow > StartScriptTime) ; start up again tomorrow
	{
		startTimeFull += 1 , Days ; push start time till tomorrow
	}

	; find number of seconds to wait from NOW until target time
	timeToWait := A_Now         
	timeToWait -= startTimeFull, seconds
	timeToWait := -1 * timeToWait
	Sleep % timeToWait * 1000   ; set timer to fire (once) until sleep time is over
Return

Main_Reload:
	Reload
	Sleep 2000 ; If successful, the reload will close this instance during the Sleep, so the line below will never be reached.
	MsgBox, 4,, The script could not be reloaded. Would you like to open it for editing?
	IfMsgBox, Yes, Edit
return

MsgBox_ChangeButtonNames:	; customizes the MsgBox button names
	IfWinNotExist, %A_ScriptName%
		return  ; Keep waiting for MsgBox to be displayed
	SetTimer, MsgBox_ChangeButtonNames, off 
	WinActivate 
	ControlSetText, Button1, &Continue  ; Yes button
	ControlSetText, Button2, &Quit ; No button
return

ExitSub:
	IfExist, %XMLFileName%
	{
		if (!DEBUG) 
		{
			FileDelete, %XMLFileName%
		}
	}
	ExitApp
return

/*
;==============================================================================
;========== Version History ===================================================
;==============================================================================
; v0.9.1 - 2011-09-02
;     * added "day of week" checking to not run on weekends
;
; v0.9 - 2011-09-01
;     * switched to XML file (BluetoothView.exe /try_to_connect <MAC Addr> was unreliable.)
;     * general alpha bug fixes
;     * various GUI improvements
;
; v0.8 - 2011-08-30
;     * initial "good enough" version
;==============================================================================
*/


I'll also post my test script for detecting when a given device's status has changed. Maybe someday I'll add the removal monitoring to my script to detect when the BT Headset runs out of power (which I assume would cause the device to be removed from the system).
* I got this from dmatch (modified by me for testing) , who in turn modified it from a much more elaborate script by Shaun4477. Thank you, dmatch.
* To use this you need the GUID Windows assigns the device on install. This is a bit of a PITA as a device can have multiple GUIDs/instances (for each "role" the device supports).
* Here are dmatch's helpful instructions to me:

The first thing to do is get that script posted in the thread you referenced [http]. Run the script without your device plugged in (turned off). Then when
you plug in (or turn on) your device you will see a bunch of info in the bottom list in the script. For some reason there will probably be multiple
devices listed as having just been plugged in even though you only plugged in a single device. I suspect (I'm no guru Wink) that there is more than
1 way to interface with a device and each way needs to be added as if it were a device.

In the bottom list find the first dbcc_name= line. Here is one for a USB Flash Drive that I plugged in:
Quote:
dbcc_name = \\?\USB#Vid_0930&Pid_6544#0710020707203#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
You will need to get the GUID (DeviceID) from this line for use in the AHK script that will be used to detect the device. It is between braces { }.

The script is as follows:
; This script was orignally written by dmatch (Thank You) and editted for testing purposes by me.
; dmatch based this off of the original monitoring script from http://www.autohotkey.com/forum/topic75475.html
; dmatch's script was for sharing a specific USB drive.  I wanted to monitor a Bluetooth headset/mic.
; Ultimatly, active monitoring was not what I wanted in my script, but this is how you'd do it.


;Detect when specific hardware is attached and share
	; You need to get the GUID for the device you're monitoring.  
	; To hunt down this GUID down use the monitoring program found at 
	; http://www.autohotkey.com/forum/topic75475.html
DeviceID={0850302A-B344-4FDA-9BE9-90576B8D46F0} ; BT Adapter
; DeviceID={6994AD04-93EF-11D0-A3CC-00A0C9223196} ; BT Headset Jawbone 2
; DeviceID={24DF01A9-3E4F-4C9F-9F66-5AA8AB14F8F4} ; BT Headset ???
#persistent
#SingleInstance force

; Monitor for WM_DEVICECHANGE
OnMessage(0x219, "MsgMonitor")

hWnd := GetAHKWin()

DEVICE_NOTIFY_WINDOW_HANDLE := 0x0
DBT_DEVTYP_DEVICEINTERFACE  := 5
DEVICE_NOTIFY_ALL_INTERFACE_CLASSES := 0x00000004
DBT_DEVICEARRIVAL          := 0x8000
DBT_DEVICEREMOVECOMPLETE   := 0x8004


VarSetCapacity(DevHdr, 32, 0) ; Actual size is 29, but the function will fail with less than 32
NumPut(32, DevHdr, 0, "UInt") ; sizeof(_DEV_BROADCAST_DEVICEINTERFACE) (should be 29)
NumPut(DBT_DEVTYP_DEVICEINTERFACE, DevHdr, 4, "UInt") ; DBT_DEVTYP_DEVICEINTERFACE
;PutGuid(&DevHdr + 8, "{1AD9E4F0-F88D-4360-BAB9-4C2D55E564CD}")
Addr := &DevHdr
Flags := DEVICE_NOTIFY_WINDOW_HANDLE|DEVICE_NOTIFY_ALL_INTERFACE_CLASSES
Msg = %Msg%RegisterDeviceNotification(%hWnd%, %Addr%, %Flags%)`r`n
Ret := DllCall("RegisterDeviceNotification", "UInt", hWnd, "UInt", Addr, "UInt", Flags)
if(!Ret){
   MsgBox, Unable to RegisterDeviceNotification!
   ExitApp
}
return

MsgMonitor(wParam, lParam, msg)
{
   global DBT_DEVICEARRIVAL, DBT_DEVICEREMOVECOMPLETE, DBT_DEVTYP_DEVICEINTERFACE, DeviceID
   if (wParam == DBT_DEVICEARRIVAL)
   {

      ; lParam points to a DEV_BROADCAST_HDR structure
      dbch_size       := NumGet(lParam+0, 0, "UInt")
      dbch_devicetype := NumGet(lParam+0, 4, "UInt")
      if (dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
      {
         ; lParam points to a DEV_BROADCAST_DEVICEINTERFACE structure
         dbcc_name := GetString(lParam+28)
         if(InStr(dbcc_name, DeviceID)){
            msgbox, added ; do something useful (dmatch had a SetTimer going to a label in order to get out of the MsgMonitor ASAP)
         }
      }
   } else if (wParam == DBT_DEVICEREMOVECOMPLETE)
   {

      ; lParam points to a DEV_BROADCAST_HDR structure
      dbch_size       := NumGet(lParam+0, 0, "UInt")
      dbch_devicetype := NumGet(lParam+0, 4, "UInt")
      if (dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
      {
         ; lParam points to a DEV_BROADCAST_DEVICEINTERFACE structure
         dbcc_name := GetString(lParam+28)
         if(InStr(dbcc_name, DeviceID)){  
            msgbox, removed ; do something useful (dmatch had a SetTimer going to a label in order to get out of the MsgMonitor ASAP)
         }
      }
   } 
   
}


GetAHKWin()
{
    Gui +LastFound
    hwnd := WinExist()
    return hwnd
}

GetString(Addr)
{
   OutString := ""
   VarSetCapacity(OutString, 1024, 0)
   Loop {
      Char := *Addr+0
      ;MsgBox, %Char%
      if (Char == 0)
         break
      OutString .= Chr(Char)
      Addr ++
   }
   return OutString
}


maeiky
  • Members
  • 2 posts
  • Last active: Feb 17 2012 03:52 AM
  • Joined: 29 Dec 2011
I found a better way using registry key. I have used regshot to analyse key change when I connect my bluethoot mouse. Then I can change the mouse speed because my Synaptics TouchPad is too slow for my mouse and the mouse too fast for the pad.

This reg key change to 1 when I connect the mouse :

HKLM\SYSTEM\CurrentControlSet\services\mouhid\Enum\Count: 0x00000001

Here is my script to change bluetooth mouse speed :

OnExit, ExitSub
#SingleInstance force
; Pointer Speed (1-20)
PadSpeed = 20
MouseSpeed = 4

; Enhance Pointer Precision
PadEnhance = 1
MouseEnhance = 1

; Precision Thresholds
PadThreshold1 = 6
PadThreshold2 = 10
MouseThreshold1 = 6
MouseThreshold2 = 10

; Use a tray icon?
TrayIcon = 1

; Tray Icons
; If you want the tray icon to reflect the current settings, enter a valid
; PadIcon and PadIconGroup. To use the only standard AutoHotkey icon, comment
; out all the icon locations.

MouseIcon = %A_WinDir%\system32\main.cpl
MouseIconGroup = 1
MouseName = Mouse

; The likely location of the Synaptics Touch Pad icon.
PadIcon = %ProgramFiles%\Synaptics\SynTP\SynTPEnh.exe
PadIconGroup = 1
PadName = Touch Pad

If !TrayIcon
   Menu, Tray, NoIcon
   
; Constants
; Read more at the following:
; http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/systemparametersinfo.asp
; http://www.pinvoke.net/search.aspx?search=SPI&namespace=%5BAll%5D
SPI_GETMOUSE =      0x0003
SPI_SETMOUSE =      0x0004
SPI_GETMOUSESPEED =   0x0070
SPI_SETMOUSESPEED =   0x0071

LastVar = 0;
Loop{
	RegRead, OutputVar, HKEY_LOCAL_MACHINE, SYSTEM\CurrentControlSet\services\mouhid\Enum, Count
	;MsgBox, Program files are in: %OutputVar%

	if(LastVar != OutputVar){
		LastVar = OutputVar;
		if(OutputVar == 1){
			MousePresent := TRUE
			Gosub, ChangeSettings
		}else{
			MousePresent := FALSE
			Gosub, ChangeSettings
		}
	}
	Sleep 500
}



ChangeSettings:
   If MousePresent
   {
      CurrentName = %MouseName%
      DeviceSpeed = %MouseSpeed%
      DeviceEnhance = %MouseEnhance%
      DeviceThreshold1 = %MouseThreshold1%
      DeviceThreshold2 = %MouseThreshold2%
      If TrayIcon and FileExist(MouseIcon)
         Menu, Tray, Icon, %MouseIcon%, %MouseIconGroup%
      Menu, Tray, Tip, Current Pointer Settings: %CurrentName%
   }
   Else
   {
      CurrentName = %PadName%
      DeviceSpeed = %PadSpeed%
      DeviceEnhance = %PadEnhance%
      DeviceThreshold1 = %PadThreshold1%
      DeviceThreshold2 = %PadThreshold2%
      If TrayIcon and FileExist(PadIcon)
         Menu, Tray, Icon, %PadIcon%, %PadIconGroup%
      Menu, Tray, Tip, Current Pointer Settings: %CurrentName%
   }

   VarSetCapacity(DeviceArray, 12, 0)
   InsertInteger(DeviceThreshold1, DeviceArray, 0)   ; Reg. Value MouseThreshold1
   InsertInteger(DeviceThreshold2, DeviceArray, 4)   ; Reg. Value MouseThreshold2
   InsertInteger(DeviceEnhance, DeviceArray, 8)      ; Reg. Value MouseSpeed

   InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4)
   ; The caller must ensure that pDest has sufficient capacity.  To preserve any existing contents in pDest,
   ; only pSize number of bytes starting at pOffset are altered in it.
   {
      Loop %pSize%  ; Copy each byte in the integer into the structure as raw binary data.
         DllCall("RtlFillMemory", "UInt", &pDest + pOffset + A_Index-1, "UInt", 1, "UChar", pInteger >> 8*(A_Index-1) & 0xFF)
   }

   ; Keep this here for future reference.
   ; DllCall("SystemParametersInfo", UInt, SPI_GETMOUSESPEED, UInt, 0, UIntP, SpeedCurrent, UInt, 0)

   ; Change the pointer speed.
   DllCall("SystemParametersInfo", UInt, SPI_SETMOUSESPEED, UInt, 0, UInt, DeviceSpeed, UInt, 1)
   ; Change the pointer precision settings.
   DllCall("SystemParametersInfo", UInt, SPI_SETMOUSE, UInt, 0, Str, DeviceArray, UInt, 1)
Return


ExitSub:
	MousePresent := FALSE
	Gosub, ChangeSettings
ExitApp