Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C++ VC++
I am a newbie to C++. I was trying to convert the function here to set html unicode text to clipboard. This is what I have done so far:
 
bool CopyHTML2(WCHAR *html ){
    wchar_t *buf = new wchar_t [400 + wcslen(html)];
    if(!buf) return false;
 
	static int cfid = 0;
    if(!cfid) cfid = RegisterClipboardFormat("HTML Format");
 
	    // Create a template string for the HTML header...
    wcscpy(buf,
        L"Version:0.9\r\n"
        L"StartHTML:00000000\r\n"
        L"EndHTML:00000000\r\n"
        L"StartFragment:00000000\r\n"
        L"EndFragment:00000000\r\n"
        L"<html><body>\r\n"
        L"<!--StartFragment -->\r\n");
 
    // Append the HTML...
    wcscat (buf, html);
    wcscat (buf, L"\r\n");
    // Finish up the HTML format...
    wcscat (buf,
        L"<!--EndFragment-->\r\n"
        L"</body>\r\n"
        L"</html>");
 
	wchar_t *ptr = wcsstr(buf, L"StartHTML");
	wsprintfW(ptr+10, L"%08u", wcsstr(buf, L"<html>") - buf);
	*(ptr+10+8) = L'\r';
 
    ptr = wcsstr(buf, L"EndHTML");
    wsprintfW(ptr+8, L"%08u", wcslen(buf));
    *(ptr+8+8) = '\r';
 
    ptr = wcsstr(buf, L"StartFragment");
    wsprintfW(ptr+14, L"%08u", wcsstr(buf, L"<!--StartFrag") - buf);
    *(ptr+14+8) = '\r';
 
    ptr = wcsstr(buf, L"EndFragment");
    wsprintfW(ptr+12, L"%08u", wcsstr(buf, L"<!--EndFrag") - buf);
    *(ptr+12+8) = '\r';
 
	// Open the clipboard...
    if(OpenClipboard(0)) {
        EmptyClipboard();
        HGLOBAL hText = GlobalAlloc(GMEM_MOVEABLE |GMEM_DDESHARE, wcslen(buf)+4);
        wchar_t *ptr = (wchar_t *)GlobalLock(hText);
        wcscpy(ptr, buf);
        GlobalUnlock(hText);
        SetClipboardData(cfid, hText);
        CloseClipboard();
        GlobalFree(hText);
    }
 
    // Clean up...
    //delete [] buf;
	return true;
}
 
I get the following error at SetClipboardData function:
 
HEAP[Project1.exe]: Heap block at 00378038 modified at 0037813E past requested size of fe
Project1.exe has triggered a breakpoint.
 
Any idea on how to solve this? Also is it the right way to do this? Or is there a simpler way to do it?
 
Thanks in advance for all your help.
Posted 12-Apr-13 20:35pm
Comments
Richard MacCutchan at 13-Apr-13 4:36am
   
All the code from the line wsprintfW(ptr+8, L"%08u", wcslen(buf)); is impossible to understand, but looks very likely to cause corruption. Start again in building your buffer but make sure that at every point you do not overflow it.

1 solution

Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

I did not see the source for the heap error but you also asked for the right or simpler way. At first you should know that the HTML clipboard format must contain UTF-8 encoded text. So the input text must be converted to UTF-8 and prefixed with the HTML format header. A snippet from one of my projects (lpszWide is the HTML text as wide string including the HTML and fragment start and end markers):
 
// Get length of UTF-8 string including terminating NULL char.
// The MSDN does not mention if the string should be NULL terminated or not.
// Providing the NULL terminator is safe and always better.
int nUtf8Size = ::WideCharToMultiByte(CP_UTF8, 0, lpszWide, -1, NULL, 0, NULL, NULL);
if (nUtf8Size < 1)
{
    TRACE0("CHtmlFormat::SetHtml: UTF-8 conversion failed\n");
    ASSERT(0);
    return false;
}
// Allocate buffer for HTML format descriptor and UTF-8 content. 
// NOTE: Adjust length definition when changing the descriptor!
const int nDescLen = 105;
hGlobal = ::GlobalAlloc(GMEM_MOVEABLE, nDescLen + nUtf8Size);
if (NULL != hGlobal)
{
    // Convert to UTF-8
    bool bErr = false;
    LPSTR lpszBuf = static_cast<LPSTR>(::GlobalLock(hGlobal));
    LPSTR lpszUtf8 = lpszBuf + nDescLen;
    if (::WideCharToMultiByte(CP_UTF8, 0, lpszWide, -1, lpszUtf8, nUtf8Size, NULL, NULL) <= 0)
    {
        TRACE0("CHtmlFormat::SetHtml: UTF-8 conversion failed\n");
        bErr = true;
    }
    else
    {
        // Get the fragment marker positions
        LPCSTR lpszStartFrag = strstr(lpszUtf8, "<!--StartFragment-->");
        LPCSTR lpszEndFrag = strstr(lpszUtf8, "<!--EndFragment-->");
        ASSERT(lpszStartFrag);
        ASSERT(lpszEndFrag);
        // Adjust pointer to be behind inserted string followed by CR-LF
        lpszStartFrag += strlen("<!--StartFragment-->") + 2;
        // Create descriptor and prepend it to the string.
        // Use only ASCII chars here!
        // Using leading zeroes with the offsets here to avoid iterative calculations.
        // With valid nDescLen, _snprintf() will not append the NULL terminator here.
        VERIFY(nDescLen == _snprintf(
            lpszBuf, nDescLen,
            "Version:1.0\r\nStartHTML:%010d\r\nEndHTML:%010d\r\nStartFragment:%010d\r\nEndFragment:%010d\r\n",
            nDescLen, 
            nDescLen + nUtf8Size - 1,		// offset to next char behind string
            nDescLen + static_cast<int>(lpszStartFrag - lpszUtf8), 
            nDescLen + static_cast<int>(lpszEndFrag - lpszUtf8)));
    }
    ::GlobalUnlock(hGlobal);
    if (bErr)
    {
        ::GlobalFree(hGlobal);
        hGlobal = NULL;
    }
}
return NULL != hGlobal;
  Permalink  
Comments
madharasan1 at 13-Apr-13 8:45am
   
To @Jochen A: I did make it work thanks a lot. Can you please explain what these lines do:
>>nDescLen = 105;
What does 105 stand for? and
>>VERIFY(nDescLen == _snprintf(...
What does his statement do? I mean what is the effect of this comparison?
 
Since I have only expression edition of Visual Studio Expression Edition, Can I remove all the macros? I mean like TRACE0, ASSERT and VERIFY? Will there be any side effects?
Jochen Arndt at 13-Apr-13 9:05am
   
105 is the length of the formatted HTML descriptor string.
 
The macros are only effective with debug builds. The VERIFY macro just checks if the length is 105. If the format string is not changed in the future, it can be removed. The TRACE macros can be removed or replaced by error messages. The ASSERT macros can be removed or replaced by code that returns from the function when the condition fails.
 
There will be no side effects for release builds. But the macros should be also present with the Express Edition.
madharasan1 at 13-Apr-13 10:43am
   
Thanks a lot for that explanation.. :)
madharasan1 at 5-May-13 6:13am
   
Hi Jochen Arndt, Here is my full code: http://pastebin.com/wEFFCSNf When even I try to paste in Office Word, PowerPoint, Excel it works perfectly, but when I paste in OneNote, it pastes some gibberish values after the anchor tag. It happens only with the anchor tag and only to a unicode text. Is there any specific reason for this? Is this a bug in MS Office OneNote? or Is something wrong with my implementation? Any ideas?
Jochen Arndt at 6-May-13 3:28am
   
I don't use OneNote. so I can't help much. You may write the generated clipboard data to a file and check it with a Hex editor and an UTF-8 capable text editor.
If your data contain a HTML header (head tags), it may help to add a charset definition:
<meta http-equiv="content-type" content="text/html; charset=utf-8">
madharasan1 at 6-May-13 5:28am
   
I do have that meta tag in my code. But let me try things you have suggested.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
0 Mathew Soji 309
1 BillWoodruff 300
2 Afzaal Ahmad Zeeshan 252
3 DamithSL 225
4 Maciej Los 215
0 OriginalGriff 6,249
1 Sergey Alexandrovich Kryukov 5,853
2 DamithSL 5,183
3 Manas Bhardwaj 4,673
4 Maciej Los 3,865


Advertise | Privacy | Mobile
Web02 | 2.8.1411019.1 | Last Updated 13 Apr 2013
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100