root/lang/perl/Win32-FindWindow/trunk/lib/Win32/FindWindow.pm @ 5016

Revision 5016, 8.3 kB (checked in by pia, 5 years ago)

fix POD
sub find_window() and find_windows() is not exported implicitly any longer

Line 
1package Win32::FindWindow;
2
3use warnings;
4use strict;
5use utf8;
6use Encode;
7use Win32::API;
8use Win32::API::Callback;
9
10use base qw(Exporter Class::Accessor::Fast);
11__PACKAGE__->mk_ro_accessors(qw(hwnd windowtext classname pid filename basename));
12
13use constant PROCESS_VM_READ           => 0x0010;
14use constant PROCESS_QUERY_INFORMATION => 0x0400;
15
16our $VERSION = '0.01';
17
18our @EXPORT = qw();
19our @EXPORT_OK = qw(find_window find_windows);
20our @ARGS_REGEXP = qw(windowtext classname filename basename);
21
22our $ENCODING  = 'cp1252';
23our $LENGTH_MAX = 1024;
24
25our $args = {};
26our @instances = ();
27
28Win32::API->Import("user32",   "GetWindowThreadProcessId", "NP",   "N");
29Win32::API->Import("user32",   "GetClassName",             "NPI",  "I");
30Win32::API->Import("user32",   "GetWindowTextLength",      "N",    "I");
31Win32::API->Import("user32",   "GetWindowText",            "NPI",  "I");
32Win32::API->Import("kernel32", "OpenProcess",              "NIN",  "N");
33Win32::API->Import("psapi",    "EnumProcessModules",       "NPNP", "I");
34Win32::API->Import("kernel32", "CloseHandle",              "N",    "I");
35Win32::API->Import("psapi",    "GetModuleFileNameEx",      "NNPN", "N");
36Win32::API->Import("psapi",    "GetModuleBaseName",        "NNPN", "N");
37Win32::API->Import("user32",   "GetDesktopWindow",         "",     "N");
38Win32::API->Import("user32",   "EnumChildWindows",         "NKP",  "I");
39
40sub _neg(@) { map { $_, "$_!" } @_ } ## no critic
41
42our $EnumChildProc = Win32::API::Callback->new(sub {
43    my %result = ();
44    $result{hwnd} = shift;
45   
46    # GetWindowThreadProcessId()
47    {
48        my $ppid = "\x0" x Win32::API::Type->sizeof( 'LPDWORD' );
49        GetWindowThreadProcessId($result{hwnd}, $ppid);
50        $result{pid} = Win32::API::Type::Unpack('LPDWORD', $ppid);
51    }
52   
53    if ($result{pid}) {
54        # GetClassName()
55        {
56            my $size = Win32::API::Type->sizeof( 'CHAR*' ) * $LENGTH_MAX;
57            my $pclassname = "\x0" x $size;
58            GetClassName($result{hwnd}, $pclassname, $size);
59            $result{classname} = Encode::decode($ENCODING, Win32::API::Type::Unpack('CHAR*', $pclassname));
60        }
61       
62        # GetWindowText()
63        {
64            my $size = GetWindowTextLength($result{hwnd});
65            if (Win32::API::IsUnicode()) { $size *= 2; }
66            $size++;
67            my $pwindowtext = "\x0" x $size;
68            GetWindowText($result{hwnd}, $pwindowtext, $size);
69            $result{windowtext} = Encode::decode($ENCODING, Win32::API::Type::Unpack('CHAR*', $pwindowtext));
70        }
71       
72        my $hprocess;
73           ($hprocess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, 0, $result{pid}))
74        or ($hprocess = OpenProcess(PROCESS_QUERY_INFORMATION,                   0, $result{pid}));
75        if ($hprocess > 0) {
76            my $cb         = Win32::API::Type->sizeof( 'HMODULE' ) * $LENGTH_MAX;
77            my $lphmodule  = "\x0" x $cb;
78            my $lpcbneeded = "\x0" x $cb;
79            if (EnumProcessModules($hprocess, $lphmodule, $cb, $lpcbneeded)) {
80                my $hmodule = Win32::API::Type::Unpack('HMODULE', $lphmodule);
81               
82                # GetModuleFileNameEx()
83                {
84                    my $size = Win32::API::Type->sizeof( 'CHAR*' ) * $LENGTH_MAX;
85                    my $lpfilenameex = "\x0" x $size;
86                    GetModuleFileNameEx($hprocess, $hmodule, $lpfilenameex, $size);
87                    $result{filename} = Encode::decode($ENCODING, Win32::API::Type::Unpack('CHAR*', $lpfilenameex));
88                }
89               
90                # GetModuleBaseName()
91                {
92                    my $size = Win32::API::Type->sizeof( 'CHAR*' ) * $LENGTH_MAX;
93                    my $lpbasename = "\x0" x $size;
94                    GetModuleBaseName($hprocess, $hmodule, $lpbasename, $size);
95                    $result{basename} = Encode::decode($ENCODING, Win32::API::Type::Unpack('CHAR*', $lpbasename));
96                }
97            }
98            CloseHandle($hprocess);
99        }
100       
101        my $found = 1;
102        for my $_key (_neg @ARGS_REGEXP) {
103            next unless defined($args->{$_key});
104            my $neg = '';
105            (my $key, $neg) = ($_key =~ /(\w+)(!)?$/);
106            next unless defined($args->{$key});
107           
108            if ($neg) {
109                $found = 0     if $result{$key} =~ $args->{$key};
110            }
111            else {
112                $found = 0 unless $result{$key} =~ $args->{$key};
113            }
114        }
115       
116        if ($found) {
117            push(@instances, __PACKAGE__->new(%result));
118        }
119    }
120    1;
121}, "NN", "I");
122
123sub find_window {
124    @instances = find_windows(@_);
125    if (@instances > 1) { @instances = sort { $a->{pid} <=> $b->{pid} } @instances; }
126    $instances[0];
127}
128
129sub find_windows {
130    $args = {@_};
131   
132    $args->{hwnd} = (defined($args->{hwnd}) and ($args->{hwnd} =~ /^\d+$/))
133                  ? $args->{hwnd}
134                  : GetDesktopWindow();
135   
136    @instances = ();
137    EnumChildWindows($args->{hwnd}, $EnumChildProc, 0);
138    @instances;
139}
140
141sub new {
142    my $class = shift;
143    bless {@_}, $class;
144}
145
1461;
147__END__
148
149=encoding utf8
150
151=head1 NAME
152
153Win32::FindWindow - find windows on Win32 systems
154
155
156=head1 SYNOPSIS
157
158    use Win32::FindWindow qw/find_window find_windows/;
159   
160    $window = find_window();
161    $window = find_window( classname  => 'ExploreWClass' );
162    $window = find_window( basename   => qr/^Explorer.EXE$/
163                         , filename   => qr/^C:\\WINDOWS\\.*/
164                         , windowtext => qr/^C:\\$/
165                         , classname  => qr/^ExploreWClass$/ );
166   
167    @windows = find_windows();
168    @windows = find_windows( windowtext => qr/ - Microsoft Internet Explorer$/ );
169    @windows = find_windows( basename   => 'mspaint.exe'
170                           , filename   => 'C:\\WINDOWS\\system32\\mspaint.exe'
171                           , windowtext => qr/^.+$/
172                           , classname  => 'MSPaintApp' );
173   
174    $window->basename;
175    $window->filename;
176    $window->windowtext;
177    $window->classname;
178    $window->hwnd;
179    $window->pid;
180
181=head1 DESCRIPTION
182
183This module provides routines for finding windows on Win32 systems.
184
185
186=head1 FUNCTIONS
187
188=over
189
190=item find_window()
191
192Returns C<Win32::FindWindow> objects by supplied search parameters.
193The parameters are as follows:
194
195    basename
196    filename
197    windowtext
198    classname
199    hwnd
200    pid
201
202C<SCALAR> or C<Regexp> value can be specified as search conditions for finding window.
203Like this:
204
205    $window = find_window( basename => 'wmplayer.exe' );
206    $window = find_window( windowtext => qr/^Windows Media/ );
207
208=item find_windows()
209
210Same as C<find_window()> except it returns multiple objects as C<ARRAY>.
211
212    @windows = find_windows( basename   => 'mspaint.exe'
213                           , filename   => 'C:\\WINDOWS\\system32\\mspaint.exe'
214                           , windowtext => qr/^.+$/
215                           , classname  => 'MSPaintApp' );
216
217=back
218
219=head1 METHODS
220
221    $window = find_window( ... );
222   
223    # accessors (read-only)
224    $window->basename;
225    $window->filename;
226    $window->windowtext;
227    $window->classname;
228    $window->hwnd;
229    $window->pid;
230
231Accessor methods is being offered as shown in the above. These are read-only.
232
233=head1 GLOBAL VARIABLES
234
235=over
236
237=item $ENCODING
238
239    # how to use regexp with wide characters
240    # e.g. pattern matching the character that starts by Japanese `スタート'
241    use Win32::FindWindow qw/find_windows/;
242    use utf8;
243    use encoding 'utf8', STDOUT => 'cp932';
244    $Win32::FindWindow::ENCODING = 'cp932';
245    @windows = find_windows( classname  => 'Button'
246                           , windowtext => qr/^スタート/ );
247
248A string value that shows system encodings. Defaults to 'cp1252'.
249Set your system's codepage string that module C<Encode> supported.
250Because this module uses C<Encode::decode()> internally.
251
252=item $LENGTH_MAX
253
254A numerical value that shows length of temporary string buffer. Defaults to 1024.
255This is used by C<GetClassName()>, C<EnumProcessModules()>, C<GetModuleFileNameEx()> and C<GetModuleBaseName()>.
256
257=back
258
259=head1 SEE ALSO
260
261L<Win32::API>, L<Win32::API::Callback>, L<Class::Accessor::Fast>, L<Encode>,
262How To Enumerate Windows Using the WIN32 API: L<http://support.microsoft.com/kb/183009>
263
264=head1 AUTHOR
265
266Michiya Honda  C<< <pia@cpan.org> >>
267
268
269=head1 LICENCE
270
271This library is free software, licensed under the same terms with Perl.
272See L<perlartistic>.
Note: See TracBrowser for help on using the browser.