How to Get the Word Under the Cursor in Windows

How to get the word under the cursor in Windows?

On recent versions of Windows, the recommended way to gather information from one application to another (if you don't own the targeted application of course) is to use the UI Automation technology.
Wikipedia is pretty good for more information on this: Microsoft UI Automation

Basically, UI automation will use all necessary means to gather what can be gathered

Here is a small console application code that will spy the UI of other apps. Run it and move the mouse over to different applications. Each application has a different support for various "UI automation patterns". For example, there is the Value pattern and the Text pattern as demonstrated here.

static void Main(string[] args)
{
do
{
System.Drawing.Point mouse = System.Windows.Forms.Cursor.Position; // use Windows forms mouse code instead of WPF
AutomationElement element = AutomationElement.FromPoint(new System.Windows.Point(mouse.X, mouse.Y));
if (element == null)
{
// no element under mouse
return;
}

Console.WriteLine("Element at position " + mouse + " is '" + element.Current.Name + "'");

object pattern;
// the "Value" pattern is supported by many application (including IE & FF)
if (element.TryGetCurrentPattern(ValuePattern.Pattern, out pattern))
{
ValuePattern valuePattern = (ValuePattern)pattern;
Console.WriteLine(" Value=" + valuePattern.Current.Value);
}

// the "Text" pattern is supported by some applications (including Notepad)and returns the current selection for example
if (element.TryGetCurrentPattern(TextPattern.Pattern, out pattern))
{
TextPattern textPattern = (TextPattern)pattern;
foreach(TextPatternRange range in textPattern.GetSelection())
{
Console.WriteLine(" SelectionRange=" + range.GetText(-1));
}
}
Thread.Sleep(1000);
Console.WriteLine(); Console.WriteLine();
}
while (true);
}

UI automation is actually supported by Internet Explorer and Firefox, but not by Chrome to my knowledge. See this link: When will Google Chrome be accessible?

Now, this is just the beginning of work for you :-), because:

  • Most of the time, all this has heavy security implication. Using this technology (or direct Windows technology such as WindowFromPoint) will require sufficient rights to do so (such as being an administrator). And I don't think DExperience has any way to overcome these limitations, unless they install a kernel driver on the computer.

  • Some applications will not expose anything to anyone, even with proper rights. For example, if I'm writing a banking application, I don't want you to spy on what my application will display :-). Other applications such as Outlook with DRM will not expose anything for the same reasons.

  • Only the UI automation Text pattern support can give more information (like the word) than just the whole text. Alas, this specific pattern is not supported by IE nor FF even if they support UI automation globally.

So, if all this does not work for you, you will have to dive deeper and use OCR or Shape recognition techniques. Even with this, there will be some cases where you won't be able to do it at all (because of security rights).

Get the word under the mouse cursor in Windows

You could capture the GDI calls that output text to the display, and then figure out which word's bounding box the cursor falls in.

How to get the word under the cursor in a Windows Word editor or in a Pdf editor with using Delphi?

This works for me using D7 and Word 2007:

procedure TForm1.GetSelectedText;
var
MSWord,
Selection,
SelectedText : OleVariant;
begin
try
MsWord := GetActiveOleObject('Word.Application');
except
try
MsWord := CreateOleObject('Word.Application');
MsWord.Visible := True;
except
Exception.Create('Error');
end;
end;

Selection := MSWord.Selection;
if not VarIsEmpty(Selection) then begin
SelectedText := Selection.Text;
Caption := SelectedText;
end;

end;

Obviously, it would be trivial to re-write the above as a stand-along function and pass in a reference to an existing MSWord object, if you already have one elsewhere in your code.

Like I said in my comment, doing the equivalent in Acrobat/Pdf is a different technical question, requiring its own q. However, having investigated it, I don't think there's a straightforward method of doing it.

  • If you import the Acrobat type library into Delphi, giving you a unit Acrobat_Tlb.Pas, you'll see that it contains a COM object interface, CAcroPDDoc.

  • You can instantiate that object for the document currently active in Acrobat. However, one* of the weird things about Acrobat's COM object model is that it doesn't provide any useful access to the text contents, if any, in the document.

  • However, from the CAcroPDDoc interface, you can get access to Acrobat's internal JavaScript object for the document by using a call to CAcroPDDoc.GetJSObject.

  • Once you've got a reference to the JS object, you can do a very limited amount of text processing, in particular there's a method GetPageNthWord(Page, WordNum, StripWhiteSpace) that "does what it says on the tin". That's as far as I've got, implementation-wise (if you want to see the code, post a new question).

  • From there, if you have the time, know-how and inclination - and I currently don't - you can apparently retrieve another JS object representing the on-screen selection rectangle and by somehow comparing that with the coordinates of the various Nth words from GetPageNthWord, you can identify which of them is/are selected. Not QED, ISTM.

All of which is a sufficient performance that if it were me, I'd just tell the user to copy the selection to the clipboard, where it would be easy to pick up from Delphi code.

* - Sometimes working with the Acrobat automation I get the feeling that Adobe have gone out of their way to not make it easy to get at the text in a .PDF file. Whether that's anything to do with the possibly apocryphal story that originally PDF was conceived as a write-only medium, so that you could guarantee that you could put one in the field and be sure that it couldn't be modified, I don't know.

How should one retrieve the word under cursor, of current active window?

You have to know the API needed for this; it's not obvious. You're looking for MSAA, Microsoft Active Accessibility

In short, you'll write an MSAA client. By calling AccessibleObjectFromPoint you get an IAccessible pointer. This pointer gives access to the properties of the object at the specified point.

Get word under mouse pointer

You need the parentheses that appear in the original regular expression. In regular expression notation, parentheses form a "match group" which is substituted in for the "$1" in the replace string.

$this.html($this.text().replace(/([^\x00-\x80]+)/g, "<span>$1</span>"));

Without any match groups in your regex, the $1 is simply treated as a literal dollar sign and one.

When you have multiple parenthesized match groups, the groups are used in to replace dollar-sign-denoted numbered placeholders in the order that the match groups are opened (the first match group replaces $1, the second replaces $2, etc).



Related Topics



Leave a reply



Submit