• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1408
  • Last Modified:

transferring UNICODE text to another application (through clipboard and not only)

i need my program to read unicode format text file (quite small - a few hundred lines) and transfer its contents to another application on hotkey (registered global hotkey) press.

i don't have any problems with registering the hotkey and it seems that also reading the file doesn't encounter any problems:

Private Function ReadFileUnicode(strFileName As String) As String
Dim strFileCont As String
Dim intFreeNum As Integer

  intFreeNum = FreeFile() 'get the free file handle number
  Open strFileName For Binary As intFreeNum 'open the file for reading it in binary mode
    strFileCont = Space(LOF(intFreeNum)) 'fill var with the spaces equal to the currently read file length (in bytes)
    Get #1, 3, strFileCont 'read the file data starting from byte 3 into var - first two bytes are useless
    ReadFileUnicode = StrConv(strFileCont, vbFromUnicode) 'convert text and return it
  Close #1 'close the file

End Function

i have tested it with MS Forms 2.0 TextBox control which supports correct unicode text displaying - and yes, text is displayed correctly. however i'm not sure i'm reading unicode file best way -  maybe someone can advice a better way.

the biggest problems i encounter with are when it comes to transfering the file contents to another application. let's say i want to transfer read data to Microsoft Word. what i tried first is:

Dim strFileConts as String
strFileConts = ReadFileUnicode("c:\TheUnicodeFile.txt") 'read file and store in var
AppActivate ("Document1 - Microsoft Word") 'give focus to Word
SendKeys (strFileConts) 'send file contents to Word by simulating key pressing

unfortunately that doesn't transfer anything to Word. Word activates and receives the focus but nothing is transferred to it. what i tried next is putting the DoEvents statement after the AppActivate statement in the previous code. this time text is transferred. the only problem is that it works_VERY_SLOW. on my 1.2 ghz celeron machine transferring only a few lines of text causes to freeze the input. this is not acceptable.

what i tried next is transferring text to Word through the clipboard object and then simulating the key combination for 'paste from clipboard' procedure:

Dim strFileConts as String
strFileConts = ReadFileUnicode("c:\TheUnicodeFile.txt")
Clipboard.Clear 'clear clipboard; don't know why but without emptying clipboard i can't paste data
Clipboard.SetText (strFileConts) 'set clipboard text
AppActivate ("Document1 - Microsoft Word")
SendKeys ("+{Insert}") 'simulate Shift + Insert key combination = 'paste from clipboard'

this time text transfers instantly, without freezing machine. the problem now is that all non-ASCII characters are replaced with the question mark (?) symbols. it seems that putting unicode text to the clipboard corrupts all 'special characters'. this also is not acceptable. i have tried to convert text before putting to the clibpoard to unicode (StrConv(strFileConts, vbUnicode)) or set clipboard format to vbCFRTF and even to operate clipboard directly with Win32Api functions but the results are the same. setting CF_UNICODETEXT as a clipboard format with WinSetClipboardData function also doesn't make any sense - just corrupts text completely (all characters now are replaced by the square-like symbols).

what i tried next? well i noticed that other unicode supporting programs e.g. Microsoft Word can put to the clipboard unicode text very well without corrupting it - for example if i load in word the same unicode text file, selecting all with CTRL + A and simply copy its contents with CTRL + C to clipboard and paste with CTRL + V into another unicode supporting application (for example WinXP Notepad) - everything is copied correctly. so what i tried is to simulate such action in my application namely:

1. putting on form Microsoft Forms 2.0 TextBox control
2. resizing it as small as possible and hiding (by sending to back) under the other needed control because in my case i don't want to show the user this TextBox - it's useless for the user because it is needed only for intermediary process purposes
3. reading and loading in it unicode text file
4. programmatically selecting all text in TextBox with SelStart and SelLength properties
5. setting focus to TextBox
6. sending 'copy to clipboard' hotkey
7. activating needed application
8. sending 'paste from clipboard' hotkey

here goes the code (if form has TextBox1 control):

