Archive

Archive for February, 2007

Spam spam spam

February 28th, 2007

I have to disable public comments due to massive amounts of spam.
If you still want to comment something, feel free to register.

buffi Uninteresting

Sending strings between win32 applications with python (WM_COPYDATA)

February 24th, 2007

While developing a small application for windows in python I realized that it was rather hard to send strings between different programs. I eventually got it running so I thought I’d post them here as examples.

I found out that the best path to choose is by using the windows message event-thingies. I’m not really much of a windows user so I have no clue about how they actually work but at least I kind of know how to use them now.
Basically to pass a string between two applications, you pass the memory address of a structure containing a string among other things (a pointer that is) to the target window by using it’s window handle (hWnd).
This is probably rather easy in c++ but since python doesn’t really have pointers you have to use the ctypes, array and struct modules to construct/deconstruct the things to send.

To get this running you need the win32 modules (win32con, win32gui, win32api) as well as ctypes. I used wxpython for the GUI but you can use anything you want. If you want my examples to run you need it installed though…

Anyways, I tried to document the code heavily so that I won’t have to explain much more…
Here is the code for the reciever

################
######reciever.py
############

import wx
import win32gui
import win32con
import struct
import ctypes
import sys

#Make an app with a static text
app = wx.PySimpleApp()
frame = wx.Frame( None, -1, "Message Reciever", size = ( 200, 50 ) )
result = wx.StaticText(frame, -1, "No text yet!",wx.Point(10,10))

#Write the windows hWnd to a file for the other app to read
fil = open( "hWnd", "w" )
fil.write( "%d" % frame.GetHandle() )
fil.close()

#Custom message handler
def MyWndProc( hWnd, msg, wParam, lParam ):

    # if we get any message from other app
    if msg == win32con.WM_COPYDATA: 

        #get the struct-string from the memory address
        structure = ctypes.string_at( lParam, 12 )

        #unpack the data
        data = struct.unpack("IIP", structure)
        unused, str_len, str_adr = data

        #and finally get the real string from the memory
        my_string = ctypes.string_at( str_adr, str_len )

        #update the static text
        result.SetLabel( my_string )

    #handles program termination
    elif msg == win32con.WM_DESTROY:
        win32gui.DestroyWindow( frame.GetHandle() )
        win32gui.PostQuitMessage(0)

    return win32gui.CallWindowProc( oldWndProc, hWnd, msg, wParam, lParam )

#Use the custom handler
oldWndProc = win32gui.SetWindowLong(
         frame.GetHandle() ,
         win32con.GWL_WNDPROC ,
         MyWndProc )

#show it!
frame.Show()
app.MainLoop()

By default running this displays a small window containing a static text that looks like this
before

Then we have the code for the sender

################
######sender.py
############

import win32con
import win32api
import struct, array
import sys

# get text to send
if len( sys.argv ) > 1:
  text_to_send = sys.argv[1]
else:
  sys.exit( 1 )

#get the hWnd to send to
#we have stored it in a file
hwnd = int( open( "hWnd", "rb" ).read() )

#create a char array from the string
my_data = array.array( 'c', text_to_send )

#get the memory address to the array
data_ad, data_len = my_data.buffer_info()

#create a struct with length and address to the data
my_struct = array.array( 'c',  struct.pack( "IIP", data_len, data_len, data_ad ) )

#and make a pointer to it
struct_ad = my_struct.buffer_info()[0]

#now send it to the hWnd
win32api.SendMessage(
         hwnd ,
         win32con.WM_COPYDATA ,
         0 ,
         struct_ad )

This doesnt use any GUI. It is just a console application that takes an argument and sends it to the other app. If you’d like you could let this application take input through a fancy GUI or whatever.

Since the reciever writes its hWnd to a file that the sender reads it knows where to send the data. You could also find the window through other means in the windows API.

Anyways, calling the sender with an argument results in the text in the other window changing!
after

Pretty basic examples that shouldn’t be too hard to build upon. Please leave a comment if it was helpful!

buffi Programming & scripting, Python, Uninteresting

BMPDecode version 1.1 released

February 21st, 2007

Just implemented the ability to export BMP’s as RAW RGB data in BMPDecode since I needed a tool to do this.
I tried it out by exporting some textures as raw RGB and loading them into opengl as textures and it worked fine :)

So if you need a quick converter from BMP -> RAW RGB/RGBA this is your fix!

Changelog:

Added these methods:

     |  exportRAW_RGB(self, outfilename)
     |      exportRAW_RGB(filename) -> no return value
     |      Exports the data contained in the decoder to a RAW
     |      RGB data file with the filename passed as an argument
     |
     |  exportRAW_RGBA(self, outfilename, alphavalue=255)
     |      exportRAW_RGB(filename, alphavalue=255) -> no return value
     |      Exports the data contained in the decoder to a RAW
     |      RGBA data file with the filename passed as an argument

Download here!

Example of use:

import bmpdecode
decoder = bmpdecode.BMPDecoder("mybmpfile.bmp")
decoder.exportRAW_RGB("myraw.raw")

Optionally call

decoder.print_fileinfoheader()

to get the height/width of the image since t is not saved in the RAW file.

buffi Programming & scripting, Python