I am trying to create a simple open source utility for windows using Python that can perform user-defined actions on the selected text of the currently active window. The utility should be activated using a pre-defined keyboard shortcut.
Usage is partially outlined in the following example:
- The user selects some text using the mouse or the keyboard (in any application window)
- The user presses a pre-defined keyboard shortcut
- The selected text is retrieved by our utility or copied to clipboard (both approaches should be fine)
- The keyboard shortcut-dependent action is performed on the selected text
What puzzles me is step 3. How the selected text is retrieved from the active window. This should work with all applications.
I use the pywin32 module.
Thanks in advance for your answers and tips.
Update #1:
Turns out that there are two approaches to accomplish the task:
- Find the active window, then send a message/keystroke (Ctrl-C) to it in order to copy the selected text to the clipboard. Then the utility can work on the text by accessing it using the clipboard-related functions.
- Find the active Window, then retrieve the selected text directly (without copying it to clipboard). This seems more difficult than the 1st approach.
As starting points:
Get the active window ID as Anurag Uniyal has pointed out in his reply.
Or get the window object with the following code:
import win32ui
wnd = win32ui.GetForegroundWindow()
print wnd.GetWindowText()
the code below will work only on simple text boxes (just did it in VB6, and ported to python)
edit: it was tested only on python 2.6
from ctypes import *
import win32gui
import win32api
import win32con
user32 = windll.user32
kernel32 = windll.kernel32
class RECT(Structure):
_fields_ = [
("left", c_ulong),
("top", c_ulong),
("right", c_ulong),
("bottom", c_ulong)
]
class GUITHREADINFO(Structure):
_fields_ = [
("cbSize", c_ulong),
("flags", c_ulong),
("hwndActive", c_ulong),
("hwndFocus", c_ulong),
("hwndCapture", c_ulong),
("hwndMenuOwner", c_ulong),
("hwndMoveSize", c_ulong),
("hwndCaret", c_ulong),
("rcCaret", RECT)
]
def get_selected_text_from_front_window(): # As String
''' vb6 to python translation '''
gui = GUITHREADINFO(cbSize=sizeof(GUITHREADINFO))
txt=''
ast_Clipboard_Obj=None
Last_Clipboard_Temp = -1
user32.GetGUIThreadInfo(0, byref(gui))
txt = GetCaretWindowText(gui.hwndCaret, True)
'''
if Txt = "" Then
LastClipboardClip = ""
Last_Clipboard_Obj = GetClipboard
Last_Clipboard_Temp = LastClipboardFormat
SendKeys "^(c)"
GetClipboard
Txt = LastClipboardClip
if LastClipboardClip <> "" Then Txt = LastClipboardClip
RestoreClipboard Last_Clipboard_Obj, Last_Clipboard_Temp
print "clbrd: " + Txt
End If
'''
return txt
def GetCaretWindowText(hWndCaret, Selected = False): # As String
startpos =0
endpos =0
txt = ""
if hWndCaret:
buf_size = 1 + win32gui.SendMessage(hWndCaret, win32con.WM_GETTEXTLENGTH, 0, 0)
if buf_size:
buffer = win32gui.PyMakeBuffer(buf_size)
win32gui.SendMessage(hWndCaret, win32con.WM_GETTEXT, buf_size, buffer)
txt = buffer[:buf_size]
if Selected and buf_size:
selinfo = win32gui.SendMessage(hWndCaret, win32con.EM_GETSEL, 0, 0)
endpos = win32api.HIWORD(selinfo)
startpos = win32api.LOWORD(selinfo)
return txt[startpos: endpos]
return txt
if __name__ == '__main__':
print get_selected_text_from_front_window()
You're far better off using the Ctrl-C method. Fetching text directly will work for something like an edit control, but is useless for retrieving text that an application has painted directly on its own window.
It won't be trivial but here is the starting point
import win32gui
hwnd = win32gui.GetForegroundWindow()
print win32gui.GetWindowText(hwnd)
Maybe you will have to use FindWindow
,FindWindowEx
to get child windows with focus
edit: also while experimenting use spy++ to see how it retrieves information about various windows, see hwnd, window class etc
basically if you can find a example in C/C++/C# it won't be difficult to translate that into pywin32 equivalent, so in a way it is win32 api specific question
来源:https://stackoverflow.com/questions/1007185/how-to-retrieve-the-selected-text-from-the-active-window