how to get the selected text without using send ^{c}?

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
wo52616111
Posts: 47
Joined: 21 Aug 2014, 04:46

how to get the selected text without using send ^{c}?

Post by wo52616111 » 23 Jan 2016, 13:07

In ahk, basically, we check if user selected some text by using send ^{c}, and check the clipboard.
But in many coding software, send ^{c} will copy a whole line text when we did not setlect any text, So we don't know whether the user select some text.
So, how can i get the selected text without using send ^{c}?

I think dllcall or sendmessage can do this job, but i search for a looooooooong time and get nothing, please help.

I can get selected text in some windows by SendMessage, 0x301, but not all.

Code: Select all

#z::
ControlGet, ctget, Hwnd , , , A
SendMessage, 0x301, , , ,ahk_id %ctget%
MsgBox, % Clipboard
return

hunter99
Posts: 129
Joined: 20 Jan 2014, 17:57

Re: how to get the selected text without using send ^{c}?

Post by hunter99 » 23 Jan 2016, 20:11

Hi wo526:
Try this. You need to clear the clipboard.
I question that the ^c with nothing selected copied that line. Think it was previously copied to the clipboard. Also why the braces around the c in ^c?
Hope this helps.
hunter99

Test:
1 - for test type "anything 0ne anything two" in notepad
2 - select anything one or anything two.
3 - hit the hot key and see it in msgbox.
You might want check this out to quickly test your code.:
get a copy of CodeQuicktester by GeekDude from here:
https://autohotkey.com/boards/viewtopic.php?f=6&t=6113

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
#Warn  ; Recommended for catching common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

^!z::				;hotkey to test with
clipboard =			;clear the clipboard
send, ^c		;copy any selected.  unless there is a reason I would use sendinput	
msgbox,,, %clipboard%		;test if anything is there
return

wo52616111
Posts: 47
Joined: 21 Aug 2014, 04:46

Re: how to get the selected text without using send ^{c}?

Post by wo52616111 » 23 Jan 2016, 20:39

thank you, hunter99. And my problem is not as you said.
You can try to press ctrl+c in this software:Microsoft Visual Studio, Sublime text, or if you are using firefox, please press shift+F4 to open the Scratchpad, then press ctrl+c without selected any text,then ctrl+v,congratulations,you get whole line text. If your browser is chrome, press F12->Sources, do the some action.

hunter99
Posts: 129
Joined: 20 Jan 2014, 17:57

Re: how to get the selected text without using send ^{c}?

Post by hunter99 » 23 Jan 2016, 21:02

Hi wo526:
I jumped too fast on that one. And you are right, I didn't understand the trouble.
I use Firefox, but never used the scratchpad. Just tried it and see what you mean.
I'll look around a bit, time permitting. Good luck to you.
hunter99



timelizards
Posts: 20
Joined: 11 Sep 2015, 21:00

Re: how to get the selected text without using send ^{c}?

Post by timelizards » 05 Feb 2016, 01:18

how can you get the selected text? autohotkey may be able to get it the same way.

im only responding b/c i dont see any other bites at this point, so ill do my best. when you send a message to an application, its up to the application how to handle it. if you send a message that replicates a ^c press, you will probably get results like you pressed ^c.

i doubt its a matter of just sending another hotkey, you probably would have already done that. if you can somehow "get" the selected text in an application thru menus or other means, you might use some software to analyze the messages to determine what the proper message is to send to the application.

depending on your specific need, maybe you can work with the whole line of text by parsing the data in some way?

softwareeater
Posts: 42
Joined: 31 Aug 2015, 11:33

Re: how to get the selected text without using send ^{c}?

Post by softwareeater » 05 Feb 2016, 15:27

Do I understand correctly that the problem is that ^c sometimes gives you a blank clipboard? If so this might work:


#z::
clipsave:=clipboard
sendinput, ^c
if !clipboard
{
clipboard:=clipsave
}
else
{
msgbox, %clipboard%
}
return

clippy

Re: how to get the selected text without using send ^{c}?

Post by clippy » 06 Feb 2016, 04:39

What the OP means is that there are certain programs that copy text to the clipboard even if you haven't made any selection.

So your caret is on line 5 in the middle of the sentence. Nothing is selected. You press ^c to copy text, either by pressing it yourself of have ahk send it it.

