Solved

Win32::API::Struct Question about WINDOWPLACEMENT

Posted on 2004-10-07
5
557 Views
Last Modified: 2008-02-01
I am trying to reposition a window using Win32::API.  I believe my struct in this case is malformed but I don't know what is malformed about it -- and the WinAPI just gives me a genertic "The parameter is incorrect.".  Any advise would be great -- thanks.  

--- CODE BELOW ---
use warnings;
use strict;

use Win32;
use Win32::API;
use Win32::API::Struct;

my $FindWindow = new Win32::API('user32', 'FindWindow', 'PP', 'N');
my $SetWindowPlacement = new Win32::API('user32', 'SetWindowPlacement', 'NP', 'N');

Win32::API::Struct->typedef( 'WINDOWPLACEMENT', qw(
      UINT length;
      UINT flags;
      UINT showCmd;
      POINT ptMinPosition;
      POINT ptMaxPosition;
      RECT rcNormalPosition;
));

Win32::API::Struct->typedef( 'POINT', qw(
      LONG x;
      LONG y;
));

Win32::API::Struct->typedef( 'RECT', qw(
      LONG left;
      LONG top;
      LONG right;
      LONG bottom;
));

my $window = $FindWindow->Call("Notepad", 'Untitled - Notepad');

my $UpperLeftPoint = new Win32::API::Struct->new( 'POINT' );
$UpperLeftPoint->{'x'} = 1;
$UpperLeftPoint->{'y'} = 1;

my $WindowSize = new Win32::API::Struct->new( 'RECT' );
$WindowSize->{'left'} = 1;
$WindowSize->{'top'} = 1;
$WindowSize->{'right'} = 1000;
$WindowSize->{'bottom'} = 1000;

my $WindowPlacement = new Win32::API::Struct->new( 'WINDOWPLACEMENT' );
$WindowPlacement->{'flags'} = 0;
$WindowPlacement->{'showCmd'} = 0;
$WindowPlacement->{'ptMinPosition'} = $UpperLeftPoint;
$WindowPlacement->{'ptMaxPosition'} = $UpperLeftPoint;
$WindowPlacement->{'rcNormalPosition'} = $WindowSize;
$WindowPlacement->{'length'} = $WindowPlacement->{'sizeof'};

print "Window: $window\n";
print "SetWindowPlacement: ".$SetWindowPlacement->Call($window, $WindowPlacement)."\n\n";

print "Errors (if any): ".Win32::FormatMessage(Win32::GetLastError());
0
Comment
Question by:rmelton
  • 4
5 Comments
 
LVL 18

Expert Comment

by:kandura
ID: 12261201
Hi rmelton,

I only have time for a couple of notes.
1. FindWindow expects the first argument to be a WindowClass. It so happens that Notepad's class is "Notepad", so that's okay.
2. sizeof is not an attribute of Win32::API::Structs, but a method, so to set the length, you need to do:

    $WindowPlacement->{'length'} = $WindowPlacement->sizeof;

Other than that, I haven't been able to get it to work yet.

HTH,
Kandura
0
 
LVL 18

Expert Comment

by:kandura
ID: 12261736
another quicky (also doesn't fix the problem...)

- you should define the struct WINDOWPLACEMENT *after* you define POINT and RECT, since it depends on those.

(I used Data::Dumper to see that it didn't have proper typedefs for the points and the rect.)
0
 
LVL 18

Accepted Solution

by:
kandura earned 500 total points
ID: 12262394
Got it working!

First of all, the error message at the end is grossly misleading. Don't call it unless SetWindowPlacement returns false.

OK, here's what I changed:
- I moved the struct definitions up towards the start of the script;
- I imported the API's instead of doing Win32::API->new
- your creation of the struct objects was flawed, you called "new struct->new()", but that should of course simply be "struct->new()"

Without much further ado, here is my version:

    use warnings;
    use strict;

    use Data::Dumper;
    use Win32;
    use Win32::API;
    use Win32::API::Struct;

    Win32::API::Struct->typedef( 'POINT' => qw(
         LONG x;
         LONG y;
    ));

    Win32::API::Struct->typedef( 'RECT' => qw(
         LONG left;
         LONG top;
         LONG right;
         LONG bottom;
    ));

    Win32::API::Struct->typedef( 'WINDOWPLACEMENT' => qw(
         UINT length;
         UINT flags;
         UINT showCmd;
         POINT ptMinPosition;
         POINT ptMaxPosition;
         RECT rcNormalPosition;
    ));


    my $FindWindow = new Win32::API('user32', 'FindWindow', 'PP', 'N');

    ### using Import instead of new
    Win32::API->Import('user32', 'INT SetWindowPlacement(HWND hWnd, WINDOWPLACEMENT lpwndplc)');
    Win32::API->Import('user32', 'INT GetWindowPlacement(HWND hWnd, WINDOWPLACEMENT lpwndplc)');

    my $window = $FindWindow->Call("ThunderRT6FormDC", "Perl"); # Quickpost for EE

    my $UpperLeftPoint = Win32::API::Struct->new( 'POINT' );
    $UpperLeftPoint->{'x'} = 1;
    $UpperLeftPoint->{'y'} = 1;

    my $LeftPoint = Win32::API::Struct->new( 'POINT' );
    $LeftPoint->{'x'} = 1;
    $LeftPoint->{'y'} = 1;

    my $WindowSize = Win32::API::Struct->new( 'RECT' );
    $WindowSize->{'left'} = 1;
    $WindowSize->{'top'} = 1;
    $WindowSize->{'right'} = 1000;
    $WindowSize->{'bottom'} = 1000;

    my $WindowPlacement = Win32::API::Struct->new( 'WINDOWPLACEMENT' );
    $WindowPlacement->{'length'} = sizeof $WindowPlacement;

    print "Window: $window\n";

    my $ret = GetWindowPlacement($window, $WindowPlacement);
    print "GetWindowPlacement: $ret\n\n";
    print Dumper($WindowPlacement);
    printf "Errors (if any): [%0x] %s", Win32::GetLastError(), Win32::FormatMessage(Win32::GetLastError()) unless $ret;

    $WindowPlacement->{'flags'} = 0;
    $WindowPlacement->{'showCmd'} = 6;
    $WindowPlacement->{'ptMinPosition'} = $UpperLeftPoint;
    $WindowPlacement->{'ptMaxPosition'} = $LeftPoint;
    $WindowPlacement->{'rcNormalPosition'} = $WindowSize;

    $ret = SetWindowPlacement($window, $WindowPlacement);
    print "SetWindowPlacement: $ret\n\n";
    print Dumper($WindowPlacement);
    printf "Errors (if any): [%0x] %s", Win32::GetLastError(), Win32::FormatMessage(Win32::GetLastError()) unless $ret;
0
 

Author Comment

by:rmelton
ID: 12264103
Thank you very much for taking the time to answer this -- I actually dodged the issue and using SetWindowPos instead, but I am sure this will help others.  Thanks again.
0
 
LVL 18

Expert Comment

by:kandura
ID: 12264186
heh. SetWindowPos makes a lot of sense if you just try to move the window...
at least I hope my post gives you some new insights in how Win32::API works. Pretty neat stuff.
0

Featured Post

PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Sending email via Perl on Windows 3 163
Existing perl code to be changed for ftp to sftp handling 14 194
perl script 4 108
Port 80 requests 16 95
A year or so back I was asked to have a play with MongoDB; within half an hour I had downloaded (http://www.mongodb.org/downloads),  installed and started the daemon, and had a console window open. After an hour or two of playing at the command …
Checking the Alert Log in AWS RDS Oracle can be a pain through their user interface.  I made a script to download the Alert Log, look for errors, and email me the trace files.  In this article I'll describe what I did and share my script.
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
Established in 1997, Technology Architects has become one of the most reputable technology solutions companies in the country. TA have been providing businesses with cost effective state-of-the-art solutions and unparalleled service that is designed…

773 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question