Logitech display include file (for G15 keyboard, etc)

Windows specific forum
User avatar
DoubleDutch
Addict
Addict
Posts: 3220
Joined: Thu Aug 07, 2003 7:01 pm
Location: United Kingdom
Contact:

Logitech display include file (for G15 keyboard, etc)

Post by DoubleDutch »

Here is an include file for writing programs for Logitech devices that have screens, eg the G15 keyboard.

Code: Select all

; lgLcd.pbi 

; Main Include for playing with the Logitech Display devices such as the G15 Keyboard
; You need to copy the 'lgLcd.lib' (v1.03 or above) to the same dir as this Header. 
; Based upon lglcd.h (c)Logitech & G15_Header.pbi (c)HeX0R 
; Updated by DoubleDutch

; Invalid handle definitions 
#LGLCD_INVALID_CONNECTION=-1 
#LGLCD_INVALID_DEVICE=-1 

; Soft-Button masks 
#LGLCDBUTTON_BUTTON0	=1<<0
#LGLCDBUTTON_BUTTON1	=1<<1
#LGLCDBUTTON_BUTTON2	=1<<2
#LGLCDBUTTON_BUTTON3	=1<<3

Structure lgLcdDeviceDesc 
	Width.l 
	Height.l 
	Bpp.l 
	NumSoftButtons.l 
EndStructure

