windows 如何从活动窗口中检索选定的文本

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1007185/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 12:38:47  来源:igfitidea点击:

How to retrieve the selected text from the active window

pythonwindowswinapipywin32

提问by George Notaras

I am trying to create a simple open source utility for windows using Pythonthat 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.

我正在尝试使用Python为 Windows 创建一个简单的开源实用程序,该实用程序可以对当前活动窗口的选定文本执行用户定义的操作。该实用程序应使用预定义的键盘快捷键激活。

Usage is partially outlined in the following example:

以下示例部分概述了用法:

  1. The user selects some text using the mouse or the keyboard (in any application window)
  2. The user presses a pre-defined keyboard shortcut
  3. The selected text is retrieved by our utility or copied to clipboard (both approaches should be fine)
  4. The keyboard shortcut-dependent action is performed on the selected text
  1. 用户使用鼠标或键盘选择一些文本(在任何应用程序窗口中)
  2. 用户按下预定义的键盘快捷键
  3. 所选文本由我们的实用程序检索或复制到剪贴板(两种方法都可以)
  4. 对所选文本执行依赖于键盘快捷键的操作

What puzzles me is step 3. How the selected text is retrieved from the active window. This should work with all applications.

令我困惑的是第 3 步如何从活动窗口中检索所选文本。这应该适用于所有应用程序。

I use the pywin32module.

我使用pywin32模块。

Thanks in advance for your answers and tips.

预先感谢您的回答和提示。

Update #1:

更新#1

Turns out that there are two approaches to accomplish the task:

事实证明,有两种方法可以完成任务:

  1. 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.
  2. Find the active Window, then retrieve the selected text directly (without copying it to clipboard). This seems more difficult than the 1st approach.
  1. 找到活动窗口,然后向其发送消息/击键 (Ctrl-C) 以将所选文本复制到剪贴板。然后,该实用程序可以通过使用剪贴板相关功能访问文本来处理文本。
  2. 找到活动窗口,然后直接检索所选文本(无需将其复制到剪贴板)。这似乎比第一种方法更难。

As starting points:

作为起点:

Get the active window ID as Anurag Uniyal has pointed out in his reply.

获取 Anurag Uniyal 在他的回复中指出的活动窗口 ID 。

Or get the window object with the following code:

或者使用以下代码获取窗口对象:

import win32ui
wnd = win32ui.GetForegroundWindow()
print wnd.GetWindowText()

回答by Berry Tsakala

the code below will work only on simple text boxes (just did it in VB6, and ported to python)

下面的代码仅适用于简单的文本框(只是在 VB6 中完成,并移植到 python)

edit: it was tested only on python 2.6

编辑:它仅在 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()

回答by Anurag Uniyal

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,FindWindowExto get child windows with focus

也许您将不得不使用FindWindow,FindWindowEx来获得具有焦点的子窗口

edit: also while experimenting use spy++ to see how it retrieves information about various windows, see hwnd, window class etc

编辑:也在试验时使用 spy++ 来查看它如何检索有关各种窗口的信息,请参阅 hwnd、窗口类等

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

基本上,如果你能在 C/C++/C# 中找到一个例子,那么将它翻译成 pywin32 等价物并不难,所以在某种程度上它是 win32 api 的特定问题

回答by Bob Moore

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.

使用 Ctrl-C 方法会好得多。直接获取文本适用于编辑控件之类的东西,但对于检索应用程序直接在其自己的窗口上绘制的文本是无用的。