Getting the HWND of a child app - OS2

This is a discussion on Getting the HWND of a child app - OS2 ; A fairly simple question (I think) but I can't find the answer. I'm starting another PM program from mine using WinStartApp(). How can I then obtain the HWND of the child app? WinStartApp() returns a HAPP, but I can't seem ...

+ Reply to Thread
Results 1 to 20 of 20

Thread: Getting the HWND of a child app

  1. Getting the HWND of a child app

    A fairly simple question (I think) but I can't find the answer.

    I'm starting another PM program from mine using WinStartApp(). How can I
    then obtain the HWND of the child app?

    WinStartApp() returns a HAPP, but I can't seem to do much with it except
    terminate the child app.

    The window title of the child app may vary, so I can't query the switch list
    for the child app's title...

    --
    Alex Taylor
    Fukushima, Japan
    http://www.socis.ca/~ataylo00

    Please take off hat when replying.

  2. Re: Getting the HWND of a child app

    [A complimentary Cc of this posting was sent to
    Alex Taylor
    ], who wrote in article :
    > A fairly simple question (I think) but I can't find the answer.
    >
    > I'm starting another PM program from mine using WinStartApp(). How can I
    > then obtain the HWND of the child app?
    >
    > WinStartApp() returns a HAPP, but I can't seem to do much with it except
    > terminate the child app.


    If your application has a window switch entry, you can find the switch
    list handle, from which it is easy to find the pid and hwnd.

    See the attached excerpt from my collection of snippets.

    Hope this helps,
    Ilya

    ================================================== =====

    undocumented API in the PMSHAPI dynamic link library called
    WinHSWITCHfromHAPP that will do exactly what you need. The workplace
    shell uses this API internally. The function will take a session
    identifier/app handle (HAPP) as a parameter and return a switch handle
    (HSWITCH) for the started application. Here is a piece of sample code
    that makes use of it along with the prototype.

    // the ordinal is 209
    #pragma import(WINHSWITCHFROMHAPP,,"PMSHAPI", 209)
    HSWITCH APIENTRY16 WINHSWITCHFROMHAPP (HAPP happ);

    // Sample code starts here

    happ = WinStartApp(NULLHANDLE, // Notification window handle
    &progdetails, // Program Details Structure
    NULL,// Command Line Parameters for the started application
    NULL, // Reserved
    SAF_INSTALLEDCMDLINE); // Start Application Flags

    // get the switch handle from the happ

    hswitch = WINHSWITCHFROMHAPP(happ);

    if (hswitch)
    {
    // if you need to you can get the switch list control structure SWCNTRL
    // which contains the pid etc...

    if (!WinQuerySwitchEntry(hswitch, &swctl))

    {

    DosSleep(1000);

    // Remove the switch list entry for the started application
    WinRemoveSwitchEntry(hswitch);

    }

    }

    =========================
    HAPP APIENTRY WinHAPPFromPID (ULONG pid)
    =========================

  3. Re: Getting the HWND of a child app

    On 3 May 2008 21:17:16 -0500, Alex Taylor wrote:

    > A fairly simple question (I think) but I can't find the answer.


    Not quite as simple as you might think.

    > I'm starting another PM program from mine using WinStartApp(). How can I
    > then obtain the HWND of the child app?


    "The" HWND? How many windows does a child app. create? Perhaps if you thought
    of obtaining "an" HWND instead, the answer may be a bit clearer?
    This raises the question of "which" HWND you are trying to find.

    > WinStartApp() returns a HAPP, but I can't seem to do much with it except
    > terminate the child app.


    As Ilya said, you can get the HSWITCH entry and therefore the PID. You
    can then enumerate (WinBeginEnumWindows() etc.) children of the desktop (if
    that's what you want) and use WinQueryWindowProcess() to find a match on PID.
    You may also need to check the window's class name (WinQueryClassName()).

  4. Re: Getting the HWND of a child app

    [A complimentary Cc of this posting was sent to
    Paul Ratcliffe
    ], who wrote in article :
    > > WinStartApp() returns a HAPP, but I can't seem to do much with it except
    > > terminate the child app.

    >
    > As Ilya said, you can get the HSWITCH entry and therefore the PID. You
    > can then enumerate (WinBeginEnumWindows() etc.) children of the desktop (if
    > that's what you want) and use WinQueryWindowProcess() to find a match on PID.
    > You may also need to check the window's class name (WinQueryClassName()).


    Eh??? HSWITCH gives you hwnd directly. (Which also makes moot your
    observation about "which window".)

    Hope this helps,
    Ilya

  5. Re: Getting the HWND of a child app

    On Sun, 4 May 2008 21:42:07 UTC, Ilya Zakharevich wrote:
    > Paul Ratcliffe wrote:


    > > > WinStartApp() returns a HAPP, but I can't seem to do much with it except
    > > > terminate the child app.

    > >
    > > As Ilya said, you can get the HSWITCH entry and therefore the PID. You
    > > can then enumerate (WinBeginEnumWindows() etc.) children of the desktop (if
    > > that's what you want) and use WinQueryWindowProcess() to find a match on PID.
    > > You may also need to check the window's class name (WinQueryClassName()).

    >
    > Eh??? HSWITCH gives you hwnd directly. (Which also makes moot your
    > observation about "which window".)


    That's only true if the app creates a single top-level frame window
    and uses the FCF_TASKLIST flag or adds the entry itself. Without
    these, you'll still be able to use WinHSWITCHfromHAPP() to locate
    an entry for the app, but you'll have to use its PID field to
    locate any of the app's window(s), as Paul described.

    It's just a matter of knowing how the target app works. Your
    method will usually work, Paul's will always work (assuming the
    app has created any windows). Also, be aware that if the app
    has multiple entries in the list, your method won't necessarily
    give you the "main" one (ISTR it returns the newest entry).

    BTW... WinHSWITCHfromHAPP() is no longer undocumented. It's
    included in the Toolkit 4.5 Addendum.



    --
    == == almost usable email address: Rich AT E-vertise.Com == ==
    __________________________________________________ _________________
    |
    | DragText v3.9 with NLS support
    Rich Walsh | A Distinctly Different Desktop Enhancement
    Ft Myers, FL | http://e-vertise.com/dragtext/
    __________________________________________________ _________________


  6. Re: Getting the HWND of a child app

    [A complimentary Cc of this posting was NOT [per weedlist] sent to
    Rich Walsh
    ], who wrote in article :
    > > Eh??? HSWITCH gives you hwnd directly. (Which also makes moot your
    > > observation about "which window".)


    > That's only true if the app creates a single top-level frame window
    > and uses the FCF_TASKLIST flag or adds the entry itself. Without
    > these, you'll still be able to use WinHSWITCHfromHAPP() to locate
    > an entry for the app, but you'll have to use its PID field to
    > locate any of the app's window(s), as Paul described.


    Thanks. Interesting...

    Do you know examples of "mainstream" apps which would not have hwnd in
    the task list, so I may experiment with my sniffers?

    > It's just a matter of knowing how the target app works. Your
    > method will usually work, Paul's will always work (assuming the
    > app has created any windows). Also, be aware that if the app
    > has multiple entries in the list, your method won't necessarily
    > give you the "main" one (ISTR it returns the newest entry).


    Thanks for this clarification too.

    Yours,
    Ilya

  7. Re: Getting the HWND of a child app

    On Sun, 4 May 2008 23:56:34 UTC, "Rich Walsh" wrote:

    > BTW... WinHSWITCHfromHAPP() is no longer undocumented. It's
    > included in the Toolkit 4.5 Addendum.


    It is not, unfortunately, included in the toolkit's headers or import
    libraries...

    --
    Alex Taylor
    Fukushima, Japan
    http://www.socis.ca/~ataylo00

    Please take off hat when replying.

  8. Re: Getting the HWND of a child app

    On 5 May 2008 02:15:02 -0500, Alex Taylor wrote:

    > On Sun, 4 May 2008 23:56:34 UTC, "Rich Walsh" wrote:
    >
    >> BTW... WinHSWITCHfromHAPP() is no longer undocumented. It's
    >> included in the Toolkit 4.5 Addendum.

    >
    > It is not, unfortunately, included in the toolkit's headers or import
    > libraries...


    So define it yourself...

    #pragma import(WinHSWITCHfromHAPP, , "PMMERGE", 5199)

    extern HSWITCH APIENTRY WinHSWITCHfromHAPP(HAPP happ);

  9. Re: Getting the HWND of a child app

    On Sun, 4 May 2008 03:14:11 UTC, Ilya Zakharevich
    wrote:

    > > WinStartApp() returns a HAPP, but I can't seem to do much with it except
    > > terminate the child app.

    >
    > If your application has a window switch entry, you can find the switch
    > list handle, from which it is easy to find the pid and hwnd.
    >
    > undocumented API in the PMSHAPI dynamic link library called
    > WinHSWITCHfromHAPP that will do exactly what you need. The workplace
    > shell uses this API internally. The function will take a session
    > identifier/app handle (HAPP) as a parameter and return a switch handle
    > (HSWITCH) for the started application. Here is a piece of sample code
    > that makes use of it along with the prototype.
    >
    > // the ordinal is 209
    > #pragma import(WINHSWITCHFROMHAPP,,"PMSHAPI", 209)
    > HSWITCH APIENTRY16 WINHSWITCHFROMHAPP (HAPP happ);


    This is exactly what I need, thanks!

    (Incidentally, I notice the addendum.inf lists it as ordinal 5199 in
    PMMERGE...)

    --
    Alex Taylor
    Fukushima, Japan
    http://www.socis.ca/~ataylo00

    Please take off hat when replying.

  10. Re: Getting the HWND of a child app

    On Sun, 4 May 2008 18:42:54 UTC, Paul Ratcliffe
    wrote:

    > > I'm starting another PM program from mine using WinStartApp(). How can
    > > I then obtain the HWND of the child app?

    >
    > "The" HWND? How many windows does a child app. create? Perhaps if you
    > thought of obtaining "an" HWND instead, the answer may be a bit clearer?
    > This raises the question of "which" HWND you are trying to find.


    Well, the frame, I suppose.


    What I'm really trying to do is find a way to force the child program (which
    is always a PM program) to be modal to the parent... or possibly even system
    modal*. If I have the HWND (or the HSWITCH) I assume I can either use
    WinSetSysModalWindow() or, more elegantly, forcibly switch the focus back
    to the child with WinSwitchToProgram() (or something) whenever the user
    attempts to activate the parent.

    Right now I'm attempting the former, at least to see if the concept works.
    It doesn't seem to have any effect at the moment, but I'll keep playing.


    * (Yes, I know this is evil. The context can arguably justify it, however.)
    --
    Alex Taylor
    Fukushima, Japan
    http://www.socis.ca/~ataylo00

    Please take off hat when replying.

  11. Re: Getting the HWND of a child app

    On 5 May 2008 06:01:02 -0500, Alex Taylor wrote:

    >> // the ordinal is 209
    >> #pragma import(WINHSWITCHFROMHAPP,,"PMSHAPI", 209)
    >> HSWITCH APIENTRY16 WINHSWITCHFROMHAPP (HAPP happ);

    >
    > This is exactly what I need, thanks!
    >
    > (Incidentally, I notice the addendum.inf lists it as ordinal 5199 in
    > PMMERGE...)


    The stuff Ilya quoted is a 16 bit entrypoint (obvious from the definition).
    The stuff I quoted is a 32 bit entrypoint. You can use PMSHAPI.155 if you
    like as that is just a forwarder to PMMERGE.5199

    Check out http://home.clara.net/orac/os2/xrefw.htm etc.

  12. Re: Getting the HWND of a child app

    On Mon, 5 May 2008 11:08:02 UTC, "Alex Taylor" wrote:
    >
    > What I'm really trying to do is find a way to force the child program (which
    > is always a PM program) to be modal to the parent... or possibly even system
    > modal*. If I have the HWND (or the HSWITCH) I assume I can either use
    > WinSetSysModalWindow() or, more elegantly, forcibly switch the focus back
    > to the child with WinSwitchToProgram() (or something) whenever the user
    > attempts to activate the parent.
    >
    > Right now I'm attempting the former, at least to see if the concept works.
    > It doesn't seem to have any effect at the moment, but I'll keep playing.


    Definitely not the way to do this - you should use DosSetSession().
    Here's an example from an unpublished version of Run! that uses
    WinStartApp() rather than DosStartSession():

    PROGDETAILS progd;
    HSWITCH hsw;
    SWCNTRL swc;
    STATUSDATA sd;

    happ = WinStartApp( hNotify, &progd, pCmdLine, 0, SAF_STARTCHILDAPP);

    hsw = WinHSWITCHFromHAPP( happ);
    if (hsw && !WinQuerySwitchEntry( hsw, &swc)) {
    sd.Length = sizeof(sd);
    sd.SelectInd = SET_SESSION_SELECTABLE;
    sd.BondInd = SET_SESSION_BOND;
    DosSetSession( swc.idSession, &sd);
    }


    --
    == == almost usable email address: Rich AT E-vertise.Com == ==
    __________________________________________________ _________________
    |
    | DragText v3.9 with NLS support
    Rich Walsh | A Distinctly Different Desktop Enhancement
    Ft Myers, FL | http://e-vertise.com/dragtext/
    __________________________________________________ _________________


  13. Re: Getting the HWND of a child app

    On Mon, 5 May 2008 10:06:12 UTC, Paul Ratcliffe
    wrote:

    > >> BTW... WinHSWITCHfromHAPP() is no longer undocumented. It's
    > >> included in the Toolkit 4.5 Addendum.

    > >
    > > It is not, unfortunately, included in the toolkit's headers or import
    > > libraries...

    >
    > So define it yourself...
    >
    > #pragma import(WinHSWITCHfromHAPP, , "PMMERGE", 5199)
    >
    > extern HSWITCH APIENTRY WinHSWITCHfromHAPP(HAPP happ);


    Yup, that's what I'm doing. I just had to look up the #pragma syntax
    as I'm not used to it...

    --
    Alex Taylor
    Fukushima, Japan
    http://www.socis.ca/~ataylo00

    Please take off hat when replying.

  14. Re: Getting the HWND of a child app

    On Mon, 5 May 2008 23:19:07 UTC, "Rich Walsh" wrote:

    > > What I'm really trying to do is find a way to force the child program
    > > (which is always a PM program) to be modal to the parent...

    >
    > Definitely not the way to do this - you should use DosSetSession().
    > Here's an example from an unpublished version of Run! that uses
    > WinStartApp() rather than DosStartSession():
    >
    > hsw = WinHSWITCHFromHAPP( happ);
    > if (hsw && !WinQuerySwitchEntry( hsw, &swc)) {
    > sd.Length = sizeof(sd);
    > sd.SelectInd = SET_SESSION_SELECTABLE;
    > sd.BondInd = SET_SESSION_BOND;
    > DosSetSession( swc.idSession, &sd);
    > }


    Ooh, cool! Thanks, that's exactly what I'm looking for!


    Now I just need to figure out why WinHSWITCHFromHAPP() is always returning
    NULLHANDLE...


    --
    Alex Taylor
    Fukushima, Japan
    http://www.socis.ca/~ataylo00

    Please take off hat when replying.

  15. Re: Getting the HWND of a child app

    On Tue, 6 May 2008 03:02:02 UTC, "Alex Taylor"
    wrote:

    > > Definitely not the way to do this - you should use DosSetSession().
    > > Here's an example from an unpublished version of Run! that uses
    > > WinStartApp() rather than DosStartSession():

    >
    > Ooh, cool! Thanks, that's exactly what I'm looking for!



    Hmm, maybe not entirely. It seems that clicking directly on the parent
    window will still raise the parent, not the child. That's exactly what I
    want to prevent from happening...


    > Now I just need to figure out why WinHSWITCHFromHAPP() is always returning
    > NULLHANDLE...


    Oddly, it seems to work today...

    --
    Alex Taylor
    Fukushima, Japan
    http://www.socis.ca/~ataylo00

    Please take off hat when replying.

  16. Re: Getting the HWND of a child app

    On Tue, 6 May 2008 03:14:01 UTC, "Alex Taylor" wrote:
    > On Tue, 6 May 2008 03:02:02 UTC, "Alex Taylor"
    > wrote:
    >
    > > > Definitely not the way to do this - you should use DosSetSession().
    > > > Here's an example from an unpublished version of Run! that uses
    > > > WinStartApp() rather than DosStartSession():

    > >
    > > Ooh, cool! Thanks, that's exactly what I'm looking for!

    >
    > Hmm, maybe not entirely. It seems that clicking directly on the parent
    > window will still raise the parent, not the child. That's exactly what I
    > want to prevent from happening...


    A big "oops" here :-( From the CP Ref:

    "The parameters only affect user selections from the Shell switch list
    or Shell selections during system hot key processing."

    I didn't have any reason to create a visible frame window for this Run!
    variant so I never tested that. I was only concerned about the window
    list and it worked there (as it still does). I just tried it with a
    visible frame & see that it is very focusable. I guess you'll have to
    intercept WM_ACTIVATE (which is a frame-level msg), then *post* a msg
    either to the parent or child to switch the focus. (Don't try to change
    focus while a focus change is in progress - it doesn't work.)


    --
    == == almost usable email address: Rich AT E-vertise.Com == ==
    __________________________________________________ _________________
    |
    | DragText v3.9 with NLS support
    Rich Walsh | A Distinctly Different Desktop Enhancement
    Ft Myers, FL | http://e-vertise.com/dragtext/
    __________________________________________________ _________________


  17. Re: Getting the HWND of a child app

    On Tue, 6 May 2008 03:14:01 UTC, "Alex Taylor"
    wrote:

    > Hmm, maybe not entirely. It seems that clicking directly on the parent
    > window will still raise the parent, not the child. That's exactly what I
    > want to prevent from happening...


    No, it occures that
    - the window releasing the focus will receive a message saying that.
    This message tells where the focus is going to
    So when you are unwilling to let go the focus to the destination
    you can act on the fact
    - the window getting the focus will receive a message saying that.
    This message tells where the focus is coming from.
    So when you are unwillig to receive the focus you can act on the
    fact.
    in that order.

    The problem is that focus change is an atomar action you can't
    interrupt even as the messages going around will suggest you can. Good
    practice is that whenever you have something against focus
    lost/receive you'll _post_ a WM_USER that sets the focus back to its
    source after the whole focus change is done.

    Sorry that I can't give more details yet as I had lost the volume
    having my complete developement kit on during multiple power failtures
    while chkdsk was working on.

    --
    Tschau/Bye
    Herbert

    Visit http://www.ecomstation.de the home of german eComStation
    eComStation 1.2R Deutsch ist da!

  18. Re: Getting the HWND of a child app

    On Tue, 6 May 2008 03:51:29 UTC, "Rich Walsh"
    wrote:

    > I didn't have any reason to create a visible frame window for this Run!
    > variant so I never tested that. I was only concerned about the window
    > list and it worked there (as it still does). I just tried it with a
    > visible frame & see that it is very focusable. I guess you'll have to
    > intercept WM_ACTIVATE (which is a frame-level msg), then *post* a msg
    > either to the parent or child to switch the focus. (Don't try to change
    > focus while a focus change is in progress - it doesn't work.)


    You must use the API to set the focus to the window that should
    receive it. The messages are only to get you informed, not to change
    the focus actively. True, yes, you must post a message to get the work
    done.

    --
    Tschau/Bye
    Herbert

    Visit http://www.ecomstation.de the home of german eComStation
    eComStation 1.2R Deutsch ist da!

  19. Re: Getting the HWND of a child app

    [A complimentary Cc of this posting was NOT [per weedlist] sent to
    Ilya Zakharevich
    ], who wrote in article :
    > > > Eh??? HSWITCH gives you hwnd directly. (Which also makes moot your
    > > > observation about "which window".)

    >
    > > That's only true if the app creates a single top-level frame window
    > > and uses the FCF_TASKLIST flag or adds the entry itself. Without
    > > these, you'll still be able to use WinHSWITCHfromHAPP() to locate
    > > an entry for the app, but you'll have to use its PID field to
    > > locate any of the app's window(s), as Paul described.

    >
    > Thanks. Interesting...
    >
    > Do you know examples of "mainstream" apps which would not have hwnd in
    > the task list, so I may experiment with my sniffers?


    Actually, I could do it myself:

    perl -MData:umper -MOS2::Process -wle "print Dumper
    [grep !$_->{owner_hwnd}, process_hentries()]"

    gives the attached list. As the attached script shows, only two of
    these 4 processes have any associated windows...

    hwnd=0x80000097 pid=0x26 tid=0x1
    hwnd=0x80000098 pid=0x26 tid=0x1
    hwnd=0x80000099 pid=0x26 tid=0x1
    hwnd=0x8000009b pid=0x26 tid=0x1
    hwnd=0x8000009c pid=0x26 tid=0x1
    ^^^ <== BLACKOUT.EXE
    hwnd=0x800001d7 pid=0x4c tid=0x4
    hwnd=0x800001db pid=0x4c tid=0x4
    hwnd=0x800001da pid=0x4c tid=0x4
    hwnd=0x800001d9 pid=0x4c tid=0x4
    hwnd=0x800001d8 pid=0x4c tid=0x4
    hwnd=0x800001d4 pid=0x4c tid=0x3
    hwnd=0x800001d5 pid=0x4c tid=0x3
    ^^^ <== CCHMAIN.EXE

    --------- shown by

    #!/usr/bin/perl -w
    use strict;
    use OS2::Process;

    my %procs;
    $procs{$_->{owner_pid}} = $_->{title} for grep !$_->{owner_hwnd}, process_hentries();

    my $l = OS2::localMorphPM->new(0);

    sub l {
    my ($o,$h) = @_;
    my ($p, $t) = WindowProcess $h;
    printf "%*shwnd=%#x pid=%#x tid=%#x\n^^^ <== %s\n",
    $o, '', $h, $p, $t, $procs{$p} if $procs{$p};
    l($o+2,$_) for ChildWindows $h;
    }
    l 0, DesktopWindow();

    Now if I knew how to interpret this....

    Thanks anyway,
    Ilya

    ================================================== =====
    {
    'nonswitchable' => 0,
    'visible' => 0,
    'icon_hwnd' => '0',
    'owner_phandle' => 0,
    'owner_sid' => 38,
    'ptype' => 3,
    'owner_pid' => 1483,
    'sw_entry' => 2240,
    'jumpable' => 1,
    'title' => 'clipserv.exe',
    'owner_hwnd' => '0'
    },
    {
    'nonswitchable' => 0,
    'visible' => 0,
    'icon_hwnd' => '0',
    'owner_phandle' => 0,
    'owner_sid' => 28,
    'ptype' => 3,
    'owner_pid' => 76,
    'sw_entry' => 2372,
    'jumpable' => 1,
    'title' => 'CCHMAIN.EXE',
    'owner_hwnd' => '0'
    },
    {
    'nonswitchable' => 0,
    'visible' => 0,
    'icon_hwnd' => '0',
    'owner_phandle' => 0,
    'owner_sid' => 20,
    'ptype' => 3,
    'owner_pid' => 38,
    'sw_entry' => 900,
    'jumpable' => 1,
    'title' => 'BLACKOUT.EXE',
    'owner_hwnd' => '0'
    },
    {
    'nonswitchable' => 0,
    'visible' => 0,
    'icon_hwnd' => '0',
    'owner_phandle' => 0,
    'owner_sid' => 16,
    'ptype' => 3,
    'owner_pid' => 29,
    'sw_entry' => 172,
    'jumpable' => 1,
    'title' => 'PMSPOOL.EXE',
    'owner_hwnd' => '0'
    }



  20. Re: Getting the HWND of a child app

    On Tue, 6 May 2008 03:51:29 UTC, "Rich Walsh" wrote:

    > A big "oops" here :-( From the CP Ref:
    >
    > "The parameters only affect user selections from the Shell switch list
    > or Shell selections during system hot key processing."
    >
    > I didn't have any reason to create a visible frame window for this Run!
    > variant so I never tested that. I was only concerned about the window
    > list and it worked there (as it still does). I just tried it with a
    > visible frame & see that it is very focusable. I guess you'll have to
    > intercept WM_ACTIVATE (which is a frame-level msg), then *post* a msg
    > either to the parent or child to switch the focus. (Don't try to change
    > focus while a focus change is in progress - it doesn't work.)


    OK. I'll probably try that in the longer term. (I settled on a short-term
    workaround in the meantime.) Thanks.


    --
    Alex Taylor
    Fukushima, Japan
    http://www.socis.ca/~ataylo00

    Please take off hat when replying.

+ Reply to Thread