Structure lgLcdDeviceDescEx
	deviceFamilyId.l
	deviceDisplayName.c[#MAX_PATH]
	Width.l
	Height.l
	Bpp.l
	NumSoftButtons.l
	Reserved1.l
	Reserved2.l
EndStructure

; lgLcdBitmap 
#LGLCD_BMP_FORMAT_160x43x1=1
#LGLCD_BMP_WIDTH=160
#LGLCD_BMP_HEIGHT=43

Structure lgLcdBitmapHeader 
	Format.l 
EndStructure

Structure lgLcdBitmap160x43x1 
	hdr.lgLcdBitmapHeader 
	pixels.b[#LGLCD_BMP_WIDTH*#LGLCD_BMP_HEIGHT] 
EndStructure 

; Priorities 
#LGLCD_PRIORITY_IDLE_NO_SHOW=0
#LGLCD_PRIORITY_BACKGROUND=64
#LGLCD_PRIORITY_NORMAL=128
#LGLCD_PRIORITY_ALERT=255

Macro LGLCD_SYNC_UPDATE(priority) 
	($80000000|priority) 
EndMacro

Macro LGLCD_SYNC_COMPLETE_WITHIN_FRAME(priority) 
	($c0000000|priority) 
EndMacro

Macro LGLCD_ASYNC_UPDATE(priority) 
	priority 
EndMacro

; Foreground mode for client applications
#LGLCD_LCD_FOREGROUND_APP_NO=#False
#LGLCD_LCD_FOREGROUND_APP_YES=#True

; Device family definitions
#LGLCD_DEVICE_FAMILY_KEYBOARD_G15			=1<<0
#LGLCD_DEVICE_FAMILY_SPEAKERS_Z10			=1<<1
#LGLCD_DEVICE_FAMILY_JACKBOX					=1<<2
#LGLCD_DEVICE_FAMILY_LCDEMULATOR_G15	=1<<3
#LGLCD_DEVICE_FAMILY_RAINBOW					=1<<4
#LGLCD_DEVICE_FAMILY_OTHER						=$80000000

; Capabilities of applets connecting to LCD Manager
#LGLCD_APPLET_CAP_BASIC												=0
#LGLCD_APPLET_CAP_CAN_CLOSE_DEVICE						=1<<0
#LGLCD_APPLET_CAP_CAN_CLOSE_CONNECTION				=1<<1
#LGLCD_APPLET_CAP_CAN_CLOSE_AND_REOPEN_DEVICE	=1<<2
#LGLCD_APPLET_CAP_CAN_RUN_ON_MULTIPLE_DEVICES	=1<<3

;Callback used To notify client of soft button change 
;Declare.l lgLcdOnSoftButtonsCB(device.l,dwButtons.l,pContext.l) 

;Callback used To allow client To pop up a "configuration panel" 
;Declare.l lgLcdOnConfigureCB(connection.l,pContect.l) 

Structure lgLcdConfigureContext 
	*configCallback			; Set to NULL if not configurable
	*configContext 
EndStructure 

Structure lgLcdNotificationContext
	*notificationCallback ; Set to NULL if not notifiable
	*notifyContext
EndStructure

Structure lgLcdConnectContext 
	*appFriendlyName		; "Friendly name" display in the listing
	isPersistent.l 			; determines whether this connection persists in the list
	isAutostartable.l		; determines whether the client can be started by LCDMon
	onConfigure.lgLcdConfigureContext 
	connection.l				; Connection handle
EndStructure

; New additions added in 1.03 revision
Structure lgLcdConnectContextEx Extends lgLcdConnectContext
	dwAppletCapabilitiesSupported.l ; Or'd combination of LGLCD_APPLET_CAP_... defines
	dwReserved1.l
	onNotify.lgLcdNotificationContext ; <- strange because Notification is depreciated as of 1.03 revision
EndStructure

; lgLcdOpenContext
Structure lgLcdSoftbuttonsChangedContext 
   *softbuttonsChangedCallback ; Set to NULL if no softbutton notifications are needed
   *softbuttonsChangedContext 
EndStructure 

Structure lgLcdOpenContext 
   connection.l 
   index.l 						; Device index to open
   onSoftbuttonsChanged.lgLcdSoftbuttonsChangedContext 
   device.l						; Device handle
EndStructure 

Import "lgLcd.lib"
; Initialize the library by calling this function.
	lgLcdInit()
; Must be called to release the library and free all allocated structures.
	lgLcdDeInit() 
; Connect as a client to the LCD subsystem. Provide name to be displayed for user when viewing the user interface of the LCD module,
; as well as a configuration callback and context, and a flag that states whether this client is startable by LCDMon
	CompilerIf #PB_Compiler_Unicode 
		lgLcdConnect.l(*ctx.lgLcdConnectContext) As "_lgLcdConnectW@4" 
	CompilerElse 
		lgLcdConnect.l(*ctx.lgLcdConnectContext) As "_lgLcdConnectA@4" 
	CompilerEndIf 
; Must be called to release the connection and free all allocated resources
	lgLcdDisconnect.l(connection.l)
; New additions added in 1.03 revision of API. Call this method to setup which device families the applet is interested
; in. After this call, the applet can use lgLcdEnumerateEx to determine if a device from the device family wanted is found.
	lgLcdSetDeviceFamiliesToUse.l(connection.l,dwDeviceFamiliesSupported.l,dwReserved1.l)
; To determine all connected LCD devices supported by this library, and their capabilities. Start with index 0,
; and increment by one, until the library returns an error (WHICH?).
	lgLcdEnumerate.l(connection.l,index.l,*description.lgLcdDeviceDesc) 
	lgLcdEnumerateEx.l(connection.l,index.l,*description.lgLcdDeviceDescEx) 
; Opens the LCD at position=index. Library sets the device parameter to its internal reference to the device.
; Calling application provides the device handle in all calls that access the LCD.
	lgLcdOpen.l(*ctx.lgLcdOpenContext)
; Closes the LCD. Must be paired with lgLcdOpen.
	lgLcdClose.l(device.l)
; Reads the state of the soft buttons for the device.
	lgLcdReadSoftButtons.l(device.l,*buttons)
; Provides a bitmap to be displayed on the LCD. The priority field further describes the way in which the bitmap is to be applied.
	lgLcdUpdateBitmap.l(device.l, *bitmap.lgLcdBitmapHeader,priority.l) 
; Sets the calling application as the shown application on the LCD, and stops
; any type of rotation among other applications on the LCD.
	lgLcdSetAsLCDForegroundApp.l(device.l,foregoundYesNoFlag.l)
EndImport 

Procedure.l Img2G15(Image,*bitmap.lgLcdBitmap160x43x1,Invers=0) 
	Protected A,B,x,y,w,h,d,Result,hDC,*bmi.BITMAPINFO,*Buffer,Add 
	If Not IsImage(Image) 
		ProcedureReturn #False 
	EndIf 
	w=ImageWidth(Image) 
	h=ImageHeight(Image) 
	d=ImageDepth(Image)
	
	; fix widths and heights
	If d=1
		d=8
	EndIf 
	If w>#LGLCD_BMP_WIDTH 
		w=#LGLCD_BMP_WIDTH 
		h=h*#LGLCD_BMP_WIDTH/ImageWidth(Image) 
		If h>#LGLCD_BMP_HEIGHT 
			h=#LGLCD_BMP_HEIGHT 
			w=w*#LGLCD_BMP_HEIGHT/ImageHeight(Image) 
		EndIf 
	ElseIf h>#LGLCD_BMP_HEIGHT 
		h=#LGLCD_BMP_HEIGHT 
		w=w*#LGLCD_BMP_HEIGHT/ImageHeight(Image) 
		If w>#LGLCD_BMP_WIDTH 
			w=#LGLCD_BMP_WIDTH 
			h=h*#LGLCD_BMP_WIDTH/ImageWidth(Image) 
		EndIf 
	EndIf 
	If w<>ImageWidth(Image) Or h<>ImageHeight(Image) 
		ResizeImage(Image,w,h) 
	EndIf 
	
	*bitmap\hdr\Format=#LGLCD_BMP_FORMAT_160x43x1 
	hDC=StartDrawing(ImageOutput(Image)) 
	If hDC 
		*bmi=AllocateMemory(SizeOf(BITMAPINFO)+255*SizeOf(RGBQUAD)) 
		If *bmi 
			*bmi\bmiHeader\biSize=SizeOf(BITMAPINFOHEADER) 
			*bmi\bmiheader\biWidth=w 
			*bmi\bmiheader\biHeight=-h 
			*bmi\bmiheader\biPlanes=1 
			*bmi\bmiheader\biBitCount=d 
			*bmi\bmiheader\biCompression=#BI_RGB 
			*Buffer=AllocateMemory(w*h*(d/8)) 
			If Not *Buffer 
				StopDrawing() 
			Else 
				Result=GetDIBits_(hDC,ImageID(Image),0,h,*Buffer,*bmi,#DIB_RGB_COLORS) 
				StopDrawing() 
				If Result 
					Add=0 
					Select d 
						Case 8 
							For y=0 To #LGLCD_BMP_HEIGHT-1 
								For x=0 To #LGLCD_BMP_WIDTH-1 
									If y>=h Or x>=w 
										B=255 
									Else 
										A=PeekB(*Buffer+Add)&$ff 
										A=PeekL(*bmi\bmiColors+A*SizeOf(RGBQUAD)) 
										B=(A&$ff)+((A>>8)&$ff)+((A>>16)&$ff) 
										Add+1 
									EndIf 
									If Invers 
										*bitmap\pixels[y*#LGLCD_BMP_WIDTH+x]=B/3 
									Else 
										*bitmap\pixels[y*#LGLCD_BMP_WIDTH+x]=255-(B/3) 
									EndIf 
								Next 
							Next 
					Case 16 
						For y=0 To #LGLCD_BMP_HEIGHT-1 
							For x=0 To #LGLCD_BMP_WIDTH-1 
								If y>=h Or x>=w 
									B=510 
								Else 
									A=PeekW(*Buffer+Add) 
									B=(A&$ff)+((A>>8)&$ff) 
									Add+2
								EndIf 
								If Invers 
									*bitmap\pixels[y*#LGLCD_BMP_WIDTH+x]=B/2 
								Else 
									*bitmap\pixels[y*#LGLCD_BMP_WIDTH+x]=255-(B/2) 
								EndIf 
							Next 
						Next 
					Case 24 
						For y=0 To #LGLCD_BMP_HEIGHT-1 
							For x=0 To #LGLCD_BMP_WIDTH-1 
								If y>=h Or x>=w 
									B=765 
								Else 
									A=PeekL(*Buffer+Add) 
									B=(A&$ff)+((A>>8)&$ff)+((A>>16)&$ff) 
									Add+3 
								EndIf 
								If Invers 
									*bitmap\pixels[y*#LGLCD_BMP_WIDTH+x]=B/3 
								Else 
									*bitmap\pixels[y*#LGLCD_BMP_WIDTH+x]=255-(B/3) 
								EndIf 
							Next 
						Next 
					Case 32 
						For y=0 To #LGLCD_BMP_HEIGHT-1 
							For x=0 To #LGLCD_BMP_WIDTH-1 
								If y>=h Or x>=w 
									B=765 
								Else 
									A=PeekL(*Buffer+Add) 
									B=(A&$ff)+((A>>8)&$ff)+((A>>16)&$ff) 
									Add+4 
								EndIf 
								If Invers 
									*bitmap\pixels[y*#LGLCD_BMP_WIDTH+x]=B/3 
								Else 
									*bitmap\pixels[y*#LGLCD_BMP_WIDTH+x]=255-(B/3) 
								EndIf 
							Next 
						Next 
					EndSelect 
				EndIf 
				FreeMemory(*Buffer) 
			EndIf 
			FreeMemory(*bmi) 
		EndIf 
	EndIf 
	
	ProcedureReturn Result 
EndProcedure 
It's basically an update of HeX0R's code that he posted somewhere ages ago. If you want some examples of use then look up his post. :twisted: The update is to make it work properly with the latest .lib file... I've tested it in an executable on versions of windows that don't support the devices and/or don't have device drivers installed, all works ok (the calls exit with an error code - no crashes!).

The only thing I haven't been able to test (and would like to know what happens if possible) is an executable with the x86 version of the .lib on a x64 machine.
https://deluxepixel.com <- My Business website
https://reportcomplete.com <- School end of term reports system