In many programs nothing will happen as you haven't selected anything.

But there are programs as mentioned above which will help the user by selecting the entire line and copy it to the clipboard.

That means you can't know if the user has selected something or that the program has selected something for you automatically even if you compare the clipboard before and after ^c because in some program text is always copied to the clipboard even if you haven't made a selection.

I don't think it is possible to know that unless you find specific solutions for each program. In a text editor you may be able to read the statusbar to see if can read if something is selected (some editors show the number of characters/lines you have selected) OR by checking for selected text using image search. The status bar might be an option in some situations but there probably won't be a 100% solution for each program.

softwareeater
Posts: 42
Joined: 31 Aug 2015, 11:33

Re: how to get the selected text without using send ^{c}?

Post by softwareeater » 06 Feb 2016, 12:47

Oh, I see. Well, one particularly hacky method could be to use Shift+Right arrow to add one character to the selection/select one character if nothing is selected, then send ctrl+c, then use StringTrimLeft to get rid of the bonus character. That might have weird side effects; hard to tell without using the program.

User avatar
waetherman
Posts: 112
Joined: 05 Feb 2016, 17:00

Re: how to get the selected text without using send ^{c}?

Post by waetherman » 06 Feb 2016, 18:11

1. Backup Clipboard (backup1 := ClipboardAll)
2. Press CTRL+C
If the clipboard is different than backup, then you copied something, but you don't know if it's a selection or a line.
If the clipboard is the same as before, then there's additional possibility you copied nothing (no selection and the program doesn't copy anything with no selection)
3. Convert clipboard to plain text (clip1 = %Clipboard%)
4. Press SHIFT+LEFT and then CTRL+C
5. Convert next clipboard to plain text (clip2 = %Clipboard%)
6. Compare clipboard (clip2) to previous (clip1):
a) If the clipboard string is shorter by one, then either:
(i) the caret is on the right border of the selection and both previous and current clipboards were copied from the selection.
(ii) there was no selection and the line with 2 chars was copied; now one character is selected and it was copied

b) if the clipboard string is the same length, then either:
(iv) the selection was one character long, the caret was on the right border of the selection; now there is no selection and the line with 1 char was copied
(v) the line with 1 char was copied and there was no selection; now you copied a selection with 1 char and the caret is on left border
(vi) there was a selection with one character inside and the caret on left side, but the caret couldn't go left (because it's position was 0)

c) if the clipboard string is longer by one, then either:
(vii) there was no selection and nothing in clipboard, now one char is selected
(viii) there was a selection and it increased in size, because the caret was on left border of the selection

What's above is obvious, question is how to resolve the doubt - here's an example:
a) press SHIFT+LEFT, CTRL+C and save another clipboard (clip3 = %Clipboard%)
(i) the clipboard got even shorter, press SHIFT+RIGHT, SHIFT+RIGHT and go to d)
(ii) the clipboard has 2 chars, press SHIFT+RIGHT, SHIFT+RIGHT (I think single RIGHT will do the trick as well) and go to e)
If the clipboard didn't change:
- the caret position is 0 and the caret can't go left. This is impossible for (i) as in case of (i) there's at least one selected character with caret on right, so caret must be able to go left
- there's no selection and Windows doesn't copy emptiness into the clipboard. This is possible for (i) but not (ii), as in the latter going left could only increase selection
so press SHIFT+RIGHT, CTRL+C, save yet another clipboard (clip4 =...)
(i) there's one character in the clipboard, so previously clipboard didn't change because nothing was selected; press SHIFT+RIGHT and go to d)
(ii) there's two characters in the clipboard, so we went from no selection and copying a 2 char line to selecting the 1st character in a line to being blocked by the beginning of the line, to deselecting by pressing SHIFT+RIGHT and so copying the 2 char line again. Don't send more keypresses and go to e)

---
You get the idea - if no one finds a flaw in my thinking and you can't do b) and c) alone, I'll try to come back on Tuesday.

d) restore clipboard (Clipboard := backup1) and use clip1 to work on it - it's the selection, not a line
e) restore clipboard and quit (there's no selection)


TWO MORE THINGS
- at the beginning I say there's a possibility you copied nothing - so that's an additional consideration I forgot to check for
- Please keep in mind, that while you convert the clipboard to plain text, you might lose emoticons etc. pressing SHIFT+LEFT or SHIFT+RIGHT may select emoticons, so it's possible they don't change the selection perceived by the algorithm above, even though really they do. So if you want to make an algorithm for rich text, you might want to operate on the clipboard in a more complex manner.
Image

User avatar
Blackholyman
Posts: 1293
Joined: 29 Sep 2013, 22:57
Location: Denmark
Contact:

Re: how to get the selected text without using send ^{c}?

Post by Blackholyman » 06 Feb 2016, 20:19

Did not read the last part of this topic but a Quick look at the clipboard content when all of a Line is copy'ed it seemed to include a Line feed at the end that may be something to check for
Also check out:
Courses on AutoHotkey

My Autohotkey Blog
:dance:

SifJar
Posts: 398
Joined: 11 Jan 2016, 17:52

Re: how to get the selected text without using send ^{c}?

Post by SifJar » 06 Feb 2016, 20:36

Blackholyman wrote:Did not read the last part of this topic but a Quick look at the clipboard content when all of a Line is copy'ed it seemed to include a Line feed at the end that may be something to check for
This may depend on the individual software in question though.

wo52616111
Posts: 47
Joined: 21 Aug 2014, 04:46

Re: how to get the selected text without using send ^{c}?

Post by wo52616111 » 07 Feb 2016, 01:09

softwareeater wrote:Oh, I see. Well, one particularly hacky method could be to use Shift+Right arrow to add one character to the selection/select one character if nothing is selected, then send ctrl+c, then use StringTrimLeft to get rid of the bonus character. That might have weird side effects; hard to tell without using the program.
thank you, Your method is one of my thought. Problem is, you don't konw the caret is on the left side of selected text or right. And, if caret is on the first line first character, you send Shift+left do nothing, the last line last character, shift+right do nothing.

waetherman wrote:1. Backup Clipboard (backup1 := ClipboardAll)
2. Press CTRL+C
If the clipboard is different than backup, then you copied something, but you don't know if it's a selection or a line.
If the clipboard is the same as before, then there's additional possibility you copied nothing (no selection and the program doesn't copy anything with no selection)
3. Convert clipboard to plain text (clip1 = %Clipboard%)
4. Press SHIFT+LEFT and then CTRL+C
...
thank you, I also thought of this method (multiple copy), but I think It is too inefficient, Spending too much time, I want to get the right text more quickly.
Blackholyman wrote:Did not read the last part of this topic but a Quick look at the clipboard content when all of a Line is copy'ed it seemed to include a Line feed at the end that may be something to check for
I use this method now. In those program which get whole line after send ctrl+c all the time, each row of the last had a line feed, except the last row...This is the problem drives me to find other ways.
my get seleted text funcion now:

Code: Select all

getSelText()
{
    ClipboardOld:=ClipboardAll
    Clipboard:=""
    SendInput, ^{c}
    ClipWait, 0.1
    if(!ErrorLevel)
    {
        selText:=Clipboard
        Clipboard:=ClipboardOld
        StringRight, lastChar, selText, 1
        if(Asc(lastChar)!=10) ;if last char is not line feed
        {
            return selText
        }
    }
    Clipboard:=ClipboardOld
    return
}

User avatar
waetherman
Posts: 112
Joined: 05 Feb 2016, 17:00

Re: how to get the selected text without using send ^{c}?

Post by waetherman » 07 Feb 2016, 05:40

wo52616111 wrote:
softwareeater wrote: thank you, I also thought of this method (multiple copy), but I think It is too inefficient, Spending too much time, I want to get the right text more quickly.
I think it may be an inefficient use of your time to make the algorithm, but up to 4 clipboard copies doesn't seem anywhere near an overkill for me. You probably will see the selection blinking when making the check, though.
If you're making a check very often, e.g. when mouse is moved, you could add a timeout in the way the check is made only if the mouse hasn't moved for 100 ms. You could also reset the timer on mouse move only when the mouse is pressed down, so when the selection actually is being changed.

I think it all comes down to one thing: do you want to use this script for yourself, or distribute it? If the latter, then You should try to make it universal.

This code is slow, seems hacky and unreliable:

Code: Select all

#NoEnv

#Warn All

F12::
	Send ^c
	Send +{Left}
	Send ^c
	Send +{Left}
	Send ^c
	Send +{Left}
	Send ^c
	Send +{Right 3}

But this code seems fine, especially because SendInput will keep getting user's keystrokes to the buffer to play them after the script ends.

Code: Select all

#NoEnv

#Warn All

F12::
	SendInput ^c
	SendInput +{Left}
	SendInput ^c
	SendInput +{Left}
	SendInput ^c
	SendInput +{Left}
	SendInput ^c
	SendInput +{Right 3}
Image

SifJar
Posts: 398
Joined: 11 Jan 2016, 17:52

Re: how to get the selected text without using send ^{c}?

Post by SifJar » 05 Mar 2016, 20:36

This works in some cases (Notepad, Notepad++, SciTE):

Code: Select all

#s::MsgBox % getSelected()

getSelected() {
	ControlGetFocus, control, A
	VarSetCapacity(start, 4)
	VarSetCapacity(end, 4)
	SendMessage, 0xB0, &start, &end, %control%, A		;EM_GETSEL
	ControlGetText, string, %control%, A
	enc := (RegexMatch(string,"[\x{0100}-\x{FFFF}]")?"cp0":"utf-16") ;detect encoding of string
	string := SubStr(StrGet(&string,enc), pos := NumGet(start) + 1, NumGet(end) - pos + 1)
	return string
}
With Notepad++ on one of my computers, the encoding of the returned string is ANSI instead of UTF, so I had to use StrGet(&string, "cp0") in the SubStr() function in place of string. Also, for some reason CodeQuickTester (an AHK script for quickly testing AHK code) returned incorrect values from EM_GETSEL. This may happen with other editors. Finally, this doesn't work with all text editors. In my testing, it didn't work with Sublime Text, for example.

Hopefully it can be useful to someone in spite of these limitations.

EDIT: Code updated to handle encoding differences. Should now work for a lot of text editors (e.g. Notepad, Notepad++, SciTE, etc.)

wo52616111
Posts: 47
Joined: 21 Aug 2014, 04:46

Re: how to get the selected text without using send ^{c}?

Post by wo52616111 » 06 Mar 2016, 08:32

SifJar wrote:This works in some cases (Notepad, Notepad++, SciTE):

Code: Select all

#s::MsgBox % getSelected()

getSelected() {
	ControlGetFocus, control, A
	VarSetCapacity(start, 4)
	VarSetCapacity(end, 4)
	SendMessage, 0xB0, &start, &end, %control%, A		;EM_GETSEL
	ControlGetText, string, %control%, A
	enc := (RegexMatch(string,"[\x{0100}-\x{FFFF}]")?"cp0":"utf-16") ;detect encoding of string
	string := SubStr(StrGet(&string,enc), pos := NumGet(start) + 1, NumGet(end) - pos + 1)
	return string
}
With Notepad++ on one of my computers, the encoding of the returned string is ANSI instead of UTF, so I had to use StrGet(&string, "cp0") in the SubStr() function in place of string. Also, for some reason CodeQuickTester (an AHK script for quickly testing AHK code) returned incorrect values from EM_GETSEL. This may happen with other editors. Finally, this doesn't work with all text editors. In my testing, it didn't work with Sublime Text, for example.

Hopefully it can be useful to someone in spite of these limitations.

EDIT: Code updated to handle encoding differences. Should now work for a lot of text editors (e.g. Notepad, Notepad++, SciTE, etc.)
thank you so much. But I need a plan can works in all cases. I had tried the script, it even can not works in firefox(and some other programs).

garry
Posts: 3795
Joined: 22 Dec 2013, 12:50

Re: how to get the selected text without using send ^{c}?

Post by garry » 06 Mar 2016, 09:23

3 examples

Code: Select all

#NoEnv
SendMode, Input
SetWorkingDir, %A_ScriptDir%
SetTitleMatchMode 2
SetBatchLines, -1


;- CASE-1
;- show marked text
$f7::
{
clipboard:=""
sendinput, ^c{right}
clipwait,2
msgbox, 262208,You copied : ,%clipboard%,
clipboard=
return
}
;---------------------------------------
;- CASE-2
;- show marked text , remove empty lines and add new-line after .?!
$f8::
clipboard:=""
sendinput, ^c{right}
clipwait,2
Text:=clipboard
clipboard:=""
stringreplace,text,text,`.,`.`r`n,all
stringreplace,text,text,`?,`?`r`n,all
stringreplace,text,text,`!,`!`r`n,all
Loop
{
StringReplace,text,text, `r`n`r`n, `r`n, UseErrorLevel
if ErrorLevel = 0                                         ;- No more replacements needed.
        break
}
msgbox, 262208,You copied : ,%text%,
text=
return
;---------------------------------------
;- CASE-3  ( I used to save ahk-scripts )
;- copy URL & TEXT in firefox  and / or save to text-file ( or ahk-file )
$f9::
{
F1=%A_Desktop%\%A_NOW%.txt  ;- rename extension to ahk if you want save an ahk-script
url      :=""
text     :=""
Clipboard:=""
sendinput, ^c{right}
clipwait,2
Text:=clipboard
clipboard:=""
sendinput,!s
sendinput, ^c{right}
clipwait,2
URL:=clipboard
;----- remove empty lines from text -----------------
Loop
{
StringReplace,text,text, `r`n`r`n, `r`n, UseErrorLevel
if ErrorLevel = 0                                         ;- No more replacements needed.
        break
}

;msgbox, 262208,You copied : ,URL=%url%`nText=`n%text%
;- part-2  save to desktop
Formattime,TS,,longdate
Formattime,TT,T12,time
FileAppend,`;-------- saved at %TS% %TT% --------------`r`n`;-------- %url% ---`r`n%text%`r`n,%F1%
Filegetsize,size1,%F1%
Splashimage,,b w600 h150 x100 Y400 CWsilver m9 b fs10 zh0,Size=%size1%`n%url%`n%text%
sleep,990
Splashimage, off
if text<>
   run,%f1%
url      :=""
text     :=""
Clipboard:=""
return
}
;=========================================================


mikagenic
Posts: 93
Joined: 16 Sep 2014, 18:26

Re: how to get the selected text without using send ^{c}?

Post by mikagenic » 09 Feb 2017, 01:28

Here is a solution I came up with, I send ^c, store the result in %selText% and then send +{right}^c+{left}

If there _really_ was a selection then the resulting Clipboard will contain %selText% - it will have one more char or be equal if it was at the end of the document - in either way IfInString, Clipboard, %selText%

If there was no selection but ^c caused a line copy (or anything else), then the resulting Clipboard will contain the character to the right or be empty - it will not contain %selText%

see:

Code: Select all

copySelected()
{
    ClipboardOld:=ClipboardAll
    Clipboard:=""
    SendInput, ^{c}
    ClipWait, 0.1
    if(!ErrorLevel)
    {
        selText:=Clipboard
		Clipboard:=""
        Send, +{right}^c+{left}
		ClipWait, 0.1
		if(!ErrorLevel)
		{
			IfInString, Clipboard, %selText%
			{
				Clipboard:=selText
				return selText
			}
		}
    }
	Clipboard:=ClipboardOld
}

User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: how to get the selected text without using send ^{c}?

Post by jeeswg » 09 Feb 2017, 11:24

Testing on Scratchpad ahk_class MozillaWindowClass.
The following gave numbers if no characters were selected,
but failed if one or more characters were selected:
MsgBox % A_CaretX " "A_CaretY

Btw I would be interested if someone has been able to
retrieve such information regarding carets/selection,
via the Acc library, or UI Automation.
This kind of thing is easy on Edit controls and COM.
E.g. Edit controls: EM_GETSEL.
E.g. Internet Explorer: carets in textboxes: selectionStart, selectionEnd.
Or if someone knows of a way to grab the text
from Excel 2003/2007 when editing macros.
I had an issue with the Home key, because I wanted to select
the whole line, not from the first non-whitespace character onwards.

==================================================

To literally answer the title of your question.
'how to get the selected text without using send ^{c}?':
ControlGetText, COM (Excel/Word/IE), the Acc library/AccViewer,
messages like WM_GETTEXT, LVM_GETITEMTEXT.

Acc library (MSAA) and AccViewer download links - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=26201

GUI COMMANDS: COMPLETE RETHINK - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=5&t=25893
JEE_TreeviewItemGetText
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA

Post Reply

Return to “Ask for Help (v1)”