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.

