winextensions sendmessage

Help
2011-01-28
2012-08-14
  • Paul Higgins

    Paul Higgins - 2011-01-28

    I am trying to figure out how to send a WM_SYSKEYUP using sendmessage of the
    winextensions. Here is my code:

    cmd = '0105'x

    wParam = reverse('00000012'x)

    lParam = reverse('c0380001'x)

    fgwnd~sendMessage(cmd,wParam, lParam)

    I have a monitor to trap keystokes and nothing appears when I do the above.
    The sendkeyup function does work but I want to be able to use the sendmessage
    function.

    Does anyone have an example of using sendmessage?

    Thanks,

    Paul

     
  • Mark Miesfeld

    Mark Miesfeld - 2011-01-28

    You're not going to be able to get that to work.

    Keyboard event messages are handled differently by the OS than most other
    window messages. For one thing, they have to be posted to a window, not sent.
    The sendMessage() method will not post a message, as the name implies it uses
    the SendMessage() API. So, it's just not going to work. <grin>

    The sendKeyXXX methods in winsystm.cls are specially written to take into
    account the differences between key event messages and other types of window
    messages.

     
  • Paul Higgins

    Paul Higgins - 2011-01-28

    OK thanks Mark.

    There also seems to be timing issue using the other sendkey functions. On some
    very fast CPUs the messages seem to get out of order. I tried issuing a
    SysSleep between the keystrokes which helps but not sure what value will work
    for all CPUs. Have you had any luck doing this or know of someone who has come
    up some code to do this?

     
  • Mark Miesfeld

    Mark Miesfeld - 2011-01-28

    Hi Paul,

    (Hope I remembered your name correctly.)

    As a matter of fact I had run into that problem when I was rewriting some of
    the examples. Note sure what version of ooRexx your are on, but if it is at
    least ooRexx 4.0.0 then in the samples directory for winsystm you will have
    this file:

    windowsSystem.frm

    In there I have a routine: sendTextWithPause() along with some comment. I used
    that to deal with text getting out of order in the examples when I ran them on
    one of my fast systems.

    It basically does what you are doing with SysSleep, maybe in a more structured
    way. It works correctly on all the systems I tested on, which included a
    couple of very fast systems. There is still no guarentee it will work on all
    CPUs, but it probably will.

    The whole thing comes down to what I mentioned above, key events need to be
    posted to the message queue. When a message is posted, the function returns
    immediately, so messages can end up arriving in the message queue in a
    different order. Sleeping a small amount is enough, when you are using sendKey
    from the same program, to synchronize things, I think.

    --
    Mark Miesfeld

     
  • Paul Higgins

    Paul Higgins - 2011-01-28

    Yes thanks I'm at 4.1.0 and had looked at that routine. What i'm having
    trouble with is trying to send a CTRL+ALT+S to Google earth. I have another
    program that sends keystrokes to a window and what it sends is:

    WM_SYSKEYUP

    wParam: 0x00000053

    lParam: 0xe11f0001

    Message Posted

    Time: 17:45:17.0118

    WM_SYSKEYUP

    wParam: 0x00000012

    lParam: 0xc1380001

    Message Posted

    Time: 17:45:17.0119

    WM_SYSKEYUP

    wParam: 0x00000011

    lParam: 0xc11d0001

    Message Posted

    Time: 17:45:17.0119

    Any idea how to do that with the oorexx functions?

    BTW: you can get that other program here:

    http://www.codeproject.com/KB/dialog/keystroke.aspx

     
  • Mark Miesfeld

    Mark Miesfeld - 2011-01-31

    Hi Paul,

    A interesting topic. I spent a little time this weekend looking into it.

    From comment in the C implementation code, this should be the way to do
    this.

    First get a WindowObject for the opened Google Earth. Then use the send key
    methods in this fashion:

    do 10

    j = SysSleep(.1)

    wnd = windowMgr~find("Google Earth")

    if wnd~class == .WindowObject then leave

    end

    VK_CONTROL = 17

    VK_MENU = 18

    VK_S = 83

    if wnd~class == .WindowObject then do

    say 'Got Google Earth'

    wnd~assocWindow(wnd~handle)

    wnd~toForeground

    wnd~sendKeyDown(VK_CONTROL, 1)

    wnd~sendKeyDown(VK_MENU)

    wnd~sendKeyDown(VK_S)

    wnd~sendKeyUP(VK_S)

    wnd~sendKeyUP(VK_CONTROL, 1)

    wnd~sendKeyUP(VK_MENU)

    end

    Unfortunately, the above doesn't work. A similar thing to send Ctrl-L, which
    should be simplier and more likely to work is:

    do 10

    j = SysSleep(.1)

    wnd = windowMgr~find("Google Earth")

    if wnd~class == .WindowObject then leave

    end

    VK_CONTROL = 17

    VK_MENU = 18

    VK_S = 83

    if wnd~class == .WindowObject then do

    say 'Got Google Earth'

    wnd~assocWindow(wnd~handle)

    wnd~toForeground

    wnd~sendKeyDown(VK_CONTROL, 1)

    wnd~sendKeyDown(VK_MENU)

    wnd~sendKeyDown(VK_S)

    wnd~sendKeyUP(VK_S)

    wnd~sendKeyUP(VK_CONTROL, 1)

    wnd~sendKeyUP(VK_MENU)

    end

    That doesn't work either.

    The existing code in the winsystm.cls implementation uses an out-dated API
    that Microsoft advises not to use. So I wrote some code using the modern API
    just to see if it would work or not. And it does work.

    I put that together in a small external libray package, which you could
    download and use if you like. Go to this spot on SourceForge:

    Well, SourceForge seems to be having trouble now. I post tomorrow on how to
    get the package. But for now, I include a small test app and this is what its
    code looks like:

    VK_CONTROL = 17

    VK_MENU = 18

    VK_L = 76

    VK_S = 83

    -- Try to find an open Google Earth window.
    do 10

    j = SysSleep(.1)

    googleWindow = .WindowRexx~findWindow("Google Earth")

    if googleWindow~class == .WindowRexx then leave

    end

    -- If we found the window, send Ctrl-Alt-S to it, otherwise abort.
    if googleWindow~class == .WindowRexx then do

    say 'Got dialog window'

    googleWindow~toForeground

    -- You can also try sending Ctrl-L by switching the two lines:

    ret = googleWindow~sendKeyPress(VK_S, .array~of(VK_CONTROL, VK_MENU))

    --ret = googleWindow~sendKeyPress(VK_L, .array~of(VK_CONTROL))

    say 'Got ret:' ret

    return ret

    end

    else do

    say "Failed to find Google Earth, aborting"

    return 99

    end

    ::requires 'windowRexx.frm'

    As you can see from the above the package name is windowRexx.frm.

    My intent is to move the fixed code in .WindowRexx, into the .Window class of
    ooDialog so that it will make it into a release.

     
  • Paul Higgins

    Paul Higgins - 2011-01-31

    Thanks for all the work Mark. Waiting for your package to try it out.

    Paul

     

Log in to post a comment.