hello
thanks kevin for the opengl example.
i have used his example to display a triangle which can be rotated in a 3D space using the  up down left right  keys.
also added a button and a textbox, i have 2 question:
1- i can rotate the triangle by keys, until i click on the button to display some text in the textbox, why is this behaviour, and how i can restore the triangle rotating after clicking the button.
2- is it possible to make the opengl window smaller than the win32gui window !!
best wishes
attached below the code, and for your convenience from here:
http://rapidshare.com/files/254072142/triangle.rar
peter
 
  use strict;
  use warnings;
  #these constants are needed for SetPixelFormat() but aren't defined in Win32::GUI
  use constant {
  PFD_TYPE_RGBA => 0,
  PFD_DOUBLEBUFFER => 0x00000001,
  PFD_DRAW_TO_WINDOW => 0x00000004,
  PFD_SUPPORT_OPENGL => 0x00000020,
  PFD_MAIN_PLANE => 0,
  };
  use OpenGL qw(:glfunctions :glconstants :glufunctions);
  #use OpenGL qw(:all);
  use Win32::API;
  use Win32::GUI qw();
  use Win32::GUI::Carp qw(warningsToDialog fatalsToDialog immediateWarnings winwarn windie);
  use Win32::GUI::Constants qw(IDI_APPLICATION WS_CLIPCHILDREN WS_CLIPSIBLINGS
  WM_CREATE WM_SIZE WM_CLOSE VK_ESCAPE CW_USEDEFAULT MB_OK MB_ICONEXCLAMATION);
  my $g_HDC; #global handle to device context
  my $hRC; #handle to rendering context
  my $rtri  = 0.0;
  my $xrot = 0;
  my $yrot = 0;
#define PIXELFORMATDESCRIPTOR struct used for the SetPixelFormat function
#refer to the Windows SDK documentation for more info about this structure
  Win32::API::Struct->typedef(
  PIXELFORMATDESCRIPTOR => qw(
  WORD nSize;
  WORD nVersion;
  DWORD dwFlags;
  BYTE iPixelType;
  BYTE cColorBits;
  BYTE cRedBits;
  BYTE cRedShift;
  BYTE cGreenBits;
  BYTE cGreenShift;
  BYTE cBlueBits;
  BYTE cBlueShift;
  BYTE cAlphaBits;
  BYTE cAlphaShift;
  BYTE cAccumBits;
  BYTE cAccumRedBits;
  BYTE cAccumGreenBits;
  BYTE cAccumBlueBits;
  BYTE cAccumAlphaBits;
  BYTE cDepthBits;
  BYTE cStencilBits;
  BYTE cAuxBuffers;
  BYTE iLayerType;
  BYTE bReserved;
  DWORD dwLayerMask;
  DWORD dwVisibleMask;
  DWORD dwDamageMask;
  )
  );
#needed for the wglMakeCurrent functions
  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
  Win32::API->Import('gdi32', 'BOOL SwapBuffers(HDC hdc);')
  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.
  Win32::API->Import('gdi32', 'int ChoosePixelFormat(HDC hdc, PIXELFORMATDESCRIPTOR * ppfd);')
  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().
  Win32::API->Import('gdi32', 'BOOL SetPixelFormat(HDC hdc, int iPixelFormat, PIXELFORMATDESCRIPTOR * ppfd);')
  or windie "Win32::API->Import(SetPixelFormat): $^E";
#creates a new OpenGL rendering context, which is suitable for drawing on the
# device referenced by hdc.
  Win32::API->Import('opengl32', 'HGLRC wglCreateContext(HDC hdc);')
  or windie "Win32::API->Import(wglCreateContext): $^E";
#makes a specified OpenGL rendering context the calling thread's current
# rendering context.
  Win32::API->Import('opengl32', 'BOOL wglMakeCurrent(HDC hdc, HGLRC hglrc);')
  or windie "Win32::API->Import(wglMakeCurrent): $^E";
