Ha ha.. I found the problem. I must Sleep(aWhile) after
SetForegroundWindow(hWnd) to give time for hWnd to turn on its caret
and capture keyboard input, BEFORE calling
GetGUIThreadInfo(GetWIndowThreadProcessId(hWhd)). Also, Micro$oft Word
does not respond to SendMessage(WM_CHAR) but PostMessage(WM_CHAR).

Here is the source code so far that worked with most applications
(Command Prompt, NotePad, WritePad, Word, Firefox...):

*** begin ****
*
* http://vcpptips.wordpress.com/tag/getwindowthreadprocessid/
* http://www.news2news.com/vfp/?function=390
* http://www.news2news.com/vfp/?example=371&function=392
*
*
#define GW_HWNDNEXT 2

#DEFINE GUITHREADINFO_SIZE  48

#DEFINE GUI_CARETBLINKING  1
#DEFINE GUI_INMOVESIZE     2
#DEFINE GUI_INMENUMODE     4
#DEFINE GUI_SYSTEMMENUMODE 8
#DEFINE GUI_POPUPMENUMODE  16

#define KEYEVENTF_KEYUP  0x0002

#define WM_CHAR            0x0102
#define WM_SETTEXT         0x000C
#define WM_PASTE           0x0302
#define WM_KEYDOWN              0x0100
#define WM_KEYUP        0x0101

#define WM_SETFOCUS      0x0007
#define WM_ACTIVATE                     0x0006
#define WM_ACTIVATEAPP             0x001C
#define WM_MOUSEACTIVATE        0x0021
#define WM_LBUTTONDOWN          0x0201
#define WM_LBUTTONUP                    0x0202

#define VK_CONTROL                 0x11


LOCAL cBuffer
LOCAL lnThreaddId, ln_current_window, ln_window_count, lc_window_title

        DECLARE INTEGER GetActiveWindow ;
           IN win32api
        DECLARE INTEGER GetWindow ;
           IN win32api ;
           INTEGER ncurr_window_handle, ;
           INTEGER ndirection
    DECLARE INTEGER GetWindowText IN user32;
            INTEGER hwnd, STRING @lpString, INTEGER cch
        DECLARE LONG IsWindowVisible IN "user32" LONG HWND

        DECLARE INTEGER SetForegroundWindow ;
                IN user32 ;
                INTEGER hwnd

        DECLARE SHORT VkKeyScan IN user32;
            INTEGER ch
        DECLARE keybd_event IN user32;
            SHORT bVk,;
            SHORT bScan,;
            INTEGER dwFlags,;
            INTEGER dwExtraInfo
        DECLARE Sleep IN kernel32 INTEGER dwMilliseconds

        DECLARE INTEGER SendMessage IN user32 ;
            INTEGER hWnd,;
            INTEGER Msg,;
            INTEGER wParam,;
            INTEGER lParam
        DECLARE SHORT PostMessage IN user32;
            INTEGER   hWnd,;
            INTEGER   Msg,;
            INTEGER   wParam,;
            INTEGER   lParam


        DECLARE INTEGER GetWindowThreadProcessId IN user32;
            INTEGER   hWnd,;
            INTEGER @ lpdwProcId
    DECLARE INTEGER GetGUIThreadInfo IN user32;
        INTEGER idThread, STRING @lpgui

    DECLARE INTEGER GetLastError IN kernel32

        DECLARE INTEGER GetClassName IN user32;
            INTEGER   hWnd,;
            STRING  @ lpClassName,;
            INTEGER   nMaxCount
clear

set safety off
set alternate to z:\debug_caret.txt
set alternat on

m.big5="哈"

ln_my_window=GetActiveWindow()
ln_current_window=ln_my_window
ln_window_count=0
DO WHILE ln_current_window>0
        lc_window_title=GetWindowCaption(ln_current_window)
        IF !EMPTY(lc_window_title)
                ? ln_current_window, lc_window_title
                do case
                        case upper(lc_window_title)="START"
                        case IsWindowVisible(ln_current_window) = 0
                        otherwise
                                ln_window_count=ln_window_count+1
                                if ln_window_count=2
                                        SetForegroundWindow(ln_current_window)
                                        sleep(50)
                                        
lnThreadId=GetWindowThreadProcessId(ln_current_window, 0)
                                        ? "window", ln_current_window, 
"thread", lnThreadId
                                        cBuffer = Chr(GUITHREADINFO_SIZE) + 