Dim strOutput As String
strOutput = ReadFileUnicode("c:\TheUnicodeFile.txt")
TextBox1.Text = ""
TextBox1.Text = strOutput
TextBox1.SelStart = 0
TextBox1.SelLength = Len(TextBox1.Text)
SendKeys ("^{Insert}")
AppActivate ("Document1 - Microsoft Word")
SendKeys ("+{Insert}")

and it really works. however there are some drawbacks with this method:

1. you can't redistribute Microsoft Forms 2 dll with your application - it must be already present on the user's pc (and it is present only if he/she has installed Microsoft Office). otherwise application won't run
2. it seems to me that displayed output in TextBox is still dependant on installed set of fonts on every individual pc. that leads to think that there can be situation that on some pc's that don't have correct fonts for displaying the current unicode file the text gets corrupted thus also the transferred text to the other application is corrupted
3. using such method seems to me like 'walking into the house through the backdoors' or 'scratching the left ear with the right hand' i.e. a bit weird
4. it is not acceptable for me in this case because my application runs hidden in systray and i can't set focus to hidden form's textbox (SetFocus method is valid only for visible controls). what i tried is to make form visible on user hotkey press, make its size both width and height to 0 and then put previous code. but this again involves problems - text is not always transferred on hotkey press - it again receives focus but nothing is transferred. i have again experimented with putting DoEvents in some places in code but nothing helps.

finally i want to know how to transfer my unicode text to another application correctly and fast and without 'walking into the house through the backdoors'. actually i don't care which way it is - through the clipboard or in some other way. what i know for sure is that it is possible to do this without 'walking into the house through the backdoors' because in the previous method text gets transferred to clipboard correctly somehow when Windows OS itself operates with clipboard (when i press CTRL + C/CTRL + INSERT)

p.s. this all was tried under WinXP
1 Solution
This may help ,, and maybe not ,, :)
but first of all you must get the handle of the Application you want to send the unicode text to

Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal Hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Const WM_PASTE = &H302
Private Const WM_SETTEXT = &HC
Dim ReceiverHWND as long 'you must know the hwnd of it ( Use SPY++)

ReceiverHWND = f000102FA ' this is an example of the handle for the destination

Dim strOutput As String
strOutput = ReadFileUnicode("c:\TheUnicodeFile.txt")
TextBox1.Text = ""
TextBox1.Text = strOutput

Clipboard.SetText TextBox1.Text, ClipBoardConstants.vbCFText
call SendMessage(ReceiverHWND, WM_PASTE , 0, 0)


please send any comments ,,
Clipboard.SetText always converts to ANSI.  If you want to copy the text and preserve its Unicode-ness, you need to use these Windows APIs:

Private Declare Function OpenClipboard lib "user32" (byval hWnd as Long) as Long
Private Declare Function SetClipboardData lib "user32" (byval Format as Long, byval hMem as Long) as Long
Private Declare Function CloseClipboard lib "user32" () as Long
Private Declare Function EmptyClipboard lib "user32" () as Long
Private Declare Function GlobalAlloc lib "kernel32" (byval Flags as Long, byval len as Long) as Long
Private Declare Function GlobalLock lib "kernel32" (byval hMem as Long) as Long
Private Declare Function GlobalUnlock lib "kernel32" (byval hMem as Long) as Long
Private Declare Sub RtlMoveMemory lib "kernel32" (byval pDest as Long, byval pSource as Long, byval len as Long)

Private Const CF_UNICODETEXT = &h0d&
Private Const GMEM_MOVEABLE = &2&
Private Const GMEM_ZEROINIT = &40&

Here's how it's done:

Dim hMem as Long, pMem as Long, StringToCopy as String
StringToCopy = "Whatever blah blah blah"
Call OpenClipboard(Me.hWnd)
Call EmptyClipboard()
hMem = GlobalAlloc(GMEM_MOVEABLE or GMEM_ZEROINIT, LenB(StringToCopy))
pMem = GlobalLock(hMem)
Call RtlMoveMemory(pMem, StrPtr(StringToCopy), LenB(StringToCopy))
Call GlobalUnlock(hMem)
Call SetClipboardData(CF_UNICODETEXT, hMem)
Call CloseClipboard()
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now