#deletes a specified OpenGL rendering context.
  Win32::API->Import('opengl32', 'BOOL wglDeleteContext(HGLRC hglrc);')
  or windie "Win32::API->Import(wglDeleteContext): $^E";
#create main window
  my $main = Win32::GUI::Window->new(
  -name => "main",
  -text => "OpenGL Example: Colour Cube",
  -size => [640,480],
  -left => CW_USEDEFAULT, #let system position window
  -pushstyle =>
#Excludes the area occupied by child windows when drawing occurs
# within the parent window.
  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.
  WS_CLIPSIBLINGS,
  -onTerminate => sub { #WM_CLOSE
  wglMakeCurrent($g_HDC->Handle(), 0); #deselect rendering context from $hDC
  wglDeleteContext($hRC); #delete rendering context $hRC
  return -1; #exit main loop
  },
  -onResize => sub { #WM_SIZE
  my $self = shift;
  return 0 unless $self;
  my $height = $self->Height(); #get height and width
  my $width = $self->Width();
  $height = 1 if $height == 0; #don't divide by 0
  glViewport(0,0,$width,$height); #set viewport to new dimensions
  glMatrixMode(GL_PROJECTION); #set matrix mode to projection matrix
  glLoadIdentity(); #reset projection matrix
  gluPerspective(54.0, $width / $height, 1.0, 1000.0); #calculate aspect ratio of window
  glMatrixMode(GL_MODELVIEW); #set modelview matrix
  glLoadIdentity(); #reset modelview matrix
  return 1;
  },
  -onKeyDown => sub { #WM_KEYDOWN
  my ($self, $flags, $key) = @_;
  return -1 if $key == VK_ESCAPE; #exit if escape key pressed
  if  ($key ==  37) {
  $yrot -= 3.0;
 } elsif ($key == 39) {
  $yrot += 3.0;
 } elsif ($key == 38) {
  $xrot += 3.0;
 } elsif ($key == 40) {
  $xrot -= 3.0;
    }
    else {
     return;
    }
    #glutPostRedisplay();
  return 1;
  },
  );
  $main->AddButton(
       -text    => "Run",
       -name    => "Button1",
       -left    => 23,
       -top     => 10,
       -width   => 56,
       -height  => 36,
       -foreground    => 0,
      );
     
      my $textfield = $main->AddTextfield(
       -text    => "",
       -name    => "Textfield_1",
       -left    => 120,
       -top     => 10,
       -width   => 150,
       -height  => 100,
       -multiline    => 1,
       -vscroll    => 1,
      );
     
     
  unless($main){
  windie("Cannot create window: $^E");
  }
  $main->SetIcon(Win32::GUI::Icon->new(IDI_APPLICATION)); #set window icon
#WM_CREATE
  $g_HDC = $main->GetDC(); #set global device context to device context of main window
   unless(SetupPixelFormat($g_HDC->Handle())){ #setup pixel format for device context
  exit 1; #exit if setup fails
  }
 
  $hRC = wglCreateContext($g_HDC->Handle()); #create rendering context used by OpenGL to draw
  wglMakeCurrent($g_HDC->Handle(), $hRC); #select rendering context $hRC into $g_HDC
#Initialize OpenGL
#my ($width, $height) = (300,200);
    glClearColor(0.0, 0.0, 0.0, 0.0);
    # Enables clearing of the Depth buffer
    glClearDepth(1.0);                   
    # The type of depth test to do
    glDepthFunc(GL_LESS);        
    # Enables depth testing with that type
    glEnable(GL_DEPTH_TEST);             
   
    # Enables smooth color shading
    glShadeModel(GL_SMOOTH);     
    # Reset the projection matrix
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity;
    # Calculate the aspect ratio of the Window
    #gluPerspective(45.0, $width/$height, 0.1, 100.0);
    # Reset the modelview matrix
   
  $main->Show(); #show window
  while(Win32::GUI::DoEvents() != -1){
  Render();
  }
