CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 11 of 11
  1. #1
    Join Date
    Jun 2007
    Posts
    29

    Problem with rapidly pasting from the clipboard under Windows 7

    Ok, I'm a relatively novice programmer, but I designed an app for work that lets you enter data in a much more efficient way, then it needs to paste this data into the very curmudgeonly interface we use for work.
    I designed this app a long time ago while at a different company, and I used VC++ 6. I'm still using VC++ 6, but in a vbox with windows XP.

    The code is being called as part of a bigger function that determines what exactly needs to be pasted into the work app spreadsheet. I have to call each item separately because the work app does not take copied tabs the way Excel would or whatever, it just ignores them. And it also pops up boxes and such that need to be handled in other ways.

    The result works just fine under Windows XP, but when I do it under my regular Win7 box or on the Win7 boxes at work, it does not work properly.

    (forgive the code for being a bit wonky, but I've spent so much time trying to test different things to get this to work)
    This sets the data up, Text being the data to be pasted:
    Code:
    while (1) {
    	if (OpenClipboard() == FALSE) {
    		::Sleep(1);
    		continue;
    	}
    	HGLOBAL clipbuffer;
    	char * buffer;
    	EmptyClipboard();
    	clipbuffer = GlobalAlloc(GMEM_DDESHARE, Text.GetLength()+1);
    	buffer = (char*)GlobalLock(clipbuffer);
    	strcpy(buffer, LPCSTR(Text));
    	GlobalUnlock(clipbuffer);
    	SetClipboardData(CF_TEXT,clipbuffer);
    	CloseClipboard();
    	break;
    }
    No infinite loops yet, again was just testing if it was OpenClipboard failing because it was being called again too quickly or something (and it did happen occasionally).

    Then testing that the clipboard data is correct (this is always true), and pasting with keybd_event. SendInput is not available with VC++ 6.

    Code:
    HGLOBAL hglb;
    LPTSTR lptstr;
    LPTSTR buf = Text.GetBuffer(0);
    
    while (OpenClipboard() == FALSE)
    	::Sleep(1);
    hglb = GetClipboardData(CF_TEXT);
    lptstr = (LPTSTR)GlobalLock(hglb);
    
    if (strcmp(lptstr,buf) != 0)
    	AfxMessageBox("$");
    
    Text.ReleaseBuffer();
    GlobalUnlock(hglb);
    CloseClipboard();
    
    //::Sleep(150);
    keybd_event(VK_CONTROL, 0x0, KEYEVENTF_EXTENDEDKEY | 0, 0);
    keybd_event(0x56, 0x56, 0, 0); //V
    keybd_event(0x56, 0x56, KEYEVENTF_KEYUP, 0);
    keybd_event(VK_CONTROL, 0x0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
    //::Sleep(150);
    If the ::Sleeps are commented out, it will paste the wrong data almost every time under win7. It seems like it pretty much uses the last thing to be copied in the function and pastes it over and over (but not *always*). If I uncomment them, it will work as expected, but it obviously takes longer. With ::Sleep(50), it works about 80-90% of the time. Obviously I can't have the wrong data being pasted, and I'd prefer not to have to wait like this--and perhaps on a slower system or a system that is doing other things it may take longer and paste the wrong thing. It works fine on XP even without the sleeps.

    Did keybd_event become a separate thread or something? Am I doing something wrong with the buffers? (I've tried using CSharedFile too with GMEM_MOVEABLE | GMEM_SHARE | GMEM_ZEROINIT settings, exact same thing.) Why does it work fine under XP but not under 7?

  2. #2
    VictorN's Avatar
    VictorN is online now Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,396

    Re: Problem with rapidly pasting from the clipboard under Windows 7

    Quote Originally Posted by Ixiterra View Post
    Ok, I'm a relatively novice programmer, but I designed an app for work that lets you enter data in a much more efficient way, then it needs to paste this data into the very curmudgeonly interface we use for work.
    I designed this app a long time ago while at a different company, and I used VC++ 6. I'm still using VC++ 6, but in a vbox with windows XP.

    The code is being called as part of a bigger function that determines what exactly needs to be pasted into the work app spreadsheet. I have to call each item separately because the work app does not take copied tabs the way Excel would or whatever, it just ignores them. And it also pops up boxes and such that need to be handled in other ways.

    The result works just fine under Windows XP, but when I do it under my regular Win7 box or on the Win7 boxes at work, it does not work properly.

    (forgive the code for being a bit wonky, but I've spent so much time trying to test different things to get this to work)
    This sets the data up, Text being the data to be pasted:
    Code:
    while (1) {
    	if (OpenClipboard() == FALSE) {
    		::Sleep(1);
    		continue;
    	}
    	HGLOBAL clipbuffer;
    	char * buffer;
    	EmptyClipboard();
    	clipbuffer = GlobalAlloc(GMEM_DDESHARE, Text.GetLength()+1);
    	buffer = (char*)GlobalLock(clipbuffer);
    	strcpy(buffer, LPCSTR(Text));
    	GlobalUnlock(clipbuffer);
    	SetClipboardData(CF_TEXT,clipbuffer);
    	CloseClipboard();
    	break;
    }
    When I see such a Sleep call in a main UI thread I always suspect that there is something wrong in the design!

    Quote Originally Posted by Ixiterra View Post
    Then testing that the clipboard data is correct (this is always true), and pasting with keybd_event. SendInput is not available with VC++ 6.
    FYI: SendInput IS available with VC++ 6 beginning from:
    Quote Originally Posted by MSDN
    Requirements
    Windows NT/2000: Requires Windows NT 4.0 SP3 or later
    Victor Nijegorodov

  3. #3
    Join Date
    Jun 2007
    Posts
    29

    Re: Problem with rapidly pasting from the clipboard under Windows 7

    Thanks for not reading my post, you have been so helpful.

  4. #4
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,620

    Re: Problem with rapidly pasting from the clipboard under Windows 7

    Code:
    //::Sleep(150);
    keybd_event(VK_CONTROL, 0x0, KEYEVENTF_EXTENDEDKEY | 0, 0);
    keybd_event(0x56, 0x56, 0, 0); //V
    keybd_event(0x56, 0x56, KEYEVENTF_KEYUP, 0);
    keybd_event(VK_CONTROL, 0x0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
    //::Sleep(150);
    A very suspicious piece of code. In fact it imitates the situation when user presses keys at light speed. And adding bracing sleeps doesn't make it be less suspicious. If I would do this keypress imitation, the code would look like:
    Code:
    keybd_event(VK_CONTROL, 0x0, KEYEVENTF_EXTENDEDKEY | 0, 0);
    ::Sleep(40);
    keybd_event(0x56, 0x56, 0, 0); //V
    ::Sleep(40);
    keybd_event(0x56, 0x56, KEYEVENTF_KEYUP, 0);
    ::Sleep(10);
    keybd_event(VK_CONTROL, 0x0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
    ::Sleep(10);
    But all this play with keypressing, how it is better than posting WM_PASTE to the required textbox?
    Best regards,
    Igor

  5. #5
    Join Date
    Jun 2007
    Posts
    29

    Re: Problem with rapidly pasting from the clipboard under Windows 7

    Well, by your suggestion I tried this:

    Code:
    		HWND hwnd = ::GetForegroundWindow();
    		LRESULT x = ::SendMessage(hwnd, WM_PASTE, 0, 0);
    hwnd is correct, x is 0, nothing pasted. At least in notepad. Sleeping between the keypresses also made no noticeable difference.

  6. #6
    Join Date
    Jun 2007
    Posts
    29

    Re: Problem with rapidly pasting from the clipboard under Windows 7

    As I said I'm a novice, I discovered I need to actually paste to the specific control, and managed to google my way into working code:

    Code:
    		HWND hwnd = ::GetForegroundWindow();
    		DWORD remoteThreadId = ::GetWindowThreadProcessId(hwnd, NULL);
    		DWORD currentThreadId = ::GetCurrentThreadId();
    		::AttachThreadInput(remoteThreadId, currentThreadId, TRUE);
    		HWND focused = ::GetFocus();
    		::AttachThreadInput(remoteThreadId, currentThreadId, FALSE);
    		::SendMessage(focused, WM_PASTE, 0, 0);
    And the exact same problem remains: pastes fine under XP, pastes very oddly under win7.

  7. #7
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Problem with rapidly pasting from the clipboard under Windows 7

    Quote Originally Posted by Ixiterra View Post
    And the exact same problem remains: pastes fine under XP, pastes very oddly under win7.
    Unless you wrote the Window procedure for the HWND that accepts the WM_PAINT, you really don't know how the WM_PAINT is handled in the HWND you're targeting (or even if WM_PAINT is being handled).

    Window procedures can be re-entrant. In all likelihood, your supersonic sending of WM_PASTE messages are stepping on each other, causing some sort of race condition in the control's handling of WM_PAINT. It is similar in effect to sending text in a rapid fire manner to an asynchronous device -- you don't know what order the messages will be received at the other end.

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; February 4th, 2013 at 11:07 PM.

  8. #8
    Join Date
    Jun 2007
    Posts
    29

    Re: Problem with rapidly pasting from the clipboard under Windows 7

    Quote Originally Posted by Paul McKenzie View Post
    Unless you wrote the Window procedure for the HWND that accepts the WM_PAINT, you really don't know how the WM_PAINT is handled in the HWND you're targeting (or even if WM_PAINT is being handled).

    Window procedures can be re-entrant. In all likelihood, your supersonic sending of WM_PASTE messages are stepping on each other, causing some sort of race condition in the control's handling of WM_PAINT. It is similar in effect to sending text in a rapid fire manner to an asynchronous device -- you don't know what order the messages will be received at the other end.
    I assumed it was something like that, but I know far too little about the internals of this type of stuff to be able to pinpoint the problem. I'm willing to have the program wait until the paste has resolved, but I have no idea how to do that, and using a kludgy method like ::Sleep is an annoying compromise. It would be nice if Win7 just exhibited the WinXP behavior though.

  9. #9
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: Problem with rapidly pasting from the clipboard under Windows 7

    There is a Win32 API WaitForInputIdle(...) function that waits until the specified process is waiting for user input with no input pending. Instead of using Sleep(...) this might provide the required synchronisation.

  10. #10
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,620

    Re: Problem with rapidly pasting from the clipboard under Windows 7

    Quote Originally Posted by Ixiterra View Post
    It would be nice if Win7 just exhibited the WinXP behavior though.
    You have no diagnostics as to what part of your machinery behaves different. Win7 is definitely not WinXP, so to apply some cure you should find out what, where and why goes wrong. You're focused somehow on your automating tool only, but problem (or some part of it) may be in your "work app" alright.
    Best regards,
    Igor

  11. #11
    Join Date
    Jun 2007
    Posts
    29

    Re: Problem with rapidly pasting from the clipboard under Windows 7

    98% of my testing is done at home, using notepad. If it doesn't work in notepad, it sure isn't going to work in the clunky work app. I should mention that I have a running version that I use at work, but I am trying to get it to the point of being usable for coworkers, which is not an easy task. If the program fails to paste the data 100% correctly, that will be a confusing and frustrating situation. I don't want them to have to trade one crappy app for another.

    Programming is just an occasional hobby of mine, and this is the first and only windows app I've ever coded, but I've got quite a few hundred hours in it and it can do some really nice things. This is a critical part though, and I've done very little with win32 stuff. This is an MFC project if the hints were missed.

    Anyways, as an update, I changed some things around that shouldn't have mattered, and I've apparently found a way to make this work with a ~10msec interval between pastes, apparently 100% reliably, at least so far on win7 notepad. I haven't been able to test it in the "real world" environment yet, but will soon. WaitForInputIdle was an interesting function, it did not seem to make any difference in testing (and I am not sure I am using it correctly, very difficult to find examples), but I left a switch for it so that I can test it out in the work app.
    Last edited by Ixiterra; February 7th, 2013 at 09:17 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured