[PythonCE] Open File dialog example

Telion telionce@yahoo.com
Mon, 7 Oct 2002 19:19:02 -0700 (PDT)


I've followed the example of Jeff, and written a small class
that enables easy interface with external C functions.
(especially for win32apis that require struct)

I made this because I wanted to use GetOpenFileName()
included in win32gui.

_test() shows how to use this class and the common
file dialog function.

Please improve it, and let me know.

Telion

------------------------------
#
# This class creates "struct" for external C functions
# It takes list or tuple of (name, format_string, initial_value) for
# each struct member.
# If the struct has padding byte(s), you have to provide dummy member for it.
#
# See the _test() for example
#
# 02/10/07 22:08
# Telion
#

import struct

class cStruct(object):
	def __init__(self, sd):
		#print "cStruct"
		self.sd=list(sd)
		self.nlst = [i[0] for i in sd]
		self.fs = "".join([i[1] for i in sd])
		t = [i[2] for i in sd]
		self.data = struct.pack(self.fs, *t)
		self.ptr = str2ptr(self.data)

	def __setattr__(self, name, v):
		if name in ['sd', 'nlst', 'fs', 'data', 'ptr']:
			object.__setattr__(self, name, v)
			return
		t = list(struct.unpack(self.fs, self.data))
		i = self.nlst.index(name)
		if i > -1:
			t[i] = v
		self.data = struct.pack(self.fs, *t)

	def __getattr__(self, name):
		t = struct.unpack(self.fs, self.data)
		i = self.nlst.index(name)
		if i > -1:
			return t[i]
		else:
			raise AttributeError

	def __str__(self):
		return self.data

	def dump(self): # use this to see the data
		t = struct.unpack(self.fs, self.data)
		ii = 0
		for i in self.nlst:
			print i, "=", t[ii]
			ii += 1
		print "fs = ", self.fs
		print "ptr = ", self.ptr
		return

#
# a few helper functions
#

# try to get the pointer for the string data
def str2ptr(s):
	try:
		import calldll  # use calldll...if you have
		try:
			return calldll.strptr(s) # not all calldll has strptr 
		except:
			pass
	except:
		pass
	return id(s)+20 # This can be different...Check! 


# make NULL terminated C unicode string ( without BOM )
def stru16(s):
	return unicode(s).encode('utf-16')[2:]+"\0\0"

# returns 'mbcs' Python string from C unicode string (NULL terminated, wittout
BOM)
def u16str(u):
	ss = u[:u.index('\0\0')+1] # Get up to double null byte.
	if len(ss) < 2:
		return ""
	return unicode(''.encode('utf-16')+ss, 'utf-16').encode('mbcs') # Add BOM



def _test(title="", inidir=""):
	# cStruct class uses following struct information.
	# (name, fs, initial_value)
	#
	# "name" is used for accessing value
	# "fs" is format string for that value (see struct module doc)
	#			For lpstr, lpcstr, lpxxx, use 'l'.
	# "initial_value" default value
	#
	# In this test, we create OPNEFILENAME struct for GetOpenFineName().
	# And retrieve filenname specified by user.
	# 
	# File dialog access is easy.
	# 
	# >>> import cs
	# >>> fn = cs._test()
	# >>> print fn
	# >>> fn = cs._test(r'DialogTitle',r'\storage card')
	#
	
	import sys

	tt = ( \
		('lStructSize', 'l', 76 ) ,	# always 76 for CE?
		('hwndOwner', 'l', sys.stdout.hwnd ) ,	# shell.hwnd
		('hInstance', 'l', sys.hinst) ,
		('lpstrFilter', 'l', 0 ), # File type filter
		('lpstrCustomFilter', 'l', 0 ), 
		('nMaxCustFilter', 'l', 0 ) ,	# Not supported in CE
		('nFilterIndex', 'l', 0 ) ,	# 
		('lpstrFile', 'l', 0 ) ,	# Initial File name and file name buffer.
		('nMaxFile', 'l', 256 ) ,	# BufferSize of file name string 256 or more
		('lpstrFileTitle', 'l', 0 ) ,	# (optional) base name recievinbg buffer
		('nMaxFileTitle', 'l', 0 ) ,	# max size of above
		('lpstrInitialDir', 'l', 0 ) ,	# (optional) initial directory
		('lpstrTitle', 'l', 0 ) ,	# TitileBar of Dialog
		('Flags', 'l', 0 ) ,	# 
		('nFileOffset', 'H', 0 ) ,	# offset to basa name  ) ,	#) ,	#) ,	# WORD
		('nFileExtension', 'H', 0 ) ,	# offset to extension ) ,	#) ,	#) ,	# WORD
		('lpstrDefExt', 'l', 0 ) ,	# default extension
		('lCustData', 'l', 0 ) ,	# Not supported in CE
		('lpfnHook', 'l', 0 ) ,	# Not supported in CE
		('lpTemplateName', 'l', 0 ) 	# Not supported in CE
	)
	
	#print tt
	cs1 = cStruct(tt)
	filename = "\0"*580 # initialize filename buffer with NULL
	
	cs1.lpstrFile = str2ptr(filename)
	if not title:
		title = r'Choose a file' # Set a string for testing
	dialogtitle = stru16(title)
	cs1.lpstrTitle = str2ptr(dialogtitle)
	
	if not inidir:
		inidir = r'\Program Files' # Set initial directory for testing
	inidir = stru16(inidir)
	cs1.lpstrInitialDir = str2ptr(inidir) # str2ptr is not good enough
	
	import win32gui
	win32gui.GetOpenFileName(cs1.data)
	
	ss = u16str(filename)
	return ss # return the filename
	
	# debug code
	print ss	# This works ascii file name only. mbcs filename needs more effort?
	print "="*10
	cs1.dump() # dump information about struct

	return ss # return the filename






=====
Telion
- telionce@yahoo.com -
http://pages.ccapcable.com/lac/PythonCE.html

__________________________________________________
Do you Yahoo!?
Faith Hill - Exclusive Performances, Videos & More
http://faith.yahoo.com