Send copy to active window

  • Thread starter Thread starter Alan Sloan
  • Start date Start date
A

Alan Sloan

I have a vb.net app in which I have setup a "hotkey" where when the user
types that key combo, something is supposed to happen. The hotkey part is
working and fires perfectly. What this is supposed to do, is copy whatever
text is selected, no matter where the user is in the system, either my app,
notepad, whatever, and copy that text to the clipboard.

I have tried SendMessage API, VB's SendKeys, and It only seems to work
sometimes. I would prefer to use SendMessage with a WM_COPY but can't get
it to work at all, so I've been using SendKeys, sending "^c" with sporatic
results.

Any suggestions?

Thanks,
Alan
 
Alan Sloan said:
I have a vb.net app in which I have setup a "hotkey" where when the user
types that key combo, something is supposed to happen. The hotkey part is
working and fires perfectly. What this is supposed to do, is copy whatever
text is selected, no matter where the user is in the system, either my app,
notepad, whatever, and copy that text to the clipboard.

I have tried SendMessage API, VB's SendKeys, and It only seems to work
sometimes. I would prefer to use SendMessage with a WM_COPY but can't get
it to work at all, so I've been using SendKeys, sending "^c" with sporatic
results.

Below is code to get the window with the focus, and copies the selection to
the clipboard. GetForegroundWindow() gets the main window handle, like
Notepad's main window, not the text box control within it. There is another
function that would get the text box handle, GetFocus(), but it require more
works to make it work with other processes. The code below uses
GetGUIThreadInfo(), then gets the text box handle using hwndFocus member.

To try the sample, add a Timer, and a TextBox to Form1. Set the TextBox's
Mutliline property to True, and set the Timer interval to 5000. Run the
project, then start Notepad, type some text then select it.

Option Explicit On

Public Class Form1

Private Declare Function GetForegroundWindow Lib "user32" () As Integer
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal
hWnd As Integer, ByRef lpdwProcessId As Integer) As Integer
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA"
(ByVal hWnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer,
ByVal lParam As Integer) As Integer
Private Declare Function GetGUIThreadInfo Lib "user32.dll" (ByVal
idThread As Integer, ByRef pgui As GUITHREADINFO) As Integer
Private Const WM_COPY As Integer = &H301
Private Structure RECT
Dim Left_Renamed As Integer
Dim Top As Integer
Dim Right_Renamed As Integer
Dim Bottom As Integer
End Structure
Private Structure GUITHREADINFO
Dim cbSize As Integer
Dim flags As Integer
Dim hwndActive As Integer
Dim hwndFocus As Integer
Dim hwndCapture As Integer
Dim hwndMenuOwner As Integer
Dim hwndMoveSize As Integer
Dim hwndCaret As Integer
Dim rcCaret As RECT
End Structure

Private Function GetFocusWindow() As Integer
Dim h As Integer
Dim ThreadID As Integer
Dim gui As GUITHREADINFO
Dim ret As Integer

h = GetForegroundWindow()
Console.WriteLine("GetFocusWindow: ForegroundWindow = " & Hex(h))
ThreadID = GetWindowThreadProcessId(h, 0)
gui.cbSize = Len(gui)
ret = GetGUIThreadInfo(ThreadID, gui)
If ret = 0 Then
Console.WriteLine("GetFocusWindow: GetGUIThreadInfo failed.
LastDllError = " & Err.LastDllError)
Exit Function
End If
Console.WriteLine("GetFocusWindow: hwndFocus = " &
Hex(gui.hwndFocus))
GetFocusWindow = gui.hwndFocus
End Function

Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Timer1.Tick
Me.Text = Hex(GetFocusWindow())
SendCopyToWindow(GetFocusWindow())
TextBox1.Text = Clipboard.GetText
End Sub

Private Sub SendCopyToWindow(ByVal hWnd As Integer)
SendMessage(hWnd, WM_COPY, 0, 0)
End Sub

End Class
 
Nobody said:
Below is code to get the window with the focus,

Nowadays, 64 bit OSes are not rare not find. Therefore I'd be careful when posting
these declarations that only work on 32 bit systems.
 
Armin Zingler said:
Nowadays, 64 bit OSes are not rare not find. Therefore I'd be careful when
posting
these declarations that only work on 32 bit systems.

If there was a .Net library function, then it should be used, but I can't
find any. 64-Bit OS'es support 32-Bit applications. Obviously, the code need
some work if one wants to compile the app as 64-Bit.
 
If there was a .Net library function, then it should be used, but I can't
find any. 64-Bit OS'es support 32-Bit applications. Obviously, the code need
some work if one wants to compile the app as 64-Bit.

The main problem is your declares... Your handles should be declared IntPtr -
as IntPtr is automatically the size of the system ptr type (32-bit on 32 bit
windows, 64-bit on 64-bit windows). And you should not alias your functions
to the A versions of the functions. I would drop the alias all together and
either use Unicode or Auto on the declare.

Win64 for the most part is Win32 with 64-bit pointers. Using IntPtr for you
handles and ptr types should go a long way in making your code 64-bit
compatible.
 
That worked beautifully!! I took it out of the timer and put it in my
hotkey pressed routine and it works every time!!

Thanks a ton!
 
Back
Top