Hey everyone,
 
Here is an alternative method for extracting a structure out of a wParam or lParam parameter. I pieced this together from various posts on the mailing list. This method is message specific and requires knowledge of the size and members of the specific structure. This example uses the WM_HELP message, which is sent when a user click the '?' button in the top-right corner:
 
$win->Hook(WM_HELP, sub {
  my ($this, $wParam, $lParam, $type, $msgcode) = @_;
  return unless $type == 0;
  return unless $msgcode == WM_HELP;
  my %helpinfo;
  #Here's how to get a stucture when only given a memory address:
  # 1. Pack the $lParam arg into a Long using pack "L" This turns the number into a usable memory address
  # 2. Unpack the result into a string using the size of the structure in bytes using unpack "P28"
  # 3. Unpack the result using the typedef for the structure and the appropriate pack formats
  @helpinfo{qw(cbSize iContextType iCtrlId hItemHandle dwContextId X Y)} = unpack("IiiLLll", unpack("P28", pack("L", $lParam)));
  #The internal Win32::GUI::GetWindowObject can get a window object from its handle
  my $control = Win32::GUI::GetWindowObject($helpinfo{hItemHandle});
  #process message...
  return 1;
 });
 
Remember, that if the structure contains any structures as parameters, they have to unpacked as well. For example, the X and Y above is part of a POINT structure.
 
Refer to the Windows SDK documentation for information about the various messages and structures.
 
Hope this helps.
 
Kevin.
 

Date: Sat, 18 Jul 2009 01:17:40 +0000
From: len@weisberg.com
To: perl-win32-gui-users@lists.sourceforge.net
Subject: Re: [perl-win32-gui-users] Interpreting an lParam pointer

perl-win32-gui-users list,

I wrote:
> But how do I find and read the [COPYDATASTRUCT] structure pointed
>    to by the integer $lParam ?

Well, I figured it out.
Here's a sub, not completely general, but handles the case
of a scalar message string.

Thanks for your indulgence.
(Maybe this will be useful for someone else searching the list archive.)

Cheers,
-Len

use Tie::Array::Pointer ;

sub read_COPYDATASTRUCT {
   ## input: $CopyData_p   (eg from an lParam)
   ## output (scalar): $Msg    (list): ($Msg, dwData_p)
   my $CopyData_p = shift ;

   my @CopyData_a ;
   tie @CopyData_a, 'Tie::Array::Pointer',
      {length => 3,    type   => 'L',    address => $CopyData_p } ;
   my ($dwData_p, $cbData_len, $lpData_p) = @CopyData_a ;

   my @Msg_a ;
   tie @Msg_a, 'Tie::Array::Pointer',
      {length => $cbData_len,  type   => 'C',  address => $lpData_p } ;

   pop @Msg_a if @Msg_a[-1] eq "\0" ;    ## pop off trailing null   (more??)
   my $Msg = pack "C$#Msg_a", @Msg_a ;
   wantarray ? ($Msg, $dwData_p)  : $Msg ;
}



On Jul 17, 2009, len@weisberg.com wrote:
I am trying to use Win32::GUI from a Perl/Tk program
to receive and interpret a message sent from another window.

I have successfully set up a window to receive and a hook to
   handle the message.
   Using the example in Win32::GUI::Reference/Methods.pod, I have

 sub msg_handler {
    ($object, $wParam, $lParam, $type, $msgcode) = @_;
    print "Click handler called!\n";
 }

The result looks reasonable in the debugger,
and $lParam is supposed to be a pointer to a WM_COPYDATA structure.

But how do I find and read the structure pointed to by the integer $lParam ?
I have a hunch that Win32::API::Struct could help, but I don't quite see how.

Thanks,
-Len


Check the daily blob for the latest on what's happening around the web What goes online, stays online