#GDIHookHandler.py

from ctypes import *
from ctypes.wintypes import *
import os
import winUser
import globalVars

#errors
GDIHook_OK = 0
GDIHook_NotFound = -1
GDIHook_InternalError = -2

MAXLEN=1024

class TGDIHookRec(Structure):
	_fields_=[('x',c_int),('y',c_int),('handle',c_uint),('text',c_wchar_p)]

dll=windll.GDIHookHandler

def attachToWindow(hwnd,libName=os.path.abspath(u"GDIHook.dll")):
	return dll.AttachToWindow(hwnd,libName)

def detachFromWindow(hwnd):
	return dll.DetachFromWindow(hwnd)

def getTextAtCoords(x,y):
	textBuf=TGDIHookRec()
	pTextBuf=pointer(textBuf)
	elems=DWORD()
	res=dll.GetTextAtCoords(x,y,byref(pTextBuf),byref(elems))
	if res != GDIHook_OK:
		if res == GDIHook_InternalError: globalVars.log.error("Internal Error in GDIHook Library")
		return None
	textBufArrayType=(TGDIHookRec*elems.value)
	textBufArray=textBufArrayType()
	textBuf=cast(pTextBuf, POINTER(textBufArrayType)).contents
	internalList=[]
	for pt in textBuf:
		internalList.append((pt.x, pt.y, pt.handle, pt.text))
	return internalList

def getTextInRect(rect):
	textBuf=TGDIHookRec()
	pTextBuf=pointer(textBuf)
	elems=DWORD()
	res=dll.GetTextInRect(byref(RECT(rect[0],rect[1],rect[2],rect[3])),byref(pTextBuf),byref(elems))
	if res != GDIHook_OK:
		if res == GDIHook_InternalError: globalVars.log.error("Internal Error in GDIHook Library")
		return None
	textBufArrayType=(TGDIHookRec*elems.value)
	textBufArray=textBufArrayType()
	textBuf=cast(pTextBuf, POINTER(textBufArrayType)).contents
	internalList=[]
	for pt in textBuf:
		internalList.append((pt.x, pt.y, pt.handle, pt.text))
	return internalList

def getTextFromWindow(handle):
	textBuf=TGDIHookRec()
	pTextBuf=pointer(textBuf)
	elems=DWORD()
	res=dll.GetTextFromWindow(handle,byref(pTextBuf),byref(elems))
	if res != GDIHook_OK:
		if res == GDIHook_InternalError: globalVars.log.error("Internal Error in GDIHook Library")
		return None
	textBufArrayType=(TGDIHookRec*elems.value)
	textBufArray=textBufArrayType()
	textBuf=cast(pTextBuf, POINTER(textBufArrayType)).contents
	internalList=[]
	for pt in textBuf:
		internalList.append((pt.x, pt.y, pt.handle, pt.text))
	return internalList

def clearStorageInRect(l,t,r,b):
	dll.ClearStorageInRect(l,t,r,b)

def makeText(internalList,windowHandles=None):
	if not internalList:
		return None
	x=None
	y=None
	oldX=None
	oldY=None
	textList=[]
	for i in internalList:
		x=i[0]
		y=i[1]
		if oldY and y>oldY:
			if (not windowHandles or i[2] in windowHandles):
				textList.append("\r\n%s"%i[3])
		elif oldX and x>oldY:
			if (not windowHandles or i[2] in windowHandles):
				textList.append("\t%s"%i[3])
		else:
			if (not windowHandles or i[2] in windowHandles):
				textList.append(i[3])
		oldX=x
		oldY=y
	return "".join(textList)

handleList=[]

def getWindowHandles(obj):
#	globalVars.log.warning("getting %d window handles"%len(handleList))
	child=obj.firstChild
	while child and winUser.isDescendantWindow(obj.windowHandle,child.windowHandle):
		w=child.windowHandle
		if w not in handleList:
			winUser.sendMessage(w,winUser.WM_PAINT,None,None)
			handleList.append(w)
			getWindowHandles(child)
		try:
			child=child.next
		except:
			child=None