Repli(Chr(0), GUITHREADINFO_SIZE-1)
                                        IF GetGUIThreadInfo(lnThreadId, 
@cBuffer) = 0
                                           ? "Error code:", GetLastError()
                                        ELSE
                                                m.haha = wnd(cBuffer, 13, 
"Window that has the keyboard focus")
                                                do case
                                                case m.haha<>0 and .f.
                                                        *** WORKING ***
                                                        PostMessage(m.haha, 
WM_CHAR, asc(left(m.big5,1)), 0)
                                                        PostMessage(m.haha, 
WM_CHAR, asc(right(m.big5,1)), 0)
                                                otherwise
                                                        * send CONTROL+V
                                                        _cliptext=m.big5
                                                        if .t.
                                                                
PostMessage(m.haha, WM_PASTE, 0, 0)
                                                        endif
                                                        if .f.
                                                                
sendkey(VK_CONTROL, 0)
                                                                
sendkey(asc("V"), 0)
                                                                
sendkey(asc("V"), KEYEVENTF_KEYUP)
                                                                
sendkey(VK_CONTROL, KEYEVENTF_KEYUP)
                                                        endif
                                                endcase
                                        ENDIF
                                        SetForegroundWindow(ln_my_window)
                                        exit
                                endif
                endcase
        ENDIF
        ln_current_window=GetWindow(ln_current_window,GW_HWNDNEXT)
ENDDO

set alternat off
set alternate to
set safety on

clear dlls
return

function sendkey
lparameter m.vk, m.flag
        keybd_event(m.vk, 0, m.flag, 0)
        Sleep(25)
return

*|typedef struct tagGUITHREADINFO {
*|    DWORD cbSize;       0:4
*|    DWORD flags;        4:4
*|    HWND hwndActive;    8:4
*|    HWND hwndFocus;     12:4
*|    HWND hwndCapture;   16:4
*|    HWND hwndMenuOwner; 20:4
*|    HWND hwndMoveSize;  24:4
*|    HWND hwndCaret;     28:4
*|    RECT rcCaret;       32:16
*|} GUITHREADINFO, *PGUITHREADINFO; total 48 bytes

function wnd
lparameter cBuffer, lnOffs, lcTitle
local hWindow, lcCaption
        ? "cBuffer:", cBuffer
    hWindow = buf2dword(SUBSTR(cBuffer, lnOffs,4))
    lcCaption = GetWindowCaption(hWindow)
    = ins(lcTitle, LTRIM(STR(hWindow)) + ", [" + GetClsName(hWindow) + "]")
return hWindow

PROCEDURE ins(cTitle, cValue)
        ? m.cTitle, m.cValue
RETURN

FUNCTION buf2dword(lcBuffer)
RETURN Asc(SUBSTR(lcBuffer, 1,1)) + ;
    BitLShift(Asc(SUBSTR(lcBuffer, 2,1)),  8) +;
    BitLShift(Asc(SUBSTR(lcBuffer, 3,1)), 16) +;
    BitLShift(Asc(SUBSTR(lcBuffer, 4,1)), 24)

FUNCTION GetWindowCaption(lnWindow)
LOCAL lnLength, lcText
    lcText = SPACE(250)
    lnLength = GetWindowText(lnWindow, @lcText, Len(lcText))
RETURN iif(lnLength>0, Left(lcText, lnLength), space(1))

Function GetClsName
lParameter ln_current_window
local cBuffer, nBufSize
cBuffer = Repli(Chr(0), 250)
nBufsize = GetClassName(ln_current_window, @cBuffer, Len(cBuffer))
return SUBSTR(cBuffer, 1, nBufsize)

*** end ****

On Sun, Mar 11, 2012 at 8:25 PM, Man-wai Chang <[email protected]> wrote:
> Oh well... I just discovered WritePad and Word don't report any
> GUIThreadInfo at all.... the example that worked with Notepad's caret
> failed with them.

-- 
 .~. Might, Courage, Vision. SINCERITY!
/ v \ 64-bit Ubuntu 9.10 (Linux kernel 2.6.39.3)
/( _ )\ http://sites.google.com/site/changmw
^ ^ May the Force and farces be with you!

_______________________________________________
Post Messages to: [email protected]
Subscription Maintenance: http://leafe.com/mailman/listinfo/profox
OT-free version of this list: http://leafe.com/mailman/listinfo/profoxtech
Searchable Archive: http://leafe.com/archives/search/profox
This message: 
http://leafe.com/archives/byMID/profox/CAGv=mjay8bbmmvbdaccwmpcy5xbkthy3rqshth33pj+1xsn...@mail.gmail.com
** All postings, unless explicitly stated otherwise, are the opinions of the 
author, and do not constitute legal or medical advice. This statement is added 
to the messages for those lawyers who are too stupid to see the obvious.

Reply via email to