May I be lucky enough to pick my ass up and put it back onto my chair, then
also say thanks for the well documented and detailed example!

I myself have toyed with OpenGL via perl before, but have never thought of
combining it with Win32::GUI myself. Seeing as I'm a  maintainer for a game,
and some people have asked for updated tools with animations from said
game.. I may someday put this example to a very literal use.

Thanks again,

Jason P

On Thu, May 21, 2009 at 11:18 PM, Kevin Marshall <kejoh...@hotmail.com>wrote:

>  Hey,
>
> This lengthy post is about how to use the Win32::GUI module together with
> the Perl OpenGL module (POGL).
>
> I would first like to thank the developers of Perl-Win32-GUI module. I have
> been using this module for a while now, and prefer using this module than
> coding the whole thing in C/C++. Thanks. I have decided to give back to the
> Win32::GUI community by way of sharing a solution for using OpenGL in
> conjunction with the Win32::GUI module. I hope that someone out there will
> find this useful.
>
> After reading the book OpenGL Game Programming (Premier Press), I decided
> to port some of the code examples to Perl. Since the Win32::GUI module makes
> the creation of windows easy, it was simply a matter of converting the
> relevant C/C++ code into Perl. A basic knowledge of OpenGL is needed in
> order to understand the example that I have provided. The example contains
> comments that should explain what each section does, but I'll provide a
> brief overview of the process. I'll only be discussing the Windows+OpenGL
> specific code, so if you don't have a good grasp of OpenGL, I recommend
> finding a good book or website about OpenGL programming before going any
> further. Detailed information regarding Windows API functions, and OpenGL
> functions can be found in the Windows Software Development Kit
> Documentation.
>
> OpenGL is a powerful, low-level rendering and modelling software library.
> OpenGL does not provide higher functionality, such as windowing, in order to
> remain platform independent. OpenGL uses a rendering context to store OpenGL
> commands and settings. This means that each platform must provide
> functionality to specify a rendering context for OpenGL. For UNIX systems,
> this is provided by GLX. For Windows this is provided by a set of functions
> affectionately known as 'wiggle' functions, since most of these start with
> 'wgl'. There are a number of other Win32 API functions that are also needed.
> These 'wiggle' and Win32 API functions relate Windows Device Contexts with
> the OpenGL rendering contexts. The Win32::API module is needed to import
> these functions for use in the program.
>
> Example Program Description:
>
> Lines 21-51 show some setup required for the functions that are to be
> imported. This includes creating the structure PIXELFORMATDESCRIPTOR used
> by the SetPixelFormat() function and creating a typedef for the
> wglMakeCurrent() function. Lines 52-63 show the functions that need to be
> imported. Info on these functions can be found in the SDK docs.
>
> Lines 64-100 creates the main window and sets its icon. This should be
> fairly basic for anyone experienced with the Win32::GUI module, so I'll just
> cover the important parts. Line 68 sets the -left of the window to
> CW_USEDEFAULT. This specifies that the system should position the window.
> Lines 69-71 add the window styles WS_CLIPCHILDREN  and WS_CLIPSIBLINGS.
> These affect how the window will be painted. For more info about these
> styles, see the SDK docs. Lines 72-76 setup an -onTerminate event handler.
> This will be called when the window is destroyed. At this point the
> rendering context is deselected from the main window Device Context and is
> then deleted. More on these functions later. Just know that each takes a
> handle to a device or rendering context. The sub returns -1 to exit the main
> loop. For those of you familiar with C/C++ Windows programming, this
> function roughly corresponds to the WM_CLOSE message. Lines 77-90 setup an
> -onResize event handler. This is called whenever the window is resized and
> corresponds to the WM_SIZE message. The functions in the sub are OpenGL
> specific and basically just reset the viewport to the new dimensions and
> resets the perspective. Refer to the SDK docs or a good OpenGL resource for
> info about these functions. Lines 91-95 setup a -onKeyDown event handler
> which exits the program when the ESC key is pressed.
>
> Lines 101-106 are where the device and rendering contexts are setup. Line
> 101 gets the device context of the main window and stores it in a global
> variable. Lines 102-104 calls the SetupPixelFormat() function, passing it
> the handle to the main window device context. If this sub fails the program
> exits. Lines 116-157 show the SetupPixelFormat() function. Line 119 creates
> a new PIXELFORMATDESCRIPTOR structure and lines 120-147 fills the structure
> with appropriate data. See the SDK docs for more info about this structure.
> Lines 148-151 calls the ChoosePixelFormat() function passing the handle to
> the DC and the PIXELFORMATDESCRIPTOR structure. This function chooses the
> best matching pixel format for the DC from the data specified in the
> PIXELFORMATDESCRIPTOR structure. The function returns 0 if not pixel format
> can be found. Lines 152-155 set the pixel format of the DC to the format
> returned from the ChoosePixelFormat() function and returns 0 if it fails.
> The sub returns 1 to show that it succeeded.  Line 105 creates an OpenGL
> rendering context from the specified DC using the wglCreateContext()
> function. The function is passed the handle to the main window DC and
> returns the handle to a rendering context. Line 106 selects the rendering
> context into the device context using the wglMakeCurrent() function. This
> functions is passed the handle to the main window DC and the handle to the
> rendering context created with wglCreateContext(). Passing 0 as the
> rendering context causes the rendering context to be deselected, such as in
> the -onTerminate event handler above. The wglDeleteContext() function is
> used to delete a rendering context and should be used after the rendering
> context has been deselected. The deselection and deletion of a rendering
> context should be performed when a window is destroyed, which is why this is
> done in the -onTerminate event handler above. Lines 101-106 could be thought
> of as equivalent to the WM_CREATE message (you could even use the Hook()
> method to implement this).
>
> Lines 107-111 show some basic setup of OpenGL before any rendering is done.
> These are OpenGL specific, so if you are unsure of what these do, refer to
> the docs.
>
> Lines 113-115 setup the main message loop. Win32::GUI::Dialog() can't be
> used here because the Render() function has to be called every frame. This
> loop is essentially the same, but a few differences are present which may
> affect applications with multiple windows, since the Win32::GUI::Dialog()
> functions does more behind the scenes. It would be nice if the
> Win32::GUI::Dialog() function accepted a sub ref which could be called every
> frame, but I'm not sure how easy that would be to create. Anyway, this does
> the job fine, but there are probably better methods.
>
> Lines 158-172 and 173-188 are the DrawCube() and Render() functions,
> respectively. These are used to draw the cube every frame and are OpenGL
> specific. Refer to the docs about what the OpenGL functions do if you are
> unsure.
>
> Line 189-193 creates a Handle() method in the Win32::GUI::DC package. This
> method returns the handle of the object passed in. Putting it in the DC
> package allows both windows and DCs to access it. This method is used when
> the OpenGL/Win32API function requires a handle. Since the objects store in
> handle internally, it makes it really easy to pass this value to the
> functions that need it.
>
> Here is my code example:
>
>
> ################################################################################
> #
> # Win32::GUI + OpenGL example
> #
> # This program demonstrates a basic example of using the Perl Win32::GUI
> #  module in conjunction with the Perl OpenGL module to render a spinning
> #  cube of points in the window.
> #
> # Requirements:
> #  Perl,
> #  Win32::GUI,
> #  Win32::GUI::Carp,
> #  Win32::API, and
> #  OpenGL
> #
> # This program was written using ActiveState Perl 5.8.8 Build 820 running
> on
> #  Windows XP and using Win32::GUI v1.06, Win32::GUI::Carp v1.01,
> #  Win32::API v0.46, and OpenGL v0.56
> #
> # Parts of this program are based on example code from the book OpenGL Game
> #  Programming (Premier Press, 2004) from the Premier Press Game
> #  Development Series. I recommend this book for anyone interested in using
> #  OpenGL for developing games on Windows. The book is written for the
> #  development of games written in C/C++ and assumes an advanced knowledge
> #  of the language but provides an in-depth look at OpenGL programming on
> #  Windows platforms, as well as a look at using DirectInput and
> #  DirectX Audio.
> #
>
> ################################################################################
>
> 1: use strict;
> 2: use warnings;
> #these constants are needed for SetPixelFormat() but aren't defined in
> Win32::GUI
> 3: use constant {
> 4:  PFD_TYPE_RGBA => 0,
> 5:  PFD_DOUBLEBUFFER => 0x00000001,
> 6:  PFD_DRAW_TO_WINDOW => 0x00000004,
> 7:  PFD_SUPPORT_OPENGL => 0x00000020,
> 8:  PFD_MAIN_PLANE => 0,
> 9: };
>
> 10: use OpenGL qw(:glfunctions :glconstants :glufunctions);
> 11: use Win32::API;
> 12: use Win32::GUI qw();
> 13: use Win32::GUI::Carp qw(warningsToDialog fatalsToDialog
> immediateWarnings winwarn windie);
> 14: use Win32::GUI::Constants qw(IDI_APPLICATION WS_CLIPCHILDREN
> WS_CLIPSIBLINGS
> 15:  WM_CREATE WM_SIZE WM_CLOSE VK_ESCAPE CW_USEDEFAULT MB_OK
> MB_ICONEXCLAMATION);
>
> 16: my $g_HDC;  #global handle to device context
> 17: my $hRC;  #handle to rendering context
>
> #keep track of rotation of cube
> 18: my $objectXRot = 0.0;
> 19: my $objectYRot = 0.0;
> 20: my $objectZRot = 0.0;
>
> #define PIXELFORMATDESCRIPTOR struct used for the SetPixelFormat function
> #refer to the Windows SDK documentation for more info about this structure
> 21: Win32::API::Struct->typedef(
> 22:  PIXELFORMATDESCRIPTOR => qw(
> 23:   WORD nSize;
> 24:   WORD nVersion;
> 25:   DWORD dwFlags;
> 26:   BYTE iPixelType;
> 27:   BYTE cColorBits;
> 28:   BYTE cRedBits;
> 29:   BYTE cRedShift;
> 30:   BYTE cGreenBits;
> 31:   BYTE cGreenShift;
> 32:   BYTE cBlueBits;
> 33:   BYTE cBlueShift;
> 34:   BYTE cAlphaBits;
> 35:   BYTE cAlphaShift;
> 36:   BYTE cAccumBits;
> 37:   BYTE cAccumRedBits;
> 38:   BYTE cAccumGreenBits;
> 39:   BYTE cAccumBlueBits;
> 40:   BYTE cAccumAlphaBits;
> 41:   BYTE cDepthBits;
> 42:   BYTE cStencilBits;
> 43:   BYTE cAuxBuffers;
> 44:   BYTE iLayerType;
> 45:   BYTE bReserved;
> 46:   DWORD dwLayerMask;
> 47:   DWORD dwVisibleMask;
> 48:   DWORD dwDamageMask;
> 49:  )
> 50: );
>
> #needed for the wglMakeCurrent functions
> 51: Win32::API::Type->typedef('HGLRC', 'HANDLE');
>
> #import some extra functions
> #more info can be found in the Windows SDK documentation
>
> #exchanges the front and back buffers of the current pixel format
> 52: Win32::API->Import('gdi32', 'BOOL SwapBuffers(HDC hdc);')
> 53:  or windie "Win32::API->Import(SwapBuffers): $^E";
>
> #attempts to match an appropriate pixel format supported by a device
> context to
> # a given pixel format specification.
> 54: Win32::API->Import('gdi32', 'int ChoosePixelFormat(HDC hdc,
> PIXELFORMATDESCRIPTOR * ppfd);')
> 55:  or windie "Win32::API->Import(ChoosePixelFormat): $^E";
>
> #sets the pixel format of the specified device context to the format
> specified
> # by the iPixelFormat index returned from ChoosePixelFormat().
> 56: Win32::API->Import('gdi32', 'BOOL SetPixelFormat(HDC hdc, int
> iPixelFormat, PIXELFORMATDESCRIPTOR * ppfd);')
> 57:  or windie "Win32::API->Import(SetPixelFormat): $^E";
>
> #creates a new OpenGL rendering context, which is suitable for drawing on
> the
> # device referenced by hdc.
> 58: Win32::API->Import('opengl32', 'HGLRC wglCreateContext(HDC hdc);')
> 59:  or windie "Win32::API->Import(wglCreateContext): $^E";
>
> #makes a specified OpenGL rendering context the calling thread's current
> # rendering context.
> 60: Win32::API->Import('opengl32', 'BOOL wglMakeCurrent(HDC hdc, HGLRC
> hglrc);')
> 61:  or windie "Win32::API->Import(wglMakeCurrent): $^E";
>
> #deletes a specified OpenGL rendering context.
> 62: Win32::API->Import('opengl32', 'BOOL wglDeleteContext(HGLRC hglrc);')
> 63:  or windie "Win32::API->Import(wglDeleteContext): $^E";
>
> #create main window
> 64: my $main = Win32::GUI::Window->new(
> 65:  -name => "main",
> 66:  -text => "OpenGL Example: Colour Cube",
> 67:  -size => [640,480],
> 68:  -left => CW_USEDEFAULT,      #let system position window
> 69:  -pushstyle =>
>   #Excludes the area occupied by child windows when drawing occurs
>   # within the parent window.
> 70:   WS_CLIPCHILDREN |
>   #When a particular child window needs to be painted, all other
> overlapping
>   # child windows are clipped out of the region of the child window to be
> updated.
> 71:   WS_CLIPSIBLINGS,
> 72:  -onTerminate => sub {      #WM_CLOSE
> 73:   wglMakeCurrent($g_HDC->Handle(), 0); #deselect rendering context from
> $hDC
> 74:   wglDeleteContext($hRC);     #delete rendering context $hRC
> 75:   return -1;        #exit main loop
> 76:  },
> 77:  -onResize => sub {       #WM_SIZE
> 78:   my $self = shift;
> 79:   return 0 unless $self;
> 80:   my $height = $self->Height();   #get height and width
> 81:   my $width = $self->Width();
> 82:   $height = 1 if $height == 0;   #don't divide by 0
> 83:   glViewport(0,0,$width,$height);   #set viewport to new dimensions
> 84:   glMatrixMode(GL_PROJECTION);   #set matrix mode to projection matrix
> 85:   glLoadIdentity();      #reset projection matrix
> 86:   gluPerspective(54.0, $width / $height, 1.0, 1000.0); #calculate
> aspect ratio of window
> 87:   glMatrixMode(GL_MODELVIEW);    #set modelview matrix
> 88:   glLoadIdentity();      #reset modelview matrix
> 89:   return 1;
> 90:  },
> 91:  -onKeyDown => sub {       #WM_KEYDOWN
> 92:   my ($self, $flags, $key) = @_;
> 93:   return -1 if $key == VK_ESCAPE;  #exit if escape key pressed
> 94:   return 1;
> 95:  },
> 96: );
> 97: unless($main){
> 98:  windie("Cannot create window: $^E");
> 99: }
> 100: $main->SetIcon(Win32::GUI::Icon->new(IDI_APPLICATION)); #set window
> icon
>
> #WM_CREATE
> 101: $g_HDC = $main->GetDC();      #set global device context to device
> context of main window
> 102: unless(SetupPixelFormat($g_HDC->Handle())){ #setup pixel format for
> device context
> 103:  exit 1;          #exit if setup fails
> 104: }
> 105: $hRC = wglCreateContext($g_HDC->Handle());  #create rendering context
> used by OpenGL to draw
> 106: wglMakeCurrent($g_HDC->Handle(), $hRC);   #select rendering context
> $hRC into $g_HDC
>
> #Initialize OpenGL
> 107: glShadeModel(GL_SMOOTH);      #set shading to smooth
> 108: glEnable(GL_DEPTH_TEST);      #do depth comparisons and update the
> depth buffer
> 109: glEnable(GL_CULL_FACE);       #cull polygons based on their winding in
> window coordinates
> 110: glFrontFace(GL_CCW);       #The orientation of front-facing polygons
> 111: glClearColor(0.0, 0.0, 0.0, 0.0);    #values that glClear uses to
> clear the colour buffers
>
> 112: $main->Show();         #show window
>
> #message event
> #This is necessary because Render() needs to be called every frame.
> #This can produce interesting results in more complex applications (with
> more
> # than one window) since the Win32::GUI::Dialog() function does more than
> just
> # check if a sub has returned -1 (perhaps the ability to call a code block
> every
> # iteration of Win32::GUI::Dialog() would be useful)
> 113: while(Win32::GUI::DoEvents() != -1){
> 114:  Render();
> 115: }
>
> #This function is used to set the pixel format for the device context.
> # Accepts a handle to the device context of the window and returns true if
> succeeds
> # or false if fails.
> #Adapted from code from OpenGL Game Programming (Premier Press, 2004)
> 116: sub SetupPixelFormat {
> 117:  my $hDC = shift;       #is a handle to DC
> 118:  my $nPixelFormat;
> 119:  my $pfd = Win32::API::Struct->new('PIXELFORMATDESCRIPTOR'); #create
> new structure
> 120:  $pfd->{nSize} = $pfd->sizeof();    #return sizeof structure
> 121:  $pfd->{nVersion} = 1;      #default version
> 122:  $pfd->{dwFlags} = PFD_DRAW_TO_WINDOW |  #window drawing support
> 123:   PFD_SUPPORT_OPENGL |      #OpenGL support
> 124:   PFD_DOUBLEBUFFER;      #double buffering support
> 125:  $pfd->{iPixelType} = PFD_TYPE_RGBA;   #rgba colour mode
> 126:  $pfd->{cColorBits} = 32;     #32 bit colour mode
> 127:  $pfd->{cRedBits} = 0;      #ignore colour bits
> 128:  $pfd->{cRedShift} = 0;      #
> 129:  $pfd->{cGreenBits} = 0;      #
> 130:  $pfd->{cGreenShift} = 0;     #
> 131:  $pfd->{cBlueBits} = 0;      #
> 132:  $pfd->{cBlueShift} = 0;      #
> 133:  $pfd->{cAlphaBits} = 0;      #not alpha buffer
> 134:  $pfd->{cAlphaShift} = 0;     #ignore alpha shift bit
> 135:  $pfd->{cAccumBits} = 0;      #no accumulation buffer
> 136:  $pfd->{cAccumRedBits} = 0;     #ignore accumulation bits
> 137:  $pfd->{cAccumGreenBits} = 0;    #
> 138:  $pfd->{cAccumBlueBits} = 0;     #
> 139:  $pfd->{cAccumAlphaBits} = 0;    #
> 140:  $pfd->{cDepthBits} = 16;     #16 bit z-buffer size
> 141:  $pfd->{cStencilBits} = 0;     #no stencil buffer
> 142:  $pfd->{cAuxBuffers} = 0;     #no auxiliary buffer
> 143:  $pfd->{iLayerType} = PFD_MAIN_PLANE;  #main drawing plane
> 144:  $pfd->{bReserved} = 0;      #reserved
> 145:  $pfd->{dwLayerMask} = 0;     #layer masks ignored
> 146:  $pfd->{dwVisibleMask} = 0;     #
> 147:  $pfd->{dwDamageMask} = 0;     #
>  # choose best matching pixel format
> 148:  unless( $nPixelFormat = ChoosePixelFormat($hDC, $pfd) ){
> 149:   winwarn("Can't find an appropriate pixel format");
> 150:   return 0;
> 151:  }
>  # set pixel format to device context
> 152:  unless( SetPixelFormat($hDC, $nPixelFormat, $pfd) ){
> 153:   winwarn("Unable to set pixel format");
> 154:   return 0;
> 155:  }
> 156:  return 1;
> 157: }
>
> #This function draws the cube of points. The colour of each point is based
> on its position
> #Adapted from code from OpenGL Game Programming (Premier Press, 2004)
> 158: sub DrawCube {
> 159:  glPointSize(2.0); #set size of points drawn
> 160:  glPushMatrix();
> 161:   glBegin(GL_POINTS);
> 162:    for(my $x = 0.0; $x <= 1.0; $x += 0.1){
> 163:     for(my $y = 0.0; $y <= 1.0; $y += 0.1){
> 164:      for(my $z = 0.0; $z <= 1.0; $z += 0.1){
> 165:       glColor3f($x,$y,$z);
>       #move and scale vertexes so that cube rotates about centre
> 166:       glVertex3f($x*50-25,$y*50-25,$z*50-25);
> 167:      }
> 168:     }
> 169:    }
> 170:   glEnd();
> 171:  glPopMatrix();
> 172: }
>
> #This function is used to draw the cube and is called every frame
> #Adapted from code from OpenGL Game Programming (Premier Press, 2004)
> 173: sub Render {
> 174:  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); #clear color and
> depth buffer
> 175:  glLoadIdentity();         #replaces the current matrix with the
> identity matrix.
> 176:  glTranslatef(0.0, 0.0, -150.0);      #move to 0,0,-150
> 177:  glPushMatrix();          #save current matrix
> 178:   glRotatef($objectXRot, 1.0, 0.0, 0.0);   #rotate around x axis
> 179:   glRotatef($objectYRot, 0.0, 1.0, 0.0);   #rotate around y axis
> 180:   glRotatef($objectZRot, 0.0, 0.0, 1.0);   #rotate around z axis
> 181:   DrawCube();          #draw cube
> 182:  glPopMatrix();          #restore matrix
> 183:  glFlush();           #clear buffers
> 184:  SwapBuffers($g_HDC->Handle());      #exchange front and back buffers
> of device context
> 185:  $objectXRot += 0.01;        #increment rotation
> 186:  $objectYRot += 0.02;
> 187:  $objectZRot += 0.01;
> 188: }
>
> #Conveniently, the Windows specific functions for setup of OpenGL accept
> and return
> # handles to windows or contexts, which are just numbers, and the handles
> to
> # these are stored in the Window and DC objects created by Win32::GUI. This
> method
> # provides an easy access to this value. Placing the method in the
> Win32::GUI::DC
> # package allows both Windows and DCs to use it.
> 189: package Win32::GUI::DC;
> 190: sub Handle {
> 191:  return shift->{-handle};
> 192: }
> 193: __END__
>
> Here are some tips and tricks regarding using Win32::GUI module and the
> OpenGL module that I have come across on my travels:
>
> Win32::GUI:
>
>
>    - It is possible to create child windows that are rendered to using
>    OpenGL instead of rendering to the parent window, but requires a lot more
>    setup. One of the tricks needed is to specify the right styles for the
>    window. I have yet to perfect this technique, but perhaps when I get it
>    working correctly I'll post an example.
>
>
> OpenGL:
>
>    - try to use the *_p variants of functions, if they exist. The function
>    has been tweaked to behave more like a regular Perl function, such as the
>    ability to accept and return arrays. This is a lot more convenient than
>    having to pack() and unpack() your a arguments. Some functions don't have a
>    *_p variant, so the next best thing is to use the *_c variant, which
>    accept OpenGL::Array objects. The use of OpenGL::Array is not documented in
>    the module, but docs can be found on the website for the module (just 
> search
>    the web for POGL). I haven't included an example of this here, since it
>    requires more knowledge of OpenGL, but experienced OpenGL programmers 
> should
>    have no problems using them.
>
>
> As an alternative to creating windows using Win32::GUI, windows can be
> created using the GLUT(OpenGL Utility Toolkit) functions supplied with
> OpenGL. These can create windows that a platform-independent, as well as a
> lot of other stuff. A lot of the examples supplied for the OpenGL module use
> the GLUT, making them more portable, but OpenGL needs to be compiled with
> support for GLUT, requiring the GLUT libraries. Since I can't seem to get
> XS-implemented modules to compile properly on my machine (I use PPM
> instead), I just stick with Win32::GUI. Its all about personal preference.
>
> Well, that's it for my Win32::GUI+OpenGL example. I hope someone finds it
> useful. I'm no expert at OpenGL or the Win32 API, so there is probably a
> better way of doing this. So far this model has worked for basic
> implementations but don't expect to be able to make anything to big, such as
> games, but you never know. I'd love to hear any questions or comments about
> this example, as well as any examples of anything anyone else has done.
>
> As a side note, I'm new to posting messages on the mailing lists. I was
> wondering whether I can send pictures attached (I was hoping to show a
> screen shot of my program). Also, how do I post a reply to an existing
> thread. Any help would be much appreciated.
>
> Sorry about any typos in advance. Contact me if you find any errors with
> this post (such as with the sample program).
>
> Thanks.
>
> Kevin Marshall
>
> (kejohm88 AT hotmail DOT com)
>
>
>
> ------------------------------
> Click Here View photos of singles in your 
> area<http://a.ninemsn.com.au/b.aspx?URL=http%3A%2F%2Fdating%2Eninemsn%2Ecom%2Eau%2Fsearch%2Fsearch%2Easpx%3Fexec%3Dgo%26tp%3Dq%26gc%3D2%26tr%3D1%26lage%3D18%26uage%3D55%26cl%3D14%26sl%3D0%26dist%3D50%26po%3D1%26do%3D2%26trackingid%3D1046138%26r2s%3D1&_t=773166090&_r=Hotmail_Endtext&_m=EXT>
>
>
> ------------------------------------------------------------------------------
> Register Now for Creativity and Technology (CaT), June 3rd, NYC. CaT
> is a gathering of tech-side developers & brand creativity professionals.
> Meet
> the minds behind Google Creative Lab, Visual Complexity, Processing, &
> iPhoneDevCamp asthey present alongside digital heavyweights like Barbarian
> Group, R/GA, & Big Spaceship. http://www.creativitycat.com
> _______________________________________________
> Perl-Win32-GUI-Users mailing list
> Perl-Win32-GUI-Users@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/perl-win32-gui-users
> http://perl-win32-gui.sourceforge.net/
>



-- 
Maximus*
WarheadsSE
MaxSource
------------------------------------------------------------------------------
Register Now for Creativity and Technology (CaT), June 3rd, NYC. CaT
is a gathering of tech-side developers & brand creativity professionals. Meet
the minds behind Google Creative Lab, Visual Complexity, Processing, & 
iPhoneDevCamp asthey present alongside digital heavyweights like Barbarian
Group, R/GA, & Big Spaceship. http://www.creativitycat.com 
_______________________________________________
Perl-Win32-GUI-Users mailing list
Perl-Win32-GUI-Users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/perl-win32-gui-users
http://perl-win32-gui.sourceforge.net/

Reply via email to