1package OS2::localMorphPM; 2# use strict; 3 4sub new { 5 my ($c,$f) = @_; 6 OS2::MorphPM($f); 7 # print STDERR ">>>>>\n"; 8 bless [$f], $c 9} 10sub DESTROY { 11 # print STDERR "<<<<<\n"; 12 OS2::UnMorphPM(shift->[0]) 13} 14 15package OS2::Process; 16 17BEGIN { 18 require Exporter; 19 require XSLoader; 20 #require AutoLoader; 21 22 our @ISA = qw(Exporter); 23 our $VERSION = "1.02"; 24 XSLoader::load('OS2::Process', $VERSION); 25} 26 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. 30our @EXPORT = qw( 31 P_BACKGROUND 32 P_DEBUG 33 P_DEFAULT 34 P_DETACH 35 P_FOREGROUND 36 P_FULLSCREEN 37 P_MAXIMIZE 38 P_MINIMIZE 39 P_NOCLOSE 40 P_NOSESSION 41 P_NOWAIT 42 P_OVERLAY 43 P_PM 44 P_QUOTE 45 P_SESSION 46 P_TILDE 47 P_UNRELATED 48 P_WAIT 49 P_WINDOWED 50 my_type 51 file_type 52 T_NOTSPEC 53 T_NOTWINDOWCOMPAT 54 T_WINDOWCOMPAT 55 T_WINDOWAPI 56 T_BOUND 57 T_DLL 58 T_DOS 59 T_PHYSDRV 60 T_VIRTDRV 61 T_PROTDLL 62 T_32BIT 63 ppid 64 ppidOf 65 sidOf 66 scrsize 67 scrsize_set 68 kbdChar 69 kbdhChar 70 kbdStatus 71 _kbdStatus_set 72 kbdhStatus 73 kbdhStatus_set 74 vioConfig 75 viohConfig 76 vioMode 77 viohMode 78 viohMode_set 79 _vioMode_set 80 _vioState 81 _vioState_set 82 vioFont 83 vioFont_set 84 process_entry 85 process_entries 86 process_hentry 87 process_hentries 88 change_entry 89 change_entryh 90 process_hwnd 91 Title_set 92 Title 93 winTitle_set 94 winTitle 95 swTitle_set 96 bothTitle_set 97 WindowText 98 WindowText_set 99 WindowPos 100 WindowPos_set 101 hWindowPos 102 hWindowPos_set 103 WindowProcess 104 SwitchToProgram 105 DesktopWindow 106 ActiveWindow 107 ActiveWindow_set 108 ClassName 109 FocusWindow 110 FocusWindow_set 111 ShowWindow 112 PostMsg 113 BeginEnumWindows 114 EndEnumWindows 115 GetNextWindow 116 IsWindow 117 ChildWindows 118 out_codepage 119 out_codepage_set 120 process_codepage_set 121 in_codepage 122 in_codepage_set 123 cursor 124 cursor_set 125 screen 126 screen_set 127 process_codepages 128 QueryWindow 129 WindowFromId 130 WindowFromPoint 131 EnumDlgItem 132 EnableWindow 133 EnableWindowUpdate 134 IsWindowEnabled 135 IsWindowVisible 136 IsWindowShowing 137 WindowPtr 138 WindowULong 139 WindowUShort 140 SetWindowBits 141 SetWindowPtr 142 SetWindowULong 143 SetWindowUShort 144 TopLevel 145 FocusWindow_set_keep_Zorder 146 147 ActiveDesktopPathname 148 InvalidateRect 149 CreateFrameControl 150 ClipbrdFmtInfo 151 ClipbrdOwner 152 ClipbrdViewer 153 ClipbrdData 154 OpenClipbrd 155 CloseClipbrd 156 ClipbrdData_set 157 ClipbrdOwner_set 158 ClipbrdViewer_set 159 EnumClipbrdFmts 160 EmptyClipbrd 161 AddAtom 162 FindAtom 163 DeleteAtom 164 AtomUsage 165 AtomName 166 AtomLength 167 SystemAtomTable 168 CreateAtomTable 169 DestroyAtomTable 170 171 _ClipbrdData_set 172 ClipbrdText 173 ClipbrdText_set 174 175 _MessageBox 176 MessageBox 177 _MessageBox2 178 MessageBox2 179 LoadPointer 180 SysPointer 181 Alarm 182 FlashWindow 183 184 get_title 185 set_title 186); 187our @EXPORT_OK = qw( 188 ResetWinError 189 MPFROMSHORT 190 MPVOID 191 MPFROMCHAR 192 MPFROM2SHORT 193 MPFROMSH2CH 194 MPFROMLONG 195); 196 197our $AUTOLOAD; 198 199sub AUTOLOAD { 200 # This AUTOLOAD is used to 'autoload' constants from the constant() 201 # XS function. If a constant is not found then control is passed 202 # to the AUTOLOAD in AutoLoader. 203 204 (my $constname = $AUTOLOAD) =~ s/.*:://; 205 my $val = constant($constname, @_ ? $_[0] : 0); 206 if ($! != 0) { 207 if ($! =~ /Invalid/ || $!{EINVAL}) { 208 die "Unsupported function $AUTOLOAD" 209 } else { 210 my ($pack,$file,$line) = caller; 211 die "Your vendor has not defined OS2::Process macro $constname, used at $file line $line. 212"; 213 } 214 } 215 eval "sub $AUTOLOAD { $val }"; 216 goto &$AUTOLOAD; 217} 218 219sub const_import { 220 require OS2::Process::Const; 221 my $sym = shift; 222 my ($err, $val) = OS2::Process::Const::constant($sym); 223 die $err if $err; 224 my $p = caller(1); 225 226 # no strict; 227 228 *{"$p\::$sym"} = sub () { $val }; 229 (); # needed by import() 230} 231 232sub import { 233 my $class = shift; 234 my $ini = @_; 235 @_ = ($class, 236 map { 237 /^(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($_) : $_ 238 } @_); 239 goto &Exporter::import if @_ > 1 or $ini == 0; 240} 241 242# Preloaded methods go here. 243 244sub Title () { (process_entry())[0] } 245 246# *Title_set = \&sesmgr_title_set; 247 248sub swTitle_set_sw { 249 my ($title, @sw) = @_; 250 $sw[0] = $title; 251 change_entry(@sw); 252} 253 254sub swTitle_set ($) { 255 my (@sw) = process_entry(); 256 swTitle_set_sw(shift, @sw); 257} 258 259sub winTitle_set_sw { 260 my ($title, @sw) = @_; 261 my $h = OS2::localMorphPM->new(0); 262 WindowText_set $sw[1], $title; 263} 264 265sub winTitle_set ($) { 266 my (@sw) = process_entry(); 267 winTitle_set_sw(shift, @sw); 268} 269 270sub winTitle () { 271 my (@sw) = process_entry(); 272 my $h = OS2::localMorphPM->new(0); 273 WindowText $sw[1]; 274} 275 276sub bothTitle_set ($) { 277 my (@sw) = process_entry(); 278 my $t = shift; 279 winTitle_set_sw($t, @sw); 280 swTitle_set_sw($t, @sw); 281} 282 283sub Title_set ($) { 284 my $t = shift; 285 return 1 if sesmgr_title_set($t); 286 return 0 unless $^E == 372; 287 my (@sw) = process_entry(); 288 winTitle_set_sw($t, @sw); 289 swTitle_set_sw($t, @sw); 290} 291 292sub process_entry { swentry_expand(process_swentry(@_)) } 293 294our @hentry_fields = qw( title owner_hwnd icon_hwnd 295 owner_phandle owner_pid owner_sid 296 visible nonswitchable jumpable ptype sw_entry ); 297 298sub swentry_hexpand ($) { 299 my %h; 300 @h{@hentry_fields} = swentry_expand(shift); 301 \%h; 302} 303 304sub process_hentry { swentry_hexpand(process_swentry(@_)) } 305sub process_hwnd { process_hentry()->{owner_hwnd} } 306 307my $swentry_size = swentry_size(); 308 309sub sw_entries () { 310 my $s = swentries_list(); 311 my ($c, $s1) = unpack 'La*', $s; 312 die "Unconsistent size in swentries_list()" unless 4+$c*$swentry_size == length $s; 313 my (@l, $e); 314 push @l, $e while $e = substr $s1, 0, $swentry_size, ''; 315 @l; 316} 317 318sub process_entries () { 319 map [swentry_expand($_)], sw_entries; 320} 321 322sub process_hentries () { 323 map swentry_hexpand($_), sw_entries; 324} 325 326sub change_entry { 327 change_swentry(create_swentry(@_)); 328} 329 330sub create_swentryh ($) { 331 my $h = shift; 332 create_swentry(@$h{@hentry_fields}); 333} 334 335sub change_entryh ($) { 336 change_swentry(create_swentryh(shift)); 337} 338 339# Massage entries into the same order as WindowPos_set: 340sub WindowPos ($) { 341 my ($fl, $h, $w, $y, $x, $behind, $hwnd, @rest) 342 = unpack 'L l4 L4', WindowSWP(shift); 343 ($x, $y, $fl, $w, $h, $behind, @rest); 344} 345 346# Put them into a hash 347sub hWindowPos ($) { 348 my %h; 349 @h{ qw(flags height width y x behind hwnd reserved1 reserved2) } 350 = unpack 'L l4 L4', WindowSWP(shift); 351 \%h; 352} 353 354my @SWP_keys = ( [qw(width height)], # SWP_SIZE=1 355 [qw(x y)], # SWP_MOVE=2 356 [qw(behind)] ); # SWP_ZORDER=3 357my %SWP_def; 358@SWP_def{ map @$_, @SWP_keys } = (0) x 20; 359 360# Get them from a hash 361sub hWindowPos_set ($$) { 362 my $hash = shift; 363 my $hwnd = (@_ ? shift : $hash->{hwnd} ); 364 my $flags; 365 if (exists $hash->{flags}) { 366 $flags = $hash->{flags}; 367 } else { # Set flags according to existing keys in $hash 368 $flags = 0; 369 for my $bit (0..2) { 370 exists $hash->{$_} and $flags |= (1<<$bit) for @{$SWP_keys[$bit]}; 371 } 372 } 373 for my $bit (0..2) { # Check for required keys 374 next unless $flags & (1<<$bit); 375 exists $hash->{$_} 376 or die sprintf "key $_ required for flags=%#x", $flags 377 for @{$SWP_keys[$bit]}; 378 } 379 my %h = (%SWP_def, flags => $flags, %$hash); # Avoid warnings 380 my ($x, $y, $fl, $w, $h, $behind) = @h{ qw(x y flags width height behind) }; 381 WindowPos_set($hwnd, $x, $y, $fl, $w, $h, $behind); 382} 383 384sub ChildWindows (;$) { 385 my $hm = OS2::localMorphPM->new(0); 386 my @kids; 387 my $h = BeginEnumWindows(@_ ? shift : 1); # HWND_DESKTOP 388 my $w; 389 push @kids, $w while $w = GetNextWindow $h; 390 EndEnumWindows $h; 391 @kids; 392} 393 394sub TopLevel ($) { 395 my $d = DesktopWindow; 396 my $w = shift; 397 while (1) { 398 my $p = QueryWindow $w, 5; # QW_PARENT; 399 return $w if not $p or $p == $d; 400 $w = $p; 401 } 402} 403 404sub FocusWindow_set_keep_Zorder ($) { 405 my $w = shift; 406 my $t = TopLevel $w; 407 my $b = hWindowPos($t)->{behind}; # we are behind this 408 EnableWindowUpdate($t, 0); 409 FocusWindow_set($w); 410# sleep 1; # Make flicker stronger when present 411 hWindowPos_set {behind => $b}, $t; 412 EnableWindowUpdate($t, 1); 413} 414 415sub ClipbrdText (@) { 416 my $morph = OS2::localMorphPM->new(0); 417 OpenClipbrd(); 418 my $txt = unpack 'p', pack 'L', ClipbrdData @_; 419 CloseClipbrd(); 420 $txt; 421} 422 423sub ClipbrdText_set ($;$) { 424 my $morph = OS2::localMorphPM->new(0); 425 OpenClipbrd(); 426 EmptyClipbrd(); # It may contain other types 427 my ($txt, $no_convert_nl) = (shift, shift); 428 ClipbrdData_set($txt, !$no_convert_nl, @_); 429 CloseClipbrd(); 430} 431 432sub MessageBox ($;$$$$$) { 433 my $morph = OS2::localMorphPM->new(0); 434 die "MessageBox needs text" unless @_; 435 push @_ , ($0 eq '-e' ? "Perl one-liner's message" : "$0 message") if @_ == 1; 436 &_MessageBox; 437} 438 439my %pointers; 440 441sub get_pointer ($;$$) { 442 my $id = $_[0]; 443 return $pointers{$id} if exists $pointers{$id}; 444 $pointers{$id} = &SysPointer; 445} 446 447# $button needs to be of the form 'String', ['String'] or ['String', flag]. 448# If ['String'], it is assumed the default button; same for 'String' if $only 449# is set. 450sub process_MB2 ($$;$) { 451 die "process_MB2() needs 2 arguments, got '@_'" unless @_ == 2 or @_ == 3; 452 my ($button, $ret, $only) = @_; 453 # default is BS_PUSHBUTTON, add BS_DEFAULT if $only is set 454 $button = [$button, $only ? 0x400 : 0] unless ref $button eq 'ARRAY'; 455 push @$button, 0x400 if @$button == 1; # BS_PUSHBUTTON|BS_DEFAULT 456 die "Button needs to be of the form 'String', ['String'] or ['String', flag]" 457 unless @$button == 2; 458 pack "Z71 x L l", $button->[0], $ret, $button->[1]; # name, retval, flag 459} 460 461# If one button, make it the default one even if it is of 'String' => val form. 462# If icon is of the form 'SP#<number>', load this via SysPointer. 463sub process_MB2_INFO ($;$$$) { 464 my $l = 0; 465 my $out; 466 die "process_MB2_INFO() needs 1..4 arguments" unless @_ and @_ < 5; 467 my $buttons = shift; 468 die "Buttons array should consist of pairs" if @$buttons % 2; 469 470 push @_, 0 unless @_; # Icon id (pointer) 471 # Box flags (MB_MOVABLE and MB_INFORMATION or MB_CUSTOMICON) 472 push @_, ($_[0] ? 0x4080 : 0x4030) unless @_ > 1; 473 push @_, 0 unless @_ > 2; # Notify window 474 475 my ($icon, $style, $notify) = (shift, shift, shift); 476 $icon = get_pointer $1 if $icon =~ /^SP#(\d+)\z/; 477 $out = pack "L L L L", # icon, #buttons, style, notify, buttons 478 $icon, @$buttons/2, $style, $notify; 479 $out .= join '', 480 map process_MB2($buttons->[2*$_], $buttons->[2*$_+1], @$buttons == 2), 481 0..@$buttons/2-1; 482 pack('L', length(pack 'L', 0) + length $out) . $out; 483} 484 485# MessageBox2 'Try this', OS2::Process::process_MB2_INFO([['Dismiss', 0] => 0x1000], OS2::Process::get_pointer(22),0x4080,0), 'me', 1, 0, 0 486# or the shortcut 487# MessageBox2 'Try this', [[['Dismiss', 0] => 0x1000], 'SP#22'], 'me' 488# 0x80 means MB_CUSTOMICON (does not focus?!). This focuses: 489# MessageBox2 'Try this', [[['Dismiss',0x400] => 0x1000], 0, 0x4030,0] 490# 0x400 means BS_DEFAULT. This is the same as the shortcut 491# MessageBox2 'Try this', [[Dismiss => 0x1000]] 492sub MessageBox2 ($;$$$$$) { 493 my $morph = OS2::localMorphPM->new(0); 494 die "MessageBox needs text" unless @_; 495 push @_ , [[Dismiss => 0x1000], # Name, retval (BS_PUSHBUTTON|BS_DEFAULT) 496 #0, # get_pointer(11), # SPTR_ICONINFORMATION 497 #0x4030, # MB_MOVEABLE | MB_INFORMATION 498 #0, # Notify window; was 1==HWND_DESKTOP 499 ] if @_ == 1; 500 push @_ , ($0 eq '-e' ? "Perl one-liner's message" : "$0's message") if @_ == 2; 501 $_[1] = &process_MB2_INFO(@{$_[1]}) if ref($_[1]) eq 'ARRAY'; 502 &_MessageBox2; 503} 504 505# backward compatibility 506*set_title = \&Title_set; 507*get_title = \&Title; 508 509# adapter; display; cbMemory; Configuration; VDHVersion; Flags; HWBufferSize; 510# FullSaveSize; PartSaveSize; EMAdaptersOFF; EMDisplaysOFF; 511sub vioConfig (;$$) { 512 my $data = &_vioConfig; 513 my @out = unpack 'x[S]SSLSSSLLLSS', $data; 514 # If present, offset points to S/S (with only the first work making sense) 515 my (@adaptersEMU, @displayEMU); 516 @displaysEMU = unpack("x[$out[10]]S/S", $data), pop @out if @out > 10; 517 @adaptersEMU = unpack("x[$out[ 9]]S/S", $data), pop @out if @out > 9; 518 $out[9] = $adaptersEMU[0] if @adaptersEMU; 519 $out[10] = $displaysEMU[0] if @displaysEMU; 520 @out; 521} 522 523my @vioConfig = qw(adapter display cbMemory Configuration VDHVersion Flags 524 HWBufferSize FullSaveSize PartSaveSize EMAdapters EMDisplays); 525 526sub viohConfig (;$$) { 527 my %h; 528 @h{@vioConfig} = &vioConfig; 529 %h; 530} 531 532# fbType; color; col; row; hres; vres; fmt_ID; attrib; buf_addr; buf_length; 533# full_length; partial_length; ext_data_addr; 534sub vioMode() {unpack 'x[S]CCSSSSCCLLLLL', _vioMode} 535 536my @vioMode = qw( fbType color col row hres vres fmt_ID attrib buf_addr 537 buf_length full_length partial_length ext_data_addr); 538 539sub viohMode() { 540 my %h; 541 @h{@vioMode} = vioMode; 542 %h; 543} 544 545sub viohMode_set { 546 my %h = (viohMode, @_); 547 my $o = pack 'x[S]CCSSSSCCLLLLL', @h{@vioMode}; 548 $o = pack 'SCCSSSSCCLLLLL', length $o, @h{@vioMode}; 549 _vioMode_set($o); 550} 551 552sub kbdChar (;$$) {unpack 'CCCCSL', &_kbdChar} 553 554my @kbdChar = qw(ascii scancode status nlsstate shifts time); 555sub kbdhChar (;$$) { 556 my %h; 557 @h{@kbdChar} = &kbdChar; 558 %h 559} 560 561sub kbdStatus (;$) {unpack 'x[S]SSSS', &_kbdStatus} 562my @kbdStatus = qw(state turnChar intCharFlags shifts); 563sub kbdhStatus (;$) { 564 my %h; 565 @h{@kbdStatus} = &kbdStatus; 566 %h 567} 568sub kbdhStatus_set { 569 my $h = (@_ % 2 ? shift @_ : 0); 570 my %h = (kbdhStatus($h), @_); 571 my $o = pack 'x[S]SSSS', @h{@kbdStatus}; 572 $o = pack 'SSSSS', length $o, @h{@kbdStatus}; 573 _kbdStatus_set($o,$h); 574} 575 576 577# Autoload methods go after __END__, and are processed by the autosplit program. 578 5791; 580__END__ 581 582=head1 NAME 583 584OS2::Process - exports constants for system() call, and process control on OS2. 585 586=head1 SYNOPSIS 587 588 use OS2::Process; 589 $pid = system(P_PM | P_BACKGROUND, "epm.exe"); 590 591=head1 DESCRIPTION 592 593=head2 Optional argument to system() 594 595the builtin function system() under OS/2 allows an optional first 596argument which denotes the mode of the process. Note that this argument is 597recognized only if it is strictly numerical. 598 599You can use either one of the process modes: 600 601 P_WAIT (0) = wait until child terminates (default) 602 P_NOWAIT = do not wait until child terminates 603 P_SESSION = new session 604 P_DETACH = detached 605 P_PM = PM program 606 607and optionally add PM and session option bits: 608 609 P_DEFAULT (0) = default 610 P_MINIMIZE = minimized 611 P_MAXIMIZE = maximized 612 P_FULLSCREEN = fullscreen (session only) 613 P_WINDOWED = windowed (session only) 614 615 P_FOREGROUND = foreground (if running in foreground) 616 P_BACKGROUND = background 617 618 P_NOCLOSE = don't close window on exit (session only) 619 620 P_QUOTE = quote all arguments 621 P_TILDE = MKS argument passing convention 622 P_UNRELATED = do not kill child when father terminates 623 624=head2 Access to process properties 625 626On OS/2 processes have the usual I<parent/child> semantic; 627additionally, there is a hierarchy of sessions with their own 628I<parent/child> tree. A session is either a FS session, or a windowed 629pseudo-session created by PM. A session is a "unit of user 630interaction", a change to in/out settings in one of them does not 631affect other sessions. 632 633=over 634 635=item my_type() 636 637returns the type of the current process (one of 638"FS", "DOS", "VIO", "PM", "DETACH" and "UNKNOWN"), or C<undef> on error. 639 640=item C<file_type(file)> 641 642returns the type of the executable file C<file>, or 643dies on error. The bits 0-2 of the result contain one of the values 644 645=over 646 647=item C<T_NOTSPEC> (0) 648 649Application type is not specified in the executable header. 650 651=item C<T_NOTWINDOWCOMPAT> (1) 652 653Application type is not-window-compatible. 654 655=item C<T_WINDOWCOMPAT> (2) 656 657Application type is window-compatible. 658 659=item C<T_WINDOWAPI> (3) 660 661Application type is window-API. 662 663=back 664 665The remaining bits should be masked with the following values to 666determine the type of the executable: 667 668=over 669 670=item C<T_BOUND> (8) 671 672Set to 1 if the executable file has been "bound" (by the BIND command) 673as a Family API application. Bits 0, 1, and 2 still apply. 674 675=item C<T_DLL> (0x10) 676 677Set to 1 if the executable file is a dynamic link library (DLL) 678module. Bits 0, 1, 2, 3, and 5 will be set to 0. 679 680=item C<T_DOS> (0x20) 681 682Set to 1 if the executable file is in PC/DOS format. Bits 0, 1, 2, 3, 683and 4 will be set to 0. 684 685=item C<T_PHYSDRV> (0x40) 686 687Set to 1 if the executable file is a physical device driver. 688 689=item C<T_VIRTDRV> (0x80) 690 691Set to 1 if the executable file is a virtual device driver. 692 693=item C<T_PROTDLL> (0x100) 694 695Set to 1 if the executable file is a protected-memory dynamic link 696library module. 697 698=item C<T_32BIT> (0x4000) 699 700Set to 1 for 32-bit executable files. 701 702=back 703 704file_type() may croak with one of the strings C<"Invalid EXE 705signature"> or C<"EXE marked invalid"> to indicate typical error 706conditions. If given non-absolute path, will look on C<PATH>, will 707add extension F<.exe> if no extension is present (add extension F<.> 708to suppress). 709 710=item C<@list = process_codepages()> 711 712the first element is the currently active codepage, up to 2 additional 713entries specify the system's "prepared codepages": the codepages the 714user can switch to. The active codepage of a process is one of the 715prepared codepages of the system (if present). 716 717=item C<process_codepage_set($cp)> 718 719sets the currently active codepage. [Affects printer output, in/out 720codepages of sessions started by this process, and the default 721codepage for drawing in PM; is inherited by kids. Does not affect the 722out- and in-codepages of the session.] 723 724=item ppid() 725 726returns the PID of the parent process. 727 728=item C<ppidOf($pid = $$)> 729 730returns the PID of the parent process of $pid. -1 on error. 731 732=item C<sidOf($pid = $$)> 733 734returns the session id of the process id $pid. -1 on error. 735 736=back 737 738=head2 Control of VIO sessions 739 740VIO applications are applications running in a text-mode session. 741 742=over 743 744=item out_codepage() 745 746gets code page used for screen output (glyphs). -1 means that a user font 747was loaded. 748 749=item C<out_codepage_set($cp)> 750 751sets code page used for screen output (glyphs). -1 switches to a preloaded 752user font. -2 switches off the preloaded user font. 753 754=item in_codepage() 755 756gets code page used for keyboard input. 0 means that a hardware codepage 757is used. 758 759=item C<in_codepage_set($cp)> 760 761sets code page used for keyboard input. 762 763=item C<($w, $h) = scrsize()> 764 765width and height of the given console window in character cells. 766 767=item C<scrsize_set([$w, ] $h)> 768 769set height (and optionally width) of the given console window in 770character cells. Use 0 size to keep the old size. 771 772=item C<($s, $e, $w, $a) = cursor()> 773 774gets start/end lines of the blinking cursor in the charcell, its width 775(1 on text modes) and attribute (-1 for hidden, in text modes other 776values mean visible, in graphic modes color). 777 778=item C<cursor_set($s, $e, [$w [, $a]])> 779 780sets start/end lines of the blinking cursor in the charcell. Negative 781values mean percents of the character cell height. 782 783=item screen() 784 785gets a buffer with characters and attributes of the screen. 786 787=item C<screen_set($buffer)> 788 789restores the screen given the result of screen(). E.g., if the file 790C<$file> contains the screen contents, then 791 792 open IN, $file or die; 793 binmode IN; 794 read IN, $in, -s IN; 795 $s = screen; 796 $in .= qq(\0) x (length($s) - length $in); 797 substr($in, length $s) = ''; 798 screen_set $in; 799 800will restore the screen content even if the height of the window 801changed (if the width changed, more manipulation is needed). 802 803=back 804 805=head2 Control of the process list 806 807With the exception of Title_set(), all these calls require that PM is 808running, they would not work under alternative Session Managers. 809 810=over 811 812=item process_entry() 813 814returns a list of the following data: 815 816=over 817 818=item 819 820Title of the process (in the C<Ctrl-Esc> list); 821 822=item 823 824window handle of switch entry of the process (in the C<Ctrl-Esc> list); 825 826=item 827 828window handle of the icon of the process; 829 830=item 831 832process handle of the owner of the entry in C<Ctrl-Esc> list; 833 834=item 835 836process id of the owner of the entry in C<Ctrl-Esc> list; 837 838=item 839 840session id of the owner of the entry in C<Ctrl-Esc> list; 841 842=item 843 844whether visible in C<Ctrl-Esc> list; 845 846=item 847 848whether item cannot be switched to (note that it is not actually 849grayed in the C<Ctrl-Esc> list)); 850 851=item 852 853whether participates in jump sequence; 854 855=item 856 857program type. Possible values are: 858 859 PROG_DEFAULT 0 860 PROG_FULLSCREEN 1 861 PROG_WINDOWABLEVIO 2 862 PROG_PM 3 863 PROG_VDM 4 864 PROG_WINDOWEDVDM 7 865 866Although there are several other program types for WIN-OS/2 programs, 867these do not show up in this field. Instead, the PROG_VDM or 868PROG_WINDOWEDVDM program types are used. For instance, for 869PROG_31_STDSEAMLESSVDM, PROG_WINDOWEDVDM is used. This is because all 870the WIN-OS/2 programs run in DOS sessions. For example, if a program 871is a windowed WIN-OS/2 program, it runs in a PROG_WINDOWEDVDM 872session. Likewise, if it's a full-screen WIN-OS/2 program, it runs in 873a PROG_VDM session. 874 875=item 876 877switch-entry handle. 878 879=back 880 881Optional arguments: the pid and the window-handle of the application running 882in the OS/2 session to query. 883 884=item process_hentry() 885 886similar to process_entry(), but returns a hash reference, the keys being 887 888 title owner_hwnd icon_hwnd owner_phandle owner_pid owner_sid 889 visible nonswitchable jumpable ptype sw_entry 890 891(a copy of the list of keys is in @hentry_fields). 892 893=item process_entries() 894 895similar to process_entry(), but returns a list of array reference for all 896the elements in the switch list (one controlling C<Ctrl-Esc> window). 897 898=item process_hentries() 899 900similar to process_hentry(), but returns a list of hash reference for all 901the elements in the switch list (one controlling C<Ctrl-Esc> window). 902 903=item change_entry() 904 905changes a process entry, arguments are the same as process_entry() returns. 906 907=item change_entryh() 908 909Similar to change_entry(), but takes a hash reference as an argument. 910 911=item process_hwnd() 912 913returns the C<owner_hwnd> of the process entry (for VIO windowed processes 914this is the frame window of the session). 915 916=item Title() 917 918returns the text of the task switch menu entry of the current session. 919(There is no way to get this info in non-standard Session Managers. This 920implementation is a shortcut via process_entry().) 921 922=item C<Title_set(newtitle)> 923 924tries two different interfaces. The Session Manager one does not work 925with some windows (if the title is set from the start). 926This is a limitation of OS/2, in such a case $^E is set to 372 (type 927 928 help 372 929 930for a funny - and wrong - explanation ;-). In such cases a 931direct-manipulation of low-level entries is used (same as bothTitle_set()). 932Keep in mind that some versions of OS/2 leak memory with such a manipulation. 933 934=item winTitle() 935 936returns text of the titlebar of the current process' window. 937 938=item C<winTitle_set(newtitle)> 939 940sets text of the titlebar of the current process' window. The change does not 941affect the text of the switch entry of the current window. 942 943=item C<swTitle_set(newtitle)> 944 945sets text of the task switch menu entry of the current process' window. [There 946is no API to query this title.] Does it via SwitchEntry interface, 947not Session manager interface. The change does not affect the text of the 948titlebar of the current window. 949 950=item C<bothTitle_set(newtitle)> 951 952sets text of the titlebar and task switch menu of the current process' window 953via direct manipulation of the windows' texts. 954 955=item C<SwitchToProgram([$sw_entry])> 956 957switch to session given by a switch list handle (defaults to the entry of our process). 958 959Use of this function causes another window (and its related windows) 960of a PM session to appear on the front of the screen, or a switch to 961another session in the case of a non-PM program. In either case, 962the keyboard (and mouse for the non-PM case) input is directed to 963the new program. 964 965=back 966 967=head2 Control of the PM windows 968 969Some of these API's require sending a message to the specified window. 970In such a case the process needs to be a PM process, or to be morphed 971to a PM process via OS2::MorphPM(). 972 973For a temporary morphing to PM use L<OS2::localMorphPM class>. 974 975Keep in mind that PM windows are engaged in 2 "orthogonal" window 976trees, as well as in the z-order list. 977 978One tree is given by the I<parent/child> relationship. This 979relationship affects drawing (child is drawn relative to its parent 980(lower-left corner), and the drawing is clipped by the parent's 981boundary; parent may request that I<it's> drawing is clipped to be 982confined to the outsize of the childs and/or siblings' windows); 983hiding; minimizing/restoring; and destroying windows. 984 985Another tree (not necessarily connected?) is given by I<ownership> 986relationship. Ownership relationship assumes cooperation of the 987engaged windows via passing messages on "important events"; e.g., 988scrollbars send information messages when the "bar" is moved, menus 989send messages when an item is selected; frames 990move/hide/unhide/minimize/restore/change-z-order-of owned frames when 991the owner is moved/etc., and destroy the owned frames (even when these 992frames are not descendants) when the owner is destroyed; etc. [An 993important restriction on ownership is that owner should be created by 994the same thread as the owned thread, so they engage in the same 995message queue.] 996 997Windows may be in many different state: Focused (take keyboard events) or not, 998Activated (=Frame windows in the I<parent/child> tree between the root and 999the window with the focus; usually indicate such "active state" by titlebar 1000highlights, and take mouse events) or not, Enabled/Disabled (this influences 1001the ability to update the graphic, and may change appearance, as for 1002enabled/disabled buttons), Visible/Hidden, Minimized/Maximized/Restored, Modal 1003or not, etc. 1004 1005The APIs below all die() on error with the message being $^E. 1006 1007=over 1008 1009=item C<WindowText($hwnd)> 1010 1011gets "a text content" of a window. Requires (morphing to) PM. 1012 1013=item C<WindowText_set($hwnd, $text)> 1014 1015sets "a text content" of a window. Requires (morphing to) PM. 1016 1017=item C<($x, $y, $flags, $width, $height, $behind, @rest) = WindowPos($hwnd)> 1018 1019gets window position info as 8 integers (of C<SWP>), in the order suitable 1020for WindowPos_set(). @rest is marked as "reserved" in PM docs. $flags 1021is a combination of C<SWP_*> constants. 1022 1023=item C<$hash = hWindowPos($hwnd)> 1024 1025gets window position info as a hash reference; the keys are C<flags width 1026height x y behind hwnd reserved1 reserved2>. 1027 1028Example: 1029 1030 exit unless $hash->{flags} & SWP_MAXIMIZE; # Maximized 1031 1032=item C<WindowPos_set($hwnd, $x, $y, $flags = SWP_MOVE, $width = 0, $height = 0, $behind = HWND_TOP)> 1033 1034Set state of the window: position, size, zorder, show/hide, activation, 1035minimize/maximize/restore etc. Which of these operations to perform 1036is governed by $flags. 1037 1038=item C<hWindowPos_set($hash, [$hwnd])> 1039 1040Same as C<WindowPos_set>, but takes the position from keys C<fl width height 1041x y behind hwnd> of the hash referenced by $hash. If $hwnd is explicitly 1042specified, it overrides C<$hash->{hwnd}>. If $hash->{flags} is not specified, 1043it is calculated basing on the existing keys of $hash. Requires (morphing to) PM. 1044 1045Example: 1046 1047 hWindowPos_set {flags => SWP_MAXIMIZE}, $hwnd; # Maximize 1048 1049=item C<($pid, $tid) = WindowProcess($hwnd)> 1050 1051gets I<PID> and I<TID> of the process associated to the window. 1052 1053=item C<ClassName($hwnd)> 1054 1055returns the class name of the window. 1056 1057If this window is of any of the preregistered WC_* classes the class 1058name returned is in the form "#nnnnn", where "nnnnn" is a group 1059of up to five digits that corresponds to the value of the WC_* class name 1060constant. 1061 1062=item FocusWindow() 1063 1064returns the handle of the focus window. Optional argument for specifying 1065the desktop to use. 1066 1067=item C<FocusWindow_set($hwnd)> 1068 1069set the focus window by handle. Optional argument for specifying the desktop 1070to use. E.g, the first entry in program_entries() is the C<Ctrl-Esc> list. 1071To show an application, use either one of 1072 1073 WinShowWindow( $hwnd, 1 ); 1074 FocusWindow_set( $hwnd ); 1075 SwitchToProgram($switch_handle); 1076 1077(Which work with alternative focus-to-front policies?) Requires 1078(morphing to) PM. 1079 1080Switching focus to currently-unfocused window moves the window to the 1081front in Z-order; use FocusWindow_set_keep_Zorder() to avoid this. 1082 1083=item C<FocusWindow_set_keep_Zorder($hwnd)> 1084 1085same as FocusWindow_set(), but preserves the Z-order of windows. 1086 1087=item C<ActiveWindow([$parentHwnd])> 1088 1089gets the active subwindow's handle for $parentHwnd or desktop. 1090Returns FALSE if none. 1091 1092=item C<ActiveWindow_set($hwnd, [$parentHwnd])> 1093 1094sets the active subwindow's handle for $parentHwnd or desktop. Requires (morphing to) PM. 1095 1096=item C<ShowWindow($hwnd [, $show])> 1097 1098Set visible/hidden flag of the window. Default: $show is TRUE. 1099 1100=item C<EnableWindowUpdate($hwnd [, $update])> 1101 1102Set window visibility state flag for the window for subsequent drawing. 1103No actual drawing is done at this moment. Use C<ShowWindow($hwnd, $state)> 1104when redrawing is needed. While update is disabled, changes to the "window 1105state" do not change the appearance of the window. Default: $update is TRUE. 1106 1107(What is manipulated is the bit C<WS_VISIBLE> of the window style.) 1108 1109=item C<EnableWindow($hwnd [, $enable])> 1110 1111Set the window enabled state. Default: $enable is TRUE. 1112 1113Results in C<WM_ENABLED> message sent to the window. Typically, this 1114would change the appearence of the window. If at the moment of disabling 1115focus is in the window (or a descendant), focus is lost (no focus anywhere). 1116If focus is needed, it can be reassigned explicitly later. 1117 1118=item IsWindowEnabled(), IsWindowVisible(), IsWindowShowing() 1119 1120these functions take $hwnd as an argument. IsWindowEnabled() queries 1121the state changed by EnableWindow(), IsWindowVisible() the state changed 1122by ShowWindow(), IsWindowShowing() is true if there is a part of the window 1123visible on the screen. 1124 1125=item C<PostMsg($hwnd, $msg, $mp1, $mp2)> 1126 1127post message to a window. The meaning of $mp1, $mp2 is specific for each 1128message id $msg, they default to 0. E.g., 1129 1130 use OS2::Process qw(:DEFAULT WM_SYSCOMMAND WM_CONTEXTMENU 1131 WM_SAVEAPPLICATION WM_QUIT WM_CLOSE 1132 SC_MAXIMIZE SC_RESTORE); 1133 $hwnd = process_hentry()->{owner_hwnd}; 1134 # Emulate choosing `Restore' from the window menu: 1135 PostMsg $hwnd, WM_SYSCOMMAND, MPFROMSHORT(SC_RESTORE); # Not immediate 1136 1137 # Emulate `Show-Contextmenu' (Double-Click-2), two ways: 1138 PostMsg ActiveWindow, WM_CONTEXTMENU; 1139 PostMsg FocusWindow, WM_CONTEXTMENU; 1140 1141 /* Emulate `Close' */ 1142 PostMsg ActiveWindow, WM_CLOSE; 1143 1144 /* Same but with some "warnings" to the application */ 1145 $hwnd = ActiveWindow; 1146 PostMsg $hwnd, WM_SAVEAPPLICATION; 1147 PostMsg $hwnd, WM_CLOSE; 1148 PostMsg $hwnd, WM_QUIT; 1149 1150In fact, MPFROMSHORT() may be omitted above. 1151 1152For messages to other processes, messages which take/return a pointer are 1153not supported. 1154 1155=item C<MP*()> 1156 1157The functions MPFROMSHORT(), MPVOID(), MPFROMCHAR(), MPFROM2SHORT(), 1158MPFROMSH2CH(), MPFROMLONG() can be used the same way as from C. Use them 1159to construct parameters $m1, $m2 to PostMsg(). 1160 1161These functions are not exported by default. 1162 1163=item C<$eh = BeginEnumWindows($hwnd)> 1164 1165starts enumerating immediate child windows of $hwnd in z-order. The 1166enumeration reflects the state at the moment of BeginEnumWindows() calls; 1167use IsWindow() to be sure. All the functions in this group require (morphing to) PM. 1168 1169=item C<$kid_hwnd = GetNextWindow($eh)> 1170 1171gets the next kid in the list. Gets 0 on error or when the list ends. 1172 1173=item C<EndEnumWindows($eh)> 1174 1175End enumeration and release the list. 1176 1177=item C<@list = ChildWindows([$hwnd])> 1178 1179returns the list of child windows at the moment of the call. Same remark 1180as for enumeration interface applies. Defaults to HWND_DESKTOP. 1181Example of usage: 1182 1183 sub l { 1184 my ($o,$h) = @_; 1185 printf ' ' x $o . "%#x\n", $h; 1186 l($o+2,$_) for ChildWindows $h; 1187 } 1188 l 0, $HWND_DESKTOP 1189 1190=item C<IsWindow($hwnd)> 1191 1192true if the window handle is still valid. 1193 1194=item C<QueryWindow($hwnd, $type)> 1195 1196gets the handle of a related window. $type should be one of C<QW_*> constants. 1197 1198=item C<IsChild($hwnd, $parent)> 1199 1200return TRUE if $hwnd is a descendant of $parent. 1201 1202=item C<WindowFromId($hwnd, $id)> 1203 1204return a window handle of a child of $hwnd with the given $id. 1205 1206 hwndSysMenu = WinWindowFromID(hwndDlg, FID_SYSMENU); 1207 WinSendMsg(hwndSysMenu, MM_SETITEMATTR, 1208 MPFROM2SHORT(SC_CLOSE, TRUE), 1209 MPFROM2SHORT(MIA_DISABLED, MIA_DISABLED)); 1210 1211=item C<WindowFromPoint($x, $y [, $hwndParent [, $descedantsToo]])> 1212 1213gets a handle of a child of $hwndParent at C<($x,$y)>. If $descedantsToo 1214(defaulting to 1) then children of children may be returned too. May return 1215$hwndParent (defaults to desktop) if no suitable children are found, 1216or 0 if the point is outside the parent. 1217 1218$x and $y are relative to $hwndParent. 1219 1220=item C<EnumDlgItem($dlgHwnd, $type [, $relativeHwnd])> 1221 1222gets a dialog item window handle for an item of type $type of $dlgHwnd 1223relative to $relativeHwnd, which is descendant of $dlgHwnd. 1224$relativeHwnd may be specified if $type is EDI_FIRSTTABITEM or 1225EDI_LASTTABITEM. 1226 1227The return is always an immediate child of hwndDlg, even if hwnd is 1228not an immediate child window. $type may be 1229 1230=over 1231 1232=item EDI_FIRSTGROUPITEM 1233 1234First item in the same group. 1235 1236=item EDI_FIRSTTABITEM 1237 1238First item in dialog with style WS_TABSTOP. hwnd is ignored. 1239 1240=item EDI_LASTGROUPITEM 1241 1242Last item in the same group. 1243 1244=item EDI_LASTTABITEM 1245 1246Last item in dialog with style WS_TABSTOP. hwnd is ignored. 1247 1248=item EDI_NEXTGROUPITEM 1249 1250Next item in the same group. Wraps around to beginning of group when 1251the end of the group is reached. 1252 1253=item EDI_NEXTTABITEM 1254 1255Next item with style WS_TABSTOP. Wraps around to beginning of dialog 1256item list when end is reached. 1257 1258=item EDI_PREVGROUPITEM 1259 1260Previous item in the same group. Wraps around to end of group when the 1261start of the group is reached. For information on the WS_GROUP style, 1262see Window Styles. 1263 1264=item EDI_PREVTABITEM 1265 1266Previous item with style WS_TABSTOP. Wraps around to end of dialog 1267item list when beginning is reached. 1268 1269=back 1270 1271=item DesktopWindow() 1272 1273gets the actual window handle of the PM desktop; most APIs accept the 1274pseudo-handle C<HWND_DESKTOP> instead. Keep in mind that the WPS 1275desktop (one with WindowText() being C<"Desktop">) is a different beast?! 1276 1277=item TopLevel($hwnd) 1278 1279gets the toplevel window of $hwnd. 1280 1281=item ResetWinError() 1282 1283Resets $^E. One may need to call it before the C<Win*>-class APIs which may 1284return 0 during normal operation. In such a case one should check both 1285for return value being zero and $^E being non-zero. The following APIs 1286do ResetWinError() themselves, thus do not need an explicit one: 1287 1288 WindowPtr 1289 WindowULong 1290 WindowUShort 1291 WindowTextLength 1292 ActiveWindow 1293 PostMsg 1294 1295This function is normally not needed. Not exported by default. 1296 1297=back 1298 1299=head2 Control of the PM data 1300 1301=over 1302 1303=item ActiveDesktopPathname() 1304 1305gets the path of the directory which corresponds to Desktop. 1306 1307=item ClipbrdText() 1308 1309gets the content of the clipboard. An optional argument is the format 1310of the data in the clipboard (defaults to C<CF_TEXT>). 1311 1312Note that the usual convention is to have clipboard data with 1313C<"\r\n"> as line separators. 1314 1315=item ClipbrdText_set($txt) 1316 1317sets the text content of the clipboard. Unless the optional argument 1318is TRUE, will convert newlines to C<"\r\n">. Another optional 1319argument is the format of the data in the clipboard (defaults to 1320C<CF_TEXT>). 1321 1322=item InvalidateRect 1323 1324=item CreateFrameControl 1325 1326=item ClipbrdFmtInfo 1327 1328=item ClipbrdOwner 1329 1330=item ClipbrdViewer 1331 1332=item ClipbrdData 1333 1334=item OpenClipbrd 1335 1336=item CloseClipbrd 1337 1338=item ClipbrdData_set 1339 1340=item ClipbrdOwner_set 1341 1342=item ClipbrdViewer_set 1343 1344=item EnumClipbrdFmts 1345 1346=item EmptyClipbrd 1347 1348=item AddAtom 1349 1350=item FindAtom 1351 1352=item DeleteAtom 1353 1354=item AtomUsage 1355 1356=item AtomName 1357 1358=item AtomLength 1359 1360=item SystemAtomTable 1361 1362=item CreateAtomTable 1363 1364=item DestroyAtomTable 1365 1366Low-level methods to access clipboard and the atom table(s). 1367 1368=back 1369 1370=head1 OS2::localMorphPM class 1371 1372This class morphs the process to PM for the duration of the given scope. 1373 1374 { 1375 my $h = OS2::localMorphPM->new(0); 1376 # Do something 1377 } 1378 1379The argument has the same meaning as one to OS2::MorphPM(). Calls can 1380nest with internal ones being NOPs. 1381 1382=head1 TODO 1383 1384Add tests for: 1385 1386 SwitchToProgram 1387 ClassName 1388 out_codepage 1389 out_codepage_set 1390 in_codepage 1391 in_codepage_set 1392 cursor 1393 cursor_set 1394 screen 1395 screen_set 1396 process_codepages 1397 QueryWindow 1398 EnumDlgItem 1399 WindowPtr 1400 WindowULong 1401 WindowUShort 1402 SetWindowBits 1403 SetWindowPtr 1404 SetWindowULong 1405 SetWindowUShort 1406 my_type 1407 file_type 1408 scrsize 1409 scrsize_set 1410 1411Document and test: Query/SetWindowULong/Short/Ptr, SetWindowBits. 1412InvalidateRect, CreateFrameControl, ClipbrdFmtInfo ClipbrdOwner 1413ClipbrdViewer ClipbrdData OpenClipbrd CloseClipbrd ClipbrdData_set 1414ClipbrdOwner_set ClipbrdViewer_set EnumClipbrdFmts EmptyClipbrd 1415AddAtom FindAtom DeleteAtom AtomUsage AtomName AtomLength 1416SystemAtomTable CreateAtomTable DestroyAtomTable 1417 1418Implement SOMETHINGFROMMR. 1419 1420 1421 >But I wish to change the default button if the user enters some 1422 >text into an entryfield. I can detect the entry ok, but can't 1423 >seem to get the button to change to default. 1424 > 1425 >No matter what message I send it, it's being ignored. 1426 1427 You need to get the style of the buttons using WinQueryWindowULong/QWL_STYLE, 1428 set and reset the BS_DEFAULT bits as appropriate and then use 1429 WinSetWindowULong/QWL_STYLE to set the button style. 1430 Something like this: 1431 hwnd1 = WinWindowFromID (hwnd, id1); 1432 hwnd2 = WinWindowFromID (hwnd, id2); 1433 style1 = WinQueryWindowULong (hwnd1, QWL_STYLE); 1434 style2 = WinQueryWindowULong (hwnd2, QWL_STYLE); 1435 style1 |= style2 & BS_DEFAULT; 1436 style2 &= ~BS_DEFAULT; 1437 WinSetWindowULong (hwnd1, QWL_STYLE, style1); 1438 WinSetWindowULong (hwnd2, QWL_STYLE, style2); 1439 1440 > How to do query and change a frame creation flags for existing window? 1441 1442 Set the style bits that correspond to the FCF_* flag for the frame 1443 window and then send a WM_UPDATEFRAME message with the appropriate FCF_* 1444 flag in mp1. 1445 1446 ULONG ulFrameStyle; 1447 ulFrameStyle = WinQueryWindowULong( WinQueryWindow(hwnd, QW_PARENT), 1448 QWL_STYLE ); 1449 ulFrameStyle = (ulFrameStyle & ~FS_SIZEBORDER) | FS_BORDER; 1450 WinSetWindowULong( WinQueryWindow(hwnd, QW_PARENT), 1451 QWL_STYLE, 1452 ulFrameStyle ); 1453 WinSendMsg( WinQueryWindow(hwnd, QW_PARENT), 1454 WM_UPDATEFRAME, 1455 MPFROMP(FCF_SIZEBORDER), 1456 MPVOID ); 1457 1458 If the FCF_* flags you want to change does not have a corresponding FS_* 1459 style (i.e. the FCF_* flag corresponds to the presence/lack of a frame 1460 control rather than a property of the frame itself) then you create or 1461 destroy the appropriate control window using the correct FID_* window 1462 identifier and then send the WM_UPDATEFRAME message with the appropriate 1463 FCF_* flag in mp1. 1464 1465 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -* 1466 | SetFrameBorder() | 1467 | Changes a frame window's border to the requested type. | 1468 | | 1469 | Parameters on entry: | 1470 | hwndFrame -> Frame window whose border is to be changed. | 1471 | ulBorderStyle -> Type of border to change to. | 1472 | | 1473 | Returns: | 1474 | BOOL -> Success indicator. | 1475 | | 1476 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ 1477 BOOL SetFrameBorder( HWND hwndFrame, ULONG ulBorderType ) { 1478 ULONG ulFrameStyle; 1479 BOOL fSuccess = TRUE; 1480 1481 ulFrameStyle = WinQueryWindowULong( hwndFrame, QWL_STYLE ); 1482 1483 switch ( ulBorderType ) { 1484 case FS_SIZEBORDER : 1485 ulFrameStyle = (ulFrameStyle & ~(FS_DLGBORDER | FS_BORDER)) 1486 | FS_SIZEBORDER; 1487 break; 1488 1489 case FS_DLGBORDER : 1490 ulFrameStyle = (ulFrameStyle & ~(FS_SIZEBORDER | FS_BORDER)) 1491 | FS_DLGBORDER; 1492 break; 1493 1494 case FS_BORDER : 1495 ulFrameStyle = (ulFrameStyle & ~(FS_SIZEBORDER | FS_DLGBORDER)) 1496 | FS_BORDER; 1497 break; 1498 1499 default : 1500 fSuccess = FALSE; 1501 break; 1502 } // end switch 1503 1504 if ( fSuccess ) { 1505 fSuccess = WinSetWindowULong( hwndFrame, QWL_STYLE, ulFrameStyle ); 1506 1507 if ( fSuccess ) { 1508 fSuccess = (BOOL)WinSendMsg( hwndFrame, WM_UPDATEFRAME, 0, 0 ); 1509 if ( fSuccess ) 1510 fSuccess = WinInvalidateRect( hwndFrame, NULL, TRUE ); 1511 } 1512 } 1513 1514 return ( fSuccess ); 1515 1516 } // End SetFrameBorder() 1517 1518 hwndMenu=WinLoadMenu(hwndParent,NULL,WND_IMAGE); 1519 WinSetWindowUShort(hwndMenu,QWS_ID,FID_MENU); 1520 ulStyle=WinQueryWindowULong(hwndMenu,QWL_STYLE); 1521 WinSetWindowULong(hwndMenu,QWL_STYLE,ulStyle|MS_ACTIONBAR); 1522 WinSendMsg(hwndParent,WM_UPDATEFRAME,MPFROMSHORT(FCF_MENU),0L); 1523 1524 OS/2-windows have another "parent" called the *owner*, 1525 which must be set separately - to get a close relationship: 1526 1527 WinSetOwner (hwndFrameChild, hwndFrameMain); 1528 1529 Now your child should move with your main window! 1530 And always stays on top of it.... 1531 1532 To avoid this, for example for dialogwindows, you can 1533 also "disconnect" this relationship with: 1534 1535 WinSetWindowBits (hwndFrameChild, QWL_STYLE 1536 , FS_NOMOVEWITHOWNER 1537 , FS_NOMOVEWITHOWNER); 1538 1539 Adding a button icon later: 1540 1541 /* switch the button style to BS_MINIICON */ 1542 WinSetWindowBits(hwndBtn, QWL_STYLE, BS_MINIICON, BS_MINIICON) ; 1543 1544 /* set up button control data */ 1545 BTNCDATA bcd; 1546 bcd.cb = sizeof(BTNCDATA); 1547 bcd.hImage = WinLoadPointer(HWND_DESKTOP, dllHandle, ID_ICON_BUTTON1) ; 1548 bcd.fsCheckState = bcd.fsHiliteState = 0 ; 1549 1550 1551 WNDPARAMS wp; 1552 wp.fsStatus = WPM_CTLDATA; 1553 wp.pCtlData = &bcd; 1554 1555 /* add the icon on the button */ 1556 WinSendMsg(hwndBtn, WM_SETWINDOWPARAMS, (MPARAM)&wp, NULL); 1557 1558 MO> Can anyone tell what OS/2 expects of an application to be properly 1559 MO> minimized to the desktop? 1560 case WM MINMAXFRAME : 1561 { 1562 BOOL fShow = ! (((PSWP) mp1)->fl & SWP MINIMIZE); 1563 HENUM henum; 1564 1565 HWND hwndChild; 1566 1567 WinEnableWindowUpdate ( hwnd, FALSE ); 1568 1569 for (henum=WinBeginEnumWindows(hwnd); 1570 (hwndChild = WinGetNextWindow (henum)) != 0; ) 1571 WinShowWindow ( hwndChild, fShow ); 1572 1573 WinEndEnumWindows ( henum ); 1574 WinEnableWindowUpdate ( hwnd, TRUE ); 1575 } 1576 break; 1577 1578Why C<hWindowPos DesktopWindow> gives C<< behind => HWND_TOP >>? 1579 1580=head1 $^E 1581 1582the majority of the APIs of this module set $^E on failure (no matter 1583whether they die() on failure or not). By the semantic of PM API 1584which returns something other than a boolean, it is impossible to 1585distinguish failure from a "normal" 0-return. In such cases C<$^E == 15860> indicates an absence of error. 1587 1588=head1 EXPORTS 1589 1590In addition to symbols described above, the following constants (available 1591also via module C<OS2::Process::Const>) are exportable. Note that these 1592symbols live in package C<OS2::Process::Const>, they are not available 1593by full name through C<OS2::Process>! 1594 1595 HWND_* Standard (abstract) window handles 1596 WM_* Message ids 1597 SC_* WM_SYSCOMMAND flavor 1598 SWP_* Size/move etc flag 1599 WC_* Standard window classes 1600 PROG_* Program category (PM, VIO etc) 1601 QW_* Query-Window flag 1602 EDI_* Enumerate-Dialog-Item code 1603 WS_* Window Style flag 1604 QWS_* Query-window-UShort offsets 1605 QWP_* Query-window-pointer offsets 1606 QWL_* Query-window-ULong offsets 1607 FF_* Frame-window state flags 1608 FI_* Frame-window information flags 1609 LS_* List box styles 1610 FS_* Frame style 1611 FCF_* Frame creation flags 1612 BS_* Button style 1613 MS_* Menu style 1614 TBM_* Title bar messages? 1615 CF_* Clipboard formats 1616 CFI_* Clipboard storage type 1617 FID_* ids of subwindows of frames 1618 1619=head1 BUGS 1620 1621whether a given API dies or returns FALSE/empty-list on error may be 1622confusing. This may change in the future. 1623 1624=head1 AUTHOR 1625 1626Andreas Kaiser <ak@ananke.s.bawue.de>, 1627Ilya Zakharevich <ilya@math.ohio-state.edu>. 1628 1629=head1 SEE ALSO 1630 1631C<spawn*>() system calls, L<OS2::Proc> and L<OS2::WinObject> modules. 1632 1633=cut 1634