#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)
  sub SetupPixelFormat {
  my $hDC = shift; #is a handle to DC
  my $nPixelFormat;
  my $pfd = Win32::API::Struct->new('PIXELFORMATDESCRIPTOR'); #create new structure
  $pfd->{nSize} = $pfd->sizeof(); #return sizeof structure
  $pfd->{nVersion} = 1; #default version
  $pfd->{dwFlags} = PFD_DRAW_TO_WINDOW | #window drawing support
  PFD_SUPPORT_OPENGL | #OpenGL support
  PFD_DOUBLEBUFFER; #double buffering support
  $pfd->{iPixelType} = PFD_TYPE_RGBA; #rgba colour mode
  $pfd->{cColorBits} = 32; #32 bit colour mode
  $pfd->{cRedBits} = 0; #ignore colour bits
  $pfd->{cRedShift} = 0; #
  $pfd->{cGreenBits} = 0; #
  $pfd->{cGreenShift} = 0; #
  $pfd->{cBlueBits} = 0; #
  $pfd->{cBlueShift} = 0; #
  $pfd->{cAlphaBits} = 0; #not alpha buffer
  $pfd->{cAlphaShift} = 0; #ignore alpha shift bit
  $pfd->{cAccumBits} = 0; #no accumulation buffer
  $pfd->{cAccumRedBits} = 0; #ignore accumulation bits
  $pfd->{cAccumGreenBits} = 0; #
  $pfd->{cAccumBlueBits} = 0; #
  $pfd->{cAccumAlphaBits} = 0; #
  $pfd->{cDepthBits} = 16; #16 bit z-buffer size
  $pfd->{cStencilBits} = 0; #no stencil buffer
  $pfd->{cAuxBuffers} = 0; #no auxiliary buffer
  $pfd->{iLayerType} = PFD_MAIN_PLANE; #main drawing plane
  $pfd->{bReserved} = 0; #reserved
  $pfd->{dwLayerMask} = 0; #layer masks ignored
  $pfd->{dwVisibleMask} = 0; #
  $pfd->{dwDamageMask} = 0; #
# choose best matching pixel format
  unless( $nPixelFormat = ChoosePixelFormat($hDC, $pfd) ){
  winwarn("Can't find an appropriate pixel format");
  return 0;
  }
# set pixel format to device context
  unless( SetPixelFormat($hDC, $nPixelFormat, $pfd) ){
  winwarn("Unable to set pixel format");
  return 0;
  }
  return 1;
  }
#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)
  sub DrawCube {
  glRotatef( $yrot, 0.0, 1.0, 0.0 );
  glRotatef( $xrot, 1.0, 0.0, 0.0 );
  glPushMatrix();
  #glBegin(GL_POINTS);
  #glRotatef($rtri, 0.0, 1.0, 0.0);
  glBegin(GL_POLYGON);
    glColor3f(1.0, 0.0, 0.0);
    glVertex3f( 0.0, 20.0, 0.0);     # Top vertex
    glColor3f(0.0, 1.0, 0.0);       # Set The Color To Green
    glVertex3f( 20.0, -20.0, 0.0);    # Bottom right vertex
    glColor3f(0.0, 0.0, 1.0);       # Set The Color To Blue
    glVertex3f(-20.0, -20.0, 0.0); 
  glEnd();
  $rtri  = $rtri  + 3.0;
  glPopMatrix();
  }
#This function is used to draw the cube and is called every frame
#Adapted from code from OpenGL Game Programming (Premier Press, 2004)
  sub Render {
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); #clear color and depth buffer
  glLoadIdentity(); #replaces the current matrix with the identity matrix.
  glTranslatef(0.0, 0.0, -150.0); #move to 0,0,-150
  glPushMatrix(); #save current matrix
  DrawCube(); #draw cube
  glPopMatrix(); #restore matrix
  glFlush(); #clear buffers
  SwapBuffers($g_HDC->Handle()); #exchange front and back buffers of device context
 
  }
 
#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.
  sub Button1_Click { 
  $textfield->Append("OpenGL example : rotating triangle\r\n");
 
 }
 
  package Win32::GUI::DC;
  sub Handle {
  return shift->{-handle};
  }
 
  __END__