how do i get the text marked by the mouse (in blue) which hasn't been copied
in to a string variable or textbox ?
Printable View
how do i get the text marked by the mouse (in blue) which hasn't been copied
in to a string variable or textbox ?
It's called selected text.
And do you mean in your project, or a third party app? Like Notepad, a web browser, etc?
That depends on what the "source" is, for a TextBox control it is simply the SelectedText property. To set the text of a TextBox control or a String variable to this value you can just assign the value:
For an external program (3rd party) you will have to go into API's.Code:Dim mystring As String
mystring = TextBox1.SelectedText
TextBox2.Text = TextBox1.SelectedText
from an external source like an internet browser, word, excel
That's going to be a lot tricker, if it's even possible at all. Which I'm not convinced it is.
No matter how you do this, you're going to have to invoke some APIs. I can't imagine something like this is built into the framework, but I could be wrong. Either way, there most likely won't be a copy and paste solution.
If you're wanting to get text from an app that has an edit control, then you'll probably have to use the FindWindow API to the get the apps, then FindWindowEx to get child windows, like text boxes, labels, etc. If you just want to get the selected text from a web browser, then you can probably just do FindWindow.
From here, you have two options. If you want to get the text as it's selected, you can use the GetCursorPos API and then use SendMessage and use one of the following constants: WM_GETTEXT, EM_GETSELTEXT, or EM_GETSELTEXT. But, like I mentioned, this only works for windows that have an edit control. Like textboxes.
I'm not really sure how'd you be able to get the data via the web browser.
Perhaps you could tell us what you're trying to accomplish? If we knew the end result, we might be able to offer a better solution. Going this route will take a very long time, especially if you're not familiar with Windows APIs.
Yep, for that you need to do the following in the following order:
1. Get the control that has focus:
2. Check if this control contains children and if so check recursively. Check if the (final) control is a TEXTBOX control by reading out the classname.Code:Private Declare Function GetFocus Lib "user32" () As IntPtr
3. Get the selected text using EM_SELTEXT using SendMessage or DefWindowProc as weirddemon suggested.
4. Process the text, since it is probably a pointer to etc.
i will need the vb.net command to activate copy on an external(non vb.net) program (such as IE)
That's not the end result though. I already told you how to do it and bergerkiller basically said the same. So if you want to do it, that's what you're probably going to have to do.
We could provide an alternative, if we knew why you needed to do this. But, from the sound of it, there might not be.
i"ll combine it with
My.Computer.Clipboard.GetText()
My.Computer.Clipboard.SetText()
the trigger :
when the mouse is left clicked and draged
Ugh... You never answer the questions as they need to be.
If I was making an application and I asked someone, "how do I get the a process?" and someone said I could do it via methods a, b, c, and d and they asked what my purpose was, I wouldn't say, "to get the process", I would tell them what I'm trying to do.
I'd say, "I'm trying to get the top most process so I can minimize it" Or whatever and then they'd be able to tell me the best option.
But here's the thing, if you want to do this, you're going to have to invoke APIs, there's no real way around this. So if you're not going to go to tell us what you're doing, then you'll just need to stick with what we suggested and try that. If not, then you'll need to abandon it.
*Edit
We know, I told you what you need to do. Use the APIs I mentioned, GetWindow, GetWindowEx, SendMessage, GetCursorPos and then copy to clipboard. You might not need to use send message, if you just copy directly, but you'll need to figure out when the cursor has stopped moving.Quote:
the trigger :
when the mouse is left clicked and draged
For the trigger use the GetAsyncKeyStatefunction:
Returns true if the specified key is down. You can check for the LMouseButton.Code:Private Declare Function GetAsyncKeyState Lib "user32" (ByVal Key As Windows.Forms.Keys) As Boolean
My previous code for getting the Focused window will not work btw, since it has to be on the calling thread. (same program)
You will then have to go with looping through the child controls. You could also send a "COPY" command:
I guess that is easier than calling the EM_SELTEXT function.Code:Public Declare Function DefWindowProc Lib "user32" Alias "SendMessageA" (ByVal hWnd As Int32, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
Public Shared Function Copy(ByVal hwnd As IntPtr) As Integer
Return DefWindowProc(hwnd, &H301, 0, 0)
End Function
Only problem that remains is getting the actual window the user is currently in...
Which isn't really too hard. He'll have to use GetWindow to get the topmost window, the app, but he'll also need to loop through the current processes, get the handle for the process he wants to check and pass it to the API.Quote:
Originally Posted by bergerkiller
For someone of his skill, this is probably going to be a rather difficult and time consuming task.
I got it figured out. I added the function in my API Window class:
I can now actually get the active window from ANY child window!Code:Public Function AttachInput(Optional ByVal attach As Boolean = True) As Boolean
Return CBool(API.AttachThreadInput(GetWindowThreadProcessId(Me.hwnd, 0), API.GetCurrentThreadId(), CInt(attach)))
End Function
Public Function DetachInput() As Boolean
Return AttachInput(False)
End Function
And can do any commands I wish with this focused window.Code:Public Property FocusedWindow() As Window
Get
Me.AttachInput()
FocusedWindow = New Window(GetFocus)
Me.DetachInput()
End Get
Set(ByVal value As Window)
value.Command(CMD.Focus)
End Set
End Property
Getting that of any Window at all:
Final result: simple coding.Code:Public Shared Function GetFocused() As Window
Return GetForeground.FocusedWindow
End Function
Final coding for those not using my Window class:Code:Dim ww As Window = Window.GetFocused
MsgBox(ww.Text)
Remaining code to get the current selected text (copy it):Code:Public Declare Function AttachThreadInput Lib "user32" (ByVal idAttach As Integer, ByVal idAttackTo As Integer, ByVal fAttack As Int32) As Boolean
Public Declare Function GetCurrentThreadId Lib "kernel32" () As Integer
Public Declare Function GetForegroundWindow Lib "user32" () As IntPtr
Public Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As IntPtr, ByRef lpdwProcessId As Integer) As Integer
Public Declare Function GetFocus Lib "user32" () As IntPtr
Public Shared Function AttachInput(ByVal hwnd As IntPtr, ByVal attach As Boolean) As Boolean
Return CBool(AttachThreadInput(GetWindowThreadProcessId(hwnd, 0), GetCurrentThreadId(), CInt(attach)))
End Function
Public Shared Function GetFocusedWindow() As IntPtr
Dim foreground As IntPtr = GetForegroundWindow
AttachInput(foreground, True)
GetFocusedWindow = GetFocus
AttachInput(foreground, False)
End Function
Code:Public Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Integer, ByVal lpClassName As System.Text.StringBuilder, ByVal nMaxCount As Integer) As Integer
Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Int32, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
Public Const WM_COPY = &H301
Public Shared Function GetClassName(ByVal hwnd As IntPtr, Optional ByVal length As Integer = 128) As String
Dim s As New System.Text.StringBuilder(length)
GetClassName(hwnd, s, s.Capacity)
Return s.ToString()
End Function
Public Shared Function CopyText() As String
Dim focus As IntPtr = GetFocusedWindow()
Dim classname As String = GetClassName(focus)
'check if this type of Window can be copied from (optional)
SendMessage(focus, WM_COPY, 0, 0)
Return Clipboard.GetData(DataFormats.Text)
End Function
One question remains though: how can I get a boolean indicating if two Thread ID's share their input? I do not want the Input detached when the user had attached the windows before.
When the windows' threads are already attached, the attach and detach functions should not take place AT ALL.
Sounded like the posted wanted to copy selected text into clipboard/a list. But automatically?
Don't think there's a way for Windows to know if a text is selected, such as throwing an event?
Wish it was that easy. Even in .NET there is no event for "selection changed". All you can do there is watch for mouse and key events.
My code does work though. It returns the Window the user is currently in, and performs the WM_COPY command on it. If the Window can handle this command, it will copy the text selected to the clipboard. I am afraid, though, that it would interfere with user dragging. Best to use it after a mouseUP event.