|
From: Robert M. <rob...@us...> - 2009-05-22 08:40:36
|
I have also experimented with OpenGL and Win32::GUI. I started to
write a module to integrate the two, but never completed it - I did
get it running though, and successfully ported most of the examples
that some with the OpenGL module.
I'll make make my code available sometime next week, once I get back
home; if anyone wants to pick this up I can give some direction on
what needs doing to complete it.
Rob.
2009/5/22 Jason Plum <ma...@wa...>:
> 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 <kej...@ho...>
> 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
>>
>> ------------------------------------------------------------------------------
>> 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
>> Per...@li...
>> 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
> Per...@li...
> https://lists.sourceforge.net/lists/listinfo/perl-win32-gui-users
> http://perl-win32-gui.sourceforge.net/
>
|