1 package OS2::localMorphPM;
7 # print STDERR ">>>>>\n";
11 # print STDERR "<<<<<\n";
12 OS2::UnMorphPM(shift->[0])
22 our @ISA = qw(Exporter);
23 our $VERSION = "1.01";
24 XSLoader::load('OS2::Process', $VERSION);
27 # Items to export into callers namespace by default. Note: do not export
28 # names by default without a very good reason. Use EXPORT_OK instead.
29 # Do not simply export all your public functions/methods/constants.
129 FocusWindow_set_keep_Zorder
131 ActiveDesktopPathname
184 # This AUTOLOAD is used to 'autoload' constants from the constant()
185 # XS function. If a constant is not found then control is passed
186 # to the AUTOLOAD in AutoLoader.
188 (my $constname = $AUTOLOAD) =~ s/.*:://;
189 my $val = constant($constname, @_ ? $_[0] : 0);
191 if ($! =~ /Invalid/ || $!{EINVAL}) {
192 die "Unsupported function $AUTOLOAD"
194 my ($pack,$file,$line) = caller;
195 die "Your vendor has not defined OS2::Process macro $constname, used at $file line $line.
199 eval "sub $AUTOLOAD { $val }";
204 require OS2::Process::Const;
206 my ($err, $val) = OS2::Process::Const::constant($sym);
212 *{"$p\::$sym"} = sub () { $val };
213 (); # needed by import()
221 /^(HWND|WM|SC|SWP|WC|PROG|QW|EDI|WS|QWS|QWP|QWL|FF|FI|LS|FS|FCF|BS|MS|TBM|CF|CFI|FID|MB|MBID|CF|CFI|SPTR)_/ ? const_import($_) : $_
223 goto &Exporter::import if @_ > 1 or $ini == 0;
226 # Preloaded methods go here.
228 sub Title () { (process_entry())[0] }
230 # *Title_set = \&sesmgr_title_set;
233 my ($title, @sw) = @_;
238 sub swTitle_set ($) {
239 my (@sw) = process_entry();
240 swTitle_set_sw(shift, @sw);
243 sub winTitle_set_sw {
244 my ($title, @sw) = @_;
245 my $h = OS2::localMorphPM->new(0);
246 WindowText_set $sw[1], $title;
249 sub winTitle_set ($) {
250 my (@sw) = process_entry();
251 winTitle_set_sw(shift, @sw);
255 my (@sw) = process_entry();
256 my $h = OS2::localMorphPM->new(0);
260 sub bothTitle_set ($) {
261 my (@sw) = process_entry();
263 winTitle_set_sw($t, @sw);
264 swTitle_set_sw($t, @sw);
269 return 1 if sesmgr_title_set($t);
270 return 0 unless $^E == 372;
271 my (@sw) = process_entry();
272 winTitle_set_sw($t, @sw);
273 swTitle_set_sw($t, @sw);
276 sub process_entry { swentry_expand(process_swentry(@_)) }
278 our @hentry_fields = qw( title owner_hwnd icon_hwnd
279 owner_phandle owner_pid owner_sid
280 visible nonswitchable jumpable ptype sw_entry );
282 sub swentry_hexpand ($) {
284 @h{@hentry_fields} = swentry_expand(shift);
288 sub process_hentry { swentry_hexpand(process_swentry(@_)) }
289 sub process_hwnd { process_hentry()->{owner_hwnd} }
291 my $swentry_size = swentry_size();
294 my $s = swentries_list();
295 my ($c, $s1) = unpack 'La*', $s;
296 die "Unconsistent size in swentries_list()" unless 4+$c*$swentry_size == length $s;
298 push @l, $e while $e = substr $s1, 0, $swentry_size, '';
302 sub process_entries () {
303 map [swentry_expand($_)], sw_entries;
306 sub process_hentries () {
307 map swentry_hexpand($_), sw_entries;
311 change_swentry(create_swentry(@_));
314 sub create_swentryh ($) {
316 create_swentry(@$h{@hentry_fields});
319 sub change_entryh ($) {
320 change_swentry(create_swentryh(shift));
323 # Massage entries into the same order as WindowPos_set:
325 my ($fl, $h, $w, $y, $x, $behind, $hwnd, @rest)
326 = unpack 'L l4 L4', WindowSWP(shift);
327 ($x, $y, $fl, $w, $h, $behind, @rest);
330 # Put them into a hash
333 @h{ qw(flags height width y x behind hwnd reserved1 reserved2) }
334 = unpack 'L l4 L4', WindowSWP(shift);
338 my @SWP_keys = ( [qw(width height)], # SWP_SIZE=1
339 [qw(x y)], # SWP_MOVE=2
340 [qw(behind)] ); # SWP_ZORDER=3
342 @SWP_def{ map @$_, @SWP_keys } = (0) x 20;
344 # Get them from a hash
345 sub hWindowPos_set ($$) {
347 my $hwnd = (@_ ? shift : $hash->{hwnd} );
349 if (exists $hash->{flags}) {
350 $flags = $hash->{flags};
351 } else { # Set flags according to existing keys in $hash
354 exists $hash->{$_} and $flags |= (1<<$bit) for @{$SWP_keys[$bit]};
357 for my $bit (0..2) { # Check for required keys
358 next unless $flags & (1<<$bit);
360 or die sprintf "key $_ required for flags=%#x", $flags
361 for @{$SWP_keys[$bit]};
363 my %h = (%SWP_def, flags => $flags, %$hash); # Avoid warnings
364 my ($x, $y, $fl, $w, $h, $behind) = @h{ qw(x y flags width height behind) };
365 WindowPos_set($hwnd, $x, $y, $fl, $w, $h, $behind);
368 sub ChildWindows (;$) {
369 my $hm = OS2::localMorphPM->new(0);
371 my $h = BeginEnumWindows(@_ ? shift : 1); # HWND_DESKTOP
373 push @kids, $w while $w = GetNextWindow $h;
379 my $d = DesktopWindow;
382 my $p = QueryWindow $w, 5; # QW_PARENT;
383 return $w if not $p or $p == $d;
388 sub FocusWindow_set_keep_Zorder ($) {
391 my $b = hWindowPos($t)->{behind}; # we are behind this
392 EnableWindowUpdate($t, 0);
394 # sleep 1; # Make flicker stronger when present
395 hWindowPos_set {behind => $b}, $t;
396 EnableWindowUpdate($t, 1);
399 sub ClipbrdText (@) {
400 my $morph = OS2::localMorphPM->new(0);
402 my $txt = unpack 'p', pack 'L', ClipbrdData @_;
407 sub ClipbrdText_set ($;$) {
408 my $morph = OS2::localMorphPM->new(0);
410 EmptyClipbrd(); # It may contain other types
411 my ($txt, $no_convert_nl) = (shift, shift);
412 ClipbrdData_set($txt, !$no_convert_nl, @_);
416 sub MessageBox ($;$$$$$) {
417 my $morph = OS2::localMorphPM->new(0);
418 die "MessageBox needs text" unless @_;
419 push @_ , ($0 eq '-e' ? "Perl one-liner's message" : "$0 message") if @_ == 1;
425 sub get_pointer ($;$$) {
427 return $pointers{$id} if exists $pointers{$id};
428 $pointers{$id} = &SysPointer;
431 # $button needs to be of the form 'String', ['String'] or ['String', flag].
432 # If ['String'], it is assumed the default button; same for 'String' if $only
434 sub process_MB2 ($$;$) {
435 die "process_MB2() needs 2 arguments, got '@_'" unless @_ == 2 or @_ == 3;
436 my ($button, $ret, $only) = @_;
437 # default is BS_PUSHBUTTON, add BS_DEFAULT if $only is set
438 $button = [$button, $only ? 0x400 : 0] unless ref $button eq 'ARRAY';
439 push @$button, 0x400 if @$button == 1; # BS_PUSHBUTTON|BS_DEFAULT
440 die "Button needs to be of the form 'String', ['String'] or ['String', flag]"
441 unless @$button == 2;
442 pack "Z71 x L l", $button->[0], $ret, $button->[1]; # name, retval, flag
445 # If one button, make it the default one even if it is of 'String' => val form.
446 # If icon is of the form 'SP#<number>', load this via SysPointer.
447 sub process_MB2_INFO ($;$$$) {
450 die "process_MB2_INFO() needs 1..4 arguments" unless @_ and @_ < 5;
452 die "Buttons array should consist of pairs" if @$buttons % 2;
454 push @_, 0 unless @_; # Icon id (pointer)
455 # Box flags (MB_MOVABLE and MB_INFORMATION or MB_CUSTOMICON)
456 push @_, ($_[0] ? 0x4080 : 0x4030) unless @_ > 1;
457 push @_, 0 unless @_ > 2; # Notify window
459 my ($icon, $style, $notify) = (shift, shift, shift);
460 $icon = get_pointer $1 if $icon =~ /^SP#(\d+)\z/;
461 $out = pack "L L L L", # icon, #buttons, style, notify, buttons
462 $icon, @$buttons/2, $style, $notify;
464 map process_MB2($buttons->[2*$_], $buttons->[2*$_+1], @$buttons == 2),
466 pack('L', length(pack 'L', 0) + length $out) . $out;
469 # MessageBox2 'Try this', OS2::Process::process_MB2_INFO([['Dismiss', 0] => 0x1000], OS2::Process::get_pointer(22),0x4080,0), 'me', 1, 0, 0
471 # MessageBox2 'Try this', [[['Dismiss', 0] => 0x1000], 'SP#22'], 'me'
472 # 0x80 means MB_CUSTOMICON (does not focus?!). This focuses:
473 # MessageBox2 'Try this', [[['Dismiss',0x400] => 0x1000], 0, 0x4030,0]
474 # 0x400 means BS_DEFAULT. This is the same as the shortcut
475 # MessageBox2 'Try this', [[Dismiss => 0x1000]]
476 sub MessageBox2 ($;$$$$$) {
477 my $morph = OS2::localMorphPM->new(0);
478 die "MessageBox needs text" unless @_;
479 push @_ , [[Dismiss => 0x1000], # Name, retval (BS_PUSHBUTTON|BS_DEFAULT)
480 #0, # get_pointer(11), # SPTR_ICONINFORMATION
481 #0x4030, # MB_MOVEABLE | MB_INFORMATION
482 #0, # Notify window; was 1==HWND_DESKTOP
484 push @_ , ($0 eq '-e' ? "Perl one-liner's message" : "$0's message") if @_ == 2;
485 $_[1] = &process_MB2_INFO(@{$_[1]}) if ref($_[1]) eq 'ARRAY';
489 # backward compatibility
490 *set_title = \&Title_set;
491 *get_title = \&Title;
493 # Autoload methods go after __END__, and are processed by the autosplit program.
500 OS2::Process - exports constants for system() call, and process control on OS2.
505 $pid = system(P_PM | P_BACKGROUND, "epm.exe");
509 =head2 Optional argument to system()
511 the builtin function system() under OS/2 allows an optional first
512 argument which denotes the mode of the process. Note that this argument is
513 recognized only if it is strictly numerical.
515 You can use either one of the process modes:
517 P_WAIT (0) = wait until child terminates (default)
518 P_NOWAIT = do not wait until child terminates
519 P_SESSION = new session
523 and optionally add PM and session option bits:
525 P_DEFAULT (0) = default
526 P_MINIMIZE = minimized
527 P_MAXIMIZE = maximized
528 P_FULLSCREEN = fullscreen (session only)
529 P_WINDOWED = windowed (session only)
531 P_FOREGROUND = foreground (if running in foreground)
532 P_BACKGROUND = background
534 P_NOCLOSE = don't close window on exit (session only)
536 P_QUOTE = quote all arguments
537 P_TILDE = MKS argument passing convention
538 P_UNRELATED = do not kill child when father terminates
540 =head2 Access to process properties
542 On OS/2 processes have the usual I<parent/child> semantic;
543 additionally, there is a hierarchy of sessions with their own
544 I<parent/child> tree. A session is either a FS session, or a windowed
545 pseudo-session created by PM. A session is a "unit of user
546 interaction", a change to in/out settings in one of them does not
547 affect other sessions.
553 returns the type of the current process (one of
554 "FS", "DOS", "VIO", "PM", "DETACH" and "UNKNOWN"), or C<undef> on error.
556 =item C<file_type(file)>
558 returns the type of the executable file C<file>, or
559 dies on error. The bits 0-2 of the result contain one of the values
563 =item C<T_NOTSPEC> (0)
565 Application type is not specified in the executable header.
567 =item C<T_NOTWINDOWCOMPAT> (1)
569 Application type is not-window-compatible.
571 =item C<T_WINDOWCOMPAT> (2)
573 Application type is window-compatible.
575 =item C<T_WINDOWAPI> (3)
577 Application type is window-API.
581 The remaining bits should be masked with the following values to
582 determine the type of the executable:
588 Set to 1 if the executable file has been "bound" (by the BIND command)
589 as a Family API application. Bits 0, 1, and 2 still apply.
591 =item C<T_DLL> (0x10)
593 Set to 1 if the executable file is a dynamic link library (DLL)
594 module. Bits 0, 1, 2, 3, and 5 will be set to 0.
596 =item C<T_DOS> (0x20)
598 Set to 1 if the executable file is in PC/DOS format. Bits 0, 1, 2, 3,
599 and 4 will be set to 0.
601 =item C<T_PHYSDRV> (0x40)
603 Set to 1 if the executable file is a physical device driver.
605 =item C<T_VIRTDRV> (0x80)
607 Set to 1 if the executable file is a virtual device driver.
609 =item C<T_PROTDLL> (0x100)
611 Set to 1 if the executable file is a protected-memory dynamic link
614 =item C<T_32BIT> (0x4000)
616 Set to 1 for 32-bit executable files.
620 file_type() may croak with one of the strings C<"Invalid EXE
621 signature"> or C<"EXE marked invalid"> to indicate typical error
622 conditions. If given non-absolute path, will look on C<PATH>, will
623 add extention F<.exe> if no extension is present (add extension F<.>
626 =item C<@list = process_codepages()>
628 the first element is the currently active codepage, up to 2 additional
629 entries specify the system's "prepared codepages": the codepages the
630 user can switch to. The active codepage of a process is one of the
631 prepared codepages of the system (if present).
633 =item C<process_codepage_set($cp)>
635 sets the currently active codepage. [Affects printer output, in/out
636 codepages of sessions started by this process, and the default
637 codepage for drawing in PM; is inherited by kids. Does not affect the
638 out- and in-codepages of the session.]
642 returns the PID of the parent process.
644 =item C<ppidOf($pid = $$)>
646 returns the PID of the parent process of $pid. -1 on error.
648 =item C<sidOf($pid = $$)>
650 returns the session id of the process id $pid. -1 on error.
654 =head2 Control of VIO sessions
656 VIO applications are applications running in a text-mode session.
662 gets code page used for screen output (glyphs). -1 means that a user font
665 =item C<out_codepage_set($cp)>
667 sets code page used for screen output (glyphs). -1 switches to a preloaded
668 user font. -2 switches off the preloaded user font.
672 gets code page used for keyboard input. 0 means that a hardware codepage
675 =item C<in_codepage_set($cp)>
677 sets code page used for keyboard input.
679 =item C<($w, $h) = scrsize()>
681 width and height of the given console window in character cells.
683 =item C<scrsize_set([$w, ] $h)>
685 set height (and optionally width) of the given console window in
686 character cells. Use 0 size to keep the old size.
688 =item C<($s, $e, $w, $a) = cursor()>
690 gets start/end lines of the blinking cursor in the charcell, its width
691 (1 on text modes) and attribute (-1 for hidden, in text modes other
692 values mean visible, in graphic modes color).
694 =item C<cursor_set($s, $e, [$w [, $a]])>
696 sets start/end lines of the blinking cursor in the charcell. Negative
697 values mean percents of the character cell height.
701 gets a buffer with characters and attributes of the screen.
703 =item C<screen_set($buffer)>
705 restores the screen given the result of screen(). E.g., if the file
706 C<$file> contains the sceen contents, then
708 open IN, $file or die;
712 $in .= qq(\0) x (length($s) - length $in);
713 substr($in, length $s) = '';
716 will restore the screen content even if the height of the window
717 changed (if the width changed, more manipulation is needed).
721 =head2 Control of the process list
723 With the exception of Title_set(), all these calls require that PM is
724 running, they would not work under alternative Session Managers.
728 =item process_entry()
730 returns a list of the following data:
736 Title of the process (in the C<Ctrl-Esc> list);
740 window handle of switch entry of the process (in the C<Ctrl-Esc> list);
744 window handle of the icon of the process;
748 process handle of the owner of the entry in C<Ctrl-Esc> list;
752 process id of the owner of the entry in C<Ctrl-Esc> list;
756 session id of the owner of the entry in C<Ctrl-Esc> list;
760 whether visible in C<Ctrl-Esc> list;
764 whether item cannot be switched to (note that it is not actually
765 grayed in the C<Ctrl-Esc> list));
769 whether participates in jump sequence;
773 program type. Possible values are:
782 Although there are several other program types for WIN-OS/2 programs,
783 these do not show up in this field. Instead, the PROG_VDM or
784 PROG_WINDOWEDVDM program types are used. For instance, for
785 PROG_31_STDSEAMLESSVDM, PROG_WINDOWEDVDM is used. This is because all
786 the WIN-OS/2 programs run in DOS sessions. For example, if a program
787 is a windowed WIN-OS/2 program, it runs in a PROG_WINDOWEDVDM
788 session. Likewise, if it's a full-screen WIN-OS/2 program, it runs in
797 Optional arguments: the pid and the window-handle of the application running
798 in the OS/2 session to query.
800 =item process_hentry()
802 similar to process_entry(), but returns a hash reference, the keys being
804 title owner_hwnd icon_hwnd owner_phandle owner_pid owner_sid
805 visible nonswitchable jumpable ptype sw_entry
807 (a copy of the list of keys is in @hentry_fields).
809 =item process_entries()
811 similar to process_entry(), but returns a list of array reference for all
812 the elements in the switch list (one controlling C<Ctrl-Esc> window).
814 =item process_hentries()
816 similar to process_hentry(), but returns a list of hash reference for all
817 the elements in the switch list (one controlling C<Ctrl-Esc> window).
821 changes a process entry, arguments are the same as process_entry() returns.
823 =item change_entryh()
825 Similar to change_entry(), but takes a hash reference as an argument.
829 returns the C<owner_hwnd> of the process entry (for VIO windowed processes
830 this is the frame window of the session).
834 returns the text of the task switch menu entry of the current session.
835 (There is no way to get this info in non-standard Session Managers. This
836 implementation is a shortcut via process_entry().)
838 =item C<Title_set(newtitle)>
840 tries two different interfaces. The Session Manager one does not work
841 with some windows (if the title is set from the start).
842 This is a limitation of OS/2, in such a case $^E is set to 372 (type
846 for a funny - and wrong - explanation ;-). In such cases a
847 direct-manipulation of low-level entries is used (same as bothTitle_set()).
848 Keep in mind that some versions of OS/2 leak memory with such a manipulation.
852 returns text of the titlebar of the current process' window.
854 =item C<winTitle_set(newtitle)>
856 sets text of the titlebar of the current process' window. The change does not
857 affect the text of the switch entry of the current window.
859 =item C<swTitle_set(newtitle)>
861 sets text of the task switch menu entry of the current process' window. [There
862 is no API to query this title.] Does it via SwitchEntry interface,
863 not Session manager interface. The change does not affect the text of the
864 titlebar of the current window.
866 =item C<bothTitle_set(newtitle)>
868 sets text of the titlebar and task switch menu of the current process' window
869 via direct manipulation of the windows' texts.
871 =item C<SwitchToProgram([$sw_entry])>
873 switch to session given by a switch list handle (defaults to the entry of our process).
875 Use of this function causes another window (and its related windows)
876 of a PM session to appear on the front of the screen, or a switch to
877 another session in the case of a non-PM program. In either case,
878 the keyboard (and mouse for the non-PM case) input is directed to
883 =head2 Control of the PM windows
885 Some of these API's require sending a message to the specified window.
886 In such a case the process needs to be a PM process, or to be morphed
887 to a PM process via OS2::MorphPM().
889 For a temporary morphing to PM use L<OS2::localMorphPM class>.
891 Keep in mind that PM windows are engaged in 2 "orthogonal" window
892 trees, as well as in the z-order list.
894 One tree is given by the I<parent/child> relationship. This
895 relationship affects drawing (child is drawn relative to its parent
896 (lower-left corner), and the drawing is clipped by the parent's
897 boundary; parent may request that I<it's> drawing is clipped to be
898 confined to the outsize of the childs and/or siblings' windows);
899 hiding; minimizing/restoring; and destroying windows.
901 Another tree (not necessarily connected?) is given by I<ownership>
902 relationship. Ownership relationship assumes cooperation of the
903 engaged windows via passing messages on "important events"; e.g.,
904 scrollbars send information messages when the "bar" is moved, menus
905 send messages when an item is selected; frames
906 move/hide/unhide/minimize/restore/change-z-order-of owned frames when
907 the owner is moved/etc., and destroy the owned frames (even when these
908 frames are not descendants) when the owner is destroyed; etc. [An
909 important restriction on ownership is that owner should be created by
910 the same thread as the owned thread, so they engage in the same
913 Windows may be in many different state: Focused (take keyboard events) or not,
914 Activated (=Frame windows in the I<parent/child> tree between the root and
915 the window with the focus; usually indicate such "active state" by titlebar
916 highlights, and take mouse events) or not, Enabled/Disabled (this influences
917 the ability to update the graphic, and may change appearance, as for
918 enabled/disabled buttons), Visible/Hidden, Minimized/Maximized/Restored, Modal
921 The APIs below all die() on error with the message being $^E.
925 =item C<WindowText($hwnd)>
927 gets "a text content" of a window. Requires (morphing to) PM.
929 =item C<WindowText_set($hwnd, $text)>
931 sets "a text content" of a window. Requires (morphing to) PM.
933 =item C<($x, $y, $flags, $width, $height, $behind, @rest) = WindowPos($hwnd)>
935 gets window position info as 8 integers (of C<SWP>), in the order suitable
936 for WindowPos_set(). @rest is marked as "reserved" in PM docs. $flags
937 is a combination of C<SWP_*> constants.
939 =item C<$hash = hWindowPos($hwnd)>
941 gets window position info as a hash reference; the keys are C<flags width
942 height x y behind hwnd reserved1 reserved2>.
946 exit unless $hash->{flags} & SWP_MAXIMIZE; # Maximized
948 =item C<WindowPos_set($hwnd, $x, $y, $flags = SWP_MOVE, $width = 0, $height = 0, $behind = HWND_TOP)>
950 Set state of the window: position, size, zorder, show/hide, activation,
951 minimize/maximize/restore etc. Which of these operations to perform
952 is governed by $flags.
954 =item C<hWindowPos_set($hash, [$hwnd])>
956 Same as C<WindowPos_set>, but takes the position from keys C<fl width height
957 x y behind hwnd> of the hash referenced by $hash. If $hwnd is explicitly
958 specified, it overrides C<$hash->{hwnd}>. If $hash->{flags} is not specified,
959 it is calculated basing on the existing keys of $hash. Requires (morphing to) PM.
963 hWindowPos_set {flags => SWP_MAXIMIZE}, $hwnd; # Maximize
965 =item C<($pid, $tid) = WindowProcess($hwnd)>
967 gets I<PID> and I<TID> of the process associated to the window.
969 =item C<ClassName($hwnd)>
971 returns the class name of the window.
973 If this window is of any of the preregistered WC_* classes the class
974 name returned is in the form "#nnnnn", where "nnnnn" is a group
975 of up to five digits that corresponds to the value of the WC_* class name
980 returns the handle of the focus window. Optional argument for specifying
983 =item C<FocusWindow_set($hwnd)>
985 set the focus window by handle. Optional argument for specifying the desktop
986 to use. E.g, the first entry in program_entries() is the C<Ctrl-Esc> list.
987 To show an application, use either one of
989 WinShowWindow( $hwnd, 1 );
990 FocusWindow_set( $hwnd );
991 SwitchToProgram($switch_handle);
993 (Which work with alternative focus-to-front policies?) Requires
996 Switching focus to currently-unfocused window moves the window to the
997 front in Z-order; use FocusWindow_set_keep_Zorder() to avoid this.
999 =item C<FocusWindow_set_keep_Zorder($hwnd)>
1001 same as FocusWindow_set(), but preserves the Z-order of windows.
1003 =item C<ActiveWindow([$parentHwnd])>
1005 gets the active subwindow's handle for $parentHwnd or desktop.
1006 Returns FALSE if none.
1008 =item C<ActiveWindow_set($hwnd, [$parentHwnd])>
1010 sets the active subwindow's handle for $parentHwnd or desktop. Requires (morphing to) PM.
1012 =item C<ShowWindow($hwnd [, $show])>
1014 Set visible/hidden flag of the window. Default: $show is TRUE.
1016 =item C<EnableWindowUpdate($hwnd [, $update])>
1018 Set window visibility state flag for the window for subsequent drawing.
1019 No actual drawing is done at this moment. Use C<ShowWindow($hwnd, $state)>
1020 when redrawing is needed. While update is disabled, changes to the "window
1021 state" do not change the appearence of the window. Default: $update is TRUE.
1023 (What is manipulated is the bit C<WS_VISIBLE> of the window style.)
1025 =item C<EnableWindow($hwnd [, $enable])>
1027 Set the window enabled state. Default: $enable is TRUE.
1029 Results in C<WM_ENABLED> message sent to the window. Typically, this
1030 would change the appearence of the window. If at the moment of disabling
1031 focus is in the window (or a descendant), focus is lost (no focus anywhere).
1032 If focus is needed, it can be reassigned explicitly later.
1034 =item IsWindowEnabled(), IsWindowVisible(), IsWindowShowing()
1036 these functions take $hwnd as an argument. IsWindowEnabled() queries
1037 the state changed by EnableWindow(), IsWindowVisible() the state changed
1038 by ShowWindow(), IsWindowShowing() is true if there is a part of the window
1039 visible on the screen.
1041 =item C<PostMsg($hwnd, $msg, $mp1, $mp2)>
1043 post message to a window. The meaning of $mp1, $mp2 is specific for each
1044 message id $msg, they default to 0. E.g.,
1046 use OS2::Process qw(:DEFAULT WM_SYSCOMMAND WM_CONTEXTMENU
1047 WM_SAVEAPPLICATION WM_QUIT WM_CLOSE
1048 SC_MAXIMIZE SC_RESTORE);
1049 $hwnd = process_hentry()->{owner_hwnd};
1050 # Emulate choosing `Restore' from the window menu:
1051 PostMsg $hwnd, WM_SYSCOMMAND, MPFROMSHORT(SC_RESTORE); # Not immediate
1053 # Emulate `Show-Contextmenu' (Double-Click-2), two ways:
1054 PostMsg ActiveWindow, WM_CONTEXTMENU;
1055 PostMsg FocusWindow, WM_CONTEXTMENU;
1057 /* Emulate `Close' */
1058 PostMsg ActiveWindow, WM_CLOSE;
1060 /* Same but with some "warnings" to the application */
1061 $hwnd = ActiveWindow;
1062 PostMsg $hwnd, WM_SAVEAPPLICATION;
1063 PostMsg $hwnd, WM_CLOSE;
1064 PostMsg $hwnd, WM_QUIT;
1066 In fact, MPFROMSHORT() may be omited above.
1068 For messages to other processes, messages which take/return a pointer are
1073 The functions MPFROMSHORT(), MPVOID(), MPFROMCHAR(), MPFROM2SHORT(),
1074 MPFROMSH2CH(), MPFROMLONG() can be used the same way as from C. Use them
1075 to construct parameters $m1, $m2 to PostMsg().
1077 These functions are not exported by default.
1079 =item C<$eh = BeginEnumWindows($hwnd)>
1081 starts enumerating immediate child windows of $hwnd in z-order. The
1082 enumeration reflects the state at the moment of BeginEnumWindows() calls;
1083 use IsWindow() to be sure. All the functions in this group require (morphing to) PM.
1085 =item C<$kid_hwnd = GetNextWindow($eh)>
1087 gets the next kid in the list. Gets 0 on error or when the list ends.
1089 =item C<EndEnumWindows($eh)>
1091 End enumeration and release the list.
1093 =item C<@list = ChildWindows([$hwnd])>
1095 returns the list of child windows at the moment of the call. Same remark
1096 as for enumeration interface applies. Defaults to HWND_DESKTOP.
1101 printf ' ' x $o . "%#x\n", $h;
1102 l($o+2,$_) for ChildWindows $h;
1106 =item C<IsWindow($hwnd)>
1108 true if the window handle is still valid.
1110 =item C<QueryWindow($hwnd, $type)>
1112 gets the handle of a related window. $type should be one of C<QW_*> constants.
1114 =item C<IsChild($hwnd, $parent)>
1116 return TRUE if $hwnd is a descendant of $parent.
1118 =item C<WindowFromId($hwnd, $id)>
1120 return a window handle of a child of $hwnd with the given $id.
1122 hwndSysMenu = WinWindowFromID(hwndDlg, FID_SYSMENU);
1123 WinSendMsg(hwndSysMenu, MM_SETITEMATTR,
1124 MPFROM2SHORT(SC_CLOSE, TRUE),
1125 MPFROM2SHORT(MIA_DISABLED, MIA_DISABLED));
1127 =item C<WindowFromPoint($x, $y [, $hwndParent [, $descedantsToo]])>
1129 gets a handle of a child of $hwndParent at C<($x,$y)>. If $descedantsToo
1130 (defaulting to 1) then children of children may be returned too. May return
1131 $hwndParent (defaults to desktop) if no suitable children are found,
1132 or 0 if the point is outside the parent.
1134 $x and $y are relative to $hwndParent.
1136 =item C<EnumDlgItem($dlgHwnd, $type [, $relativeHwnd])>
1138 gets a dialog item window handle for an item of type $type of $dlgHwnd
1139 relative to $relativeHwnd, which is descendant of $dlgHwnd.
1140 $relativeHwnd may be specified if $type is EDI_FIRSTTABITEM or
1143 The return is always an immediate child of hwndDlg, even if hwnd is
1144 not an immediate child window. $type may be
1148 =item EDI_FIRSTGROUPITEM
1150 First item in the same group.
1152 =item EDI_FIRSTTABITEM
1154 First item in dialog with style WS_TABSTOP. hwnd is ignored.
1156 =item EDI_LASTGROUPITEM
1158 Last item in the same group.
1160 =item EDI_LASTTABITEM
1162 Last item in dialog with style WS_TABSTOP. hwnd is ignored.
1164 =item EDI_NEXTGROUPITEM
1166 Next item in the same group. Wraps around to beginning of group when
1167 the end of the group is reached.
1169 =item EDI_NEXTTABITEM
1171 Next item with style WS_TABSTOP. Wraps around to beginning of dialog
1172 item list when end is reached.
1174 =item EDI_PREVGROUPITEM
1176 Previous item in the same group. Wraps around to end of group when the
1177 start of the group is reached. For information on the WS_GROUP style,
1180 =item EDI_PREVTABITEM
1182 Previous item with style WS_TABSTOP. Wraps around to end of dialog
1183 item list when beginning is reached.
1187 =item DesktopWindow()
1189 gets the actual window handle of the PM desktop; most APIs accept the
1190 pseudo-handle C<HWND_DESKTOP> instead. Keep in mind that the WPS
1191 desktop (one with WindowText() being C<"Desktop">) is a different beast?!
1193 =item TopLevel($hwnd)
1195 gets the toplevel window of $hwnd.
1197 =item ResetWinError()
1199 Resets $^E. One may need to call it before the C<Win*>-class APIs which may
1200 return 0 during normal operation. In such a case one should check both
1201 for return value being zero and $^E being non-zero. The following APIs
1202 do ResetWinError() themselves, thus do not need an explicit one:
1211 This function is normally not needed. Not exported by default.
1215 =head2 Control of the PM data
1219 =item ActiveDesktopPathname()
1221 gets the path of the directory which corresponds to Desktop.
1225 gets the content of the clipboard. An optional argument is the format
1226 of the data in the clipboard (defaults to C<CF_TEXT>).
1228 Note that the usual convention is to have clipboard data with
1229 C<"\r\n"> as line separators.
1231 =item ClipbrdText_set($txt)
1233 sets the text content of the clipboard. Unless the optional argument
1234 is TRUE, will convert newlines to C<"\r\n">. Another optional
1235 argument is the format of the data in the clipboard (defaults to
1238 =item InvalidateRect
1240 =item CreateFrameControl
1242 =item ClipbrdFmtInfo
1254 =item ClipbrdData_set
1256 =item ClipbrdOwner_set
1258 =item ClipbrdViewer_set
1260 =item EnumClipbrdFmts
1276 =item SystemAtomTable
1278 =item CreateAtomTable
1280 =item DestroyAtomTable
1282 Low-level methods to access clipboard and the atom table(s).
1286 =head1 OS2::localMorphPM class
1288 This class morphs the process to PM for the duration of the given scope.
1291 my $h = OS2::localMorphPM->new(0);
1295 The argument has the same meaning as one to OS2::MorphPM(). Calls can
1296 nest with internal ones being NOPs.
1327 Document and test: Query/SetWindowULong/Short/Ptr, SetWindowBits.
1328 InvalidateRect, CreateFrameControl, ClipbrdFmtInfo ClipbrdOwner
1329 ClipbrdViewer ClipbrdData OpenClipbrd CloseClipbrd ClipbrdData_set
1330 ClipbrdOwner_set ClipbrdViewer_set EnumClipbrdFmts EmptyClipbrd
1331 AddAtom FindAtom DeleteAtom AtomUsage AtomName AtomLength
1332 SystemAtomTable CreateAtomTable DestroyAtomTable
1334 Implement SOMETHINGFROMMR.
1337 >But I wish to change the default button if the user enters some
1338 >text into an entryfield. I can detect the entry ok, but can't
1339 >seem to get the button to change to default.
1341 >No matter what message I send it, it's being ignored.
1343 You need to get the style of the buttons using WinQueryWindowULong/QWL_STYLE,
1344 set and reset the BS_DEFAULT bits as appropriate and then use
1345 WinSetWindowULong/QWL_STYLE to set the button style.
1346 Something like this:
1347 hwnd1 = WinWindowFromID (hwnd, id1);
1348 hwnd2 = WinWindowFromID (hwnd, id2);
1349 style1 = WinQueryWindowULong (hwnd1, QWL_STYLE);
1350 style2 = WinQueryWindowULong (hwnd2, QWL_STYLE);
1351 style1 |= style2 & BS_DEFAULT;
1352 style2 &= ~BS_DEFAULT;
1353 WinSetWindowULong (hwnd1, QWL_STYLE, style1);
1354 WinSetWindowULong (hwnd2, QWL_STYLE, style2);
1356 > How to do query and change a frame creation flags for existing window?
1358 Set the style bits that correspond to the FCF_* flag for the frame
1359 window and then send a WM_UPDATEFRAME message with the appropriate FCF_*
1363 ulFrameStyle = WinQueryWindowULong( WinQueryWindow(hwnd, QW_PARENT),
1365 ulFrameStyle = (ulFrameStyle & ~FS_SIZEBORDER) | FS_BORDER;
1366 WinSetWindowULong( WinQueryWindow(hwnd, QW_PARENT),
1369 WinSendMsg( WinQueryWindow(hwnd, QW_PARENT),
1371 MPFROMP(FCF_SIZEBORDER),
1374 If the FCF_* flags you want to change does not have a corresponding FS_*
1375 style (i.e. the FCF_* flag corresponds to the presence/lack of a frame
1376 control rather than a property of the frame itself) then you create or
1377 destroy the appropriate control window using the correct FID_* window
1378 identifier and then send the WM_UPDATEFRAME message with the appropriate
1381 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*
1382 | SetFrameBorder() |
1383 | Changes a frame window's border to the requested type. |
1385 | Parameters on entry: |
1386 | hwndFrame -> Frame window whose border is to be changed. |
1387 | ulBorderStyle -> Type of border to change to. |
1390 | BOOL -> Success indicator. |
1392 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
1393 BOOL SetFrameBorder( HWND hwndFrame, ULONG ulBorderType ) {
1395 BOOL fSuccess = TRUE;
1397 ulFrameStyle = WinQueryWindowULong( hwndFrame, QWL_STYLE );
1399 switch ( ulBorderType ) {
1400 case FS_SIZEBORDER :
1401 ulFrameStyle = (ulFrameStyle & ~(FS_DLGBORDER | FS_BORDER))
1406 ulFrameStyle = (ulFrameStyle & ~(FS_SIZEBORDER | FS_BORDER))
1411 ulFrameStyle = (ulFrameStyle & ~(FS_SIZEBORDER | FS_DLGBORDER))
1421 fSuccess = WinSetWindowULong( hwndFrame, QWL_STYLE, ulFrameStyle );
1424 fSuccess = (BOOL)WinSendMsg( hwndFrame, WM_UPDATEFRAME, 0, 0 );
1426 fSuccess = WinInvalidateRect( hwndFrame, NULL, TRUE );
1430 return ( fSuccess );
1432 } // End SetFrameBorder()
1434 hwndMenu=WinLoadMenu(hwndParent,NULL,WND_IMAGE);
1435 WinSetWindowUShort(hwndMenu,QWS_ID,FID_MENU);
1436 ulStyle=WinQueryWindowULong(hwndMenu,QWL_STYLE);
1437 WinSetWindowULong(hwndMenu,QWL_STYLE,ulStyle|MS_ACTIONBAR);
1438 WinSendMsg(hwndParent,WM_UPDATEFRAME,MPFROMSHORT(FCF_MENU),0L);
1440 OS/2-windows have another "parent" called the *owner*,
1441 which must be set separately - to get a close relationship:
1443 WinSetOwner (hwndFrameChild, hwndFrameMain);
1445 Now your child should move with your main window!
1446 And always stays on top of it....
1448 To avoid this, for example for dialogwindows, you can
1449 also "disconnect" this relationship with:
1451 WinSetWindowBits (hwndFrameChild, QWL_STYLE
1452 , FS_NOMOVEWITHOWNER
1453 , FS_NOMOVEWITHOWNER);
1455 Adding a button icon later:
1457 /* switch the button style to BS_MINIICON */
1458 WinSetWindowBits(hwndBtn, QWL_STYLE, BS_MINIICON, BS_MINIICON) ;
1460 /* set up button control data */
1462 bcd.cb = sizeof(BTNCDATA);
1463 bcd.hImage = WinLoadPointer(HWND_DESKTOP, dllHandle, ID_ICON_BUTTON1) ;
1464 bcd.fsCheckState = bcd.fsHiliteState = 0 ;
1468 wp.fsStatus = WPM_CTLDATA;
1471 /* add the icon on the button */
1472 WinSendMsg(hwndBtn, WM_SETWINDOWPARAMS, (MPARAM)&wp, NULL);
1474 MO> Can anyone tell what OS/2 expects of an application to be properly
1475 MO> minimized to the desktop?
1476 case WM MINMAXFRAME :
1478 BOOL fShow = ! (((PSWP) mp1)->fl & SWP MINIMIZE);
1483 WinEnableWindowUpdate ( hwnd, FALSE );
1485 for (henum=WinBeginEnumWindows(hwnd);
1486 (hwndChild = WinGetNextWindow (henum)) != 0; )
1487 WinShowWindow ( hwndChild, fShow );
1489 WinEndEnumWindows ( henum );
1490 WinEnableWindowUpdate ( hwnd, TRUE );
1494 Why C<hWindowPos DesktopWindow> gives C<< behind => HWND_TOP >>?
1498 the majority of the APIs of this module set $^E on failure (no matter
1499 whether they die() on failure or not). By the semantic of PM API
1500 which returns something other than a boolean, it is impossible to
1501 distinguish failure from a "normal" 0-return. In such cases C<$^E ==
1502 0> indicates an absence of error.
1506 In addition to symbols described above, the following constants (available
1507 also via module C<OS2::Process::Const>) are exportable. Note that these
1508 symbols live in package C<OS2::Process::Const>, they are not available
1509 by full name through C<OS2::Process>!
1511 HWND_* Standard (abstract) window handles
1513 SC_* WM_SYSCOMMAND flavor
1514 SWP_* Size/move etc flag
1515 WC_* Standard window classes
1516 PROG_* Program category (PM, VIO etc)
1517 QW_* Query-Window flag
1518 EDI_* Enumerate-Dialog-Item code
1519 WS_* Window Style flag
1520 QWS_* Query-window-UShort offsets
1521 QWP_* Query-window-pointer offsets
1522 QWL_* Query-window-ULong offsets
1523 FF_* Frame-window state flags
1524 FI_* Frame-window information flags
1525 LS_* List box styles
1527 FCF_* Frame creation flags
1530 TBM_* Title bar messages?
1531 CF_* Clipboard formats
1532 CFI_* Clipboard storage type
1533 FID_* ids of subwindows of frames
1537 whether a given API dies or returns FALSE/empty-list on error may be
1538 confusing. This may change in the future.
1542 Andreas Kaiser <ak@ananke.s.bawue.de>,
1543 Ilya Zakharevich <ilya@math.ohio-state.edu>.
1547 C<spawn*>() system calls, L<OS2::Proc> and L<OS2::WinObject> modules.