2015-10-26 5 views
1

Ранее после вызова VirtualStringGrid -> CopyToClipBoard я мог вставлять сетку в виде текста с вкладками в блокнот или в виде полностью отформатированной сетки (заголовки и цвет и границы) при вставке в Excel или Outlook.TVirtualStringGrid CopyToClipboard issue Embarcadero Seattle C++

Однако у меня возникают проблемы с CopyToClipboard, так как я перешел из Embarcadero XE8 в RAD Seattle с VirtualTreeView V6.2: я могу вставлять только текст, если целевое приложение - это своего рода текстовый редактор. Вставка какого-либо «богатого» приложения, принимающего RTF или html, приводит к ошибке.

Я попытался вызвать методы ContentToXXX (см. Код ниже), текст экспортируется в порядке. Html экспортируется, но в результате строка Data2Export содержит весь код на странице html и не может быть вставлена ​​в Outlook, например. Любой звонок в ContentToRTF приводит к сбою.

Я искал эту проблему, но не нашел ничего подходящего.

void __fastcall TForm::ExportGrid(void) 
{ 
// old code that used to work fine 
// VST->CopyToClipboard(); 

    Virtualtrees::TVSTTextSourceType exportSrcType = tstAll; 

    OpenClipboard(Handle); 
    EmptyClipboard(); 

    std::string Data2Export = ""; 
    HGLOBAL hg; 

    // tabbed text 
    Data2Export = AnsiString(VST->ContentToText(exportSrcType, "\t")).c_str(); 
    hg = GlobalAlloc(GMEM_MOVEABLE, Data2Export.size() + 1); 

    if (!hg) 
    { 
    CloseClipboard(); 
    return; 
    } 

    memcpy(GlobalLock(hg), Data2Export.c_str(), Data2Export.size() + 1); 
    GlobalUnlock(hg); 
    SetClipboardData(CF_TEXT, hg); 
    GlobalFree(hg); 

    // html 
    Data2Export = AnsiString(VST->ContentToHTML(exportSrcType)).c_str(); 
    hg = GlobalAlloc(GMEM_MOVEABLE, Data2Export.size() + 1); 

    if (!hg) 
    { 
    CloseClipboard(); 
    return; 
    } 

    memcpy(GlobalLock(hg), Data2Export.c_str(), Data2Export.size() + 1); 
    GlobalUnlock(hg); 
    SetClipboardData(CF_HTML, hg); 
    GlobalFree(hg); 

    // RTF 
    Data2Export = AnsiString(VST->ContentToRTF(exportSrcType).c_str()).c_str(); 
    hg  = GlobalAlloc(GMEM_MOVEABLE, Data2Export.size() + 1); 

    if (!hg) 
    { 
    CloseClipboard(); 
    return; 
    } 

    memcpy(GlobalLock(hg), Data2Export.c_str(), Data2Export.size() + 1); 
    GlobalUnlock(hg); 
    SetClipboardData(CF_TEXT, hg); 
    GlobalFree(hg); 

    CloseClipboard(); 
} 

Любая идея о том, как решить эту проблему или решить эту проблему?

Что-то не так с кодом?

PD: платформа dev - это Win8 и Win10, а в VirtualStringTree для ClipboardFormats установлено значение true.

ответ

1

Вы звоните GlobalFree() после каждого звонка до SetClipboardData(). ВЫ НЕ ДОЛЖНЫ СДЕЛАТЬ ЭТО, если SetClipboardData() не удается. Документация очень ясно по этому вопросу:

SetClipboardData function

Если SetClipboardData успешно, система принадлежит объект, идентифицированный параметром hMem. Приложение не может записывать или освобождать данные после того, как собственность была перенесена в систему, но она может блокировать и считывать данные, пока не будет вызвана функция CloseClipboard. (Память должна быть разблокирована до закрытия буфера обмена.) Если параметр hMem идентифицирует объект памяти, объект должен быть выделен с помощью функции с флагом GMEM_MOVEABLE.

Кроме того, вы сохраняете свои блоки данных текста и RTF в буфер обмена, используя тот же формат CF_TEXT. Ваши RTF-данные должны использовать формат CF_RTF.

Попробуйте это:

#include <richedit.h> 

void __fastcall TForm::ExportGrid(void) 
{ 
    // old code that used to work fine 
    // VST->CopyToClipboard(); 

    Virtualtrees::TVSTTextSourceType exportSrcType = tstAll; 

    if (!OpenClipboard(Handle)) return; 
    try 
    { 
     EmptyClipboard(); 

     AnsiString Data2Export; 
     HGLOBAL hg; 

     // tabbed text 
     Data2Export = VST->ContentToText(exportSrcType, "\t"); 
     hg = GlobalAlloc(GMEM_MOVEABLE, Data2Export.size() + 1); 
     if (hg) 
     { 
      memcpy(GlobalLock(hg), Data2Export.c_str(), Data2Export.Length() + 1); 
      GlobalUnlock(hg); 
      if (!SetClipboardData(CF_TEXT, hg)) // or maybe CF_CSV instead... 
       GlobalFree(hg); 
     } 

     // html 
     Data2Export = VST->ContentToHTML(exportSrcType); 
     hg = GlobalAlloc(GMEM_MOVEABLE, Data2Export.Length() + 1); 
     if (hg) 
     { 
      memcpy(GlobalLock(hg), Data2Export.c_str(), Data2Export.Length() + 1); 
      GlobalUnlock(hg); 

      if (!SetClipboardData(CF_HTML, hg)) 
       GlobalFree(hg); 
     } 

     // RTF 
     Data2Export = VST->ContentToRTF(exportSrcType); 
     hg = GlobalAlloc(GMEM_MOVEABLE, Data2Export.Length() + 1); 
     if (hg) 
     { 
      memcpy(GlobalLock(hg), Data2Export.c_str(), Data2Export.Length() + 1); 
      GlobalUnlock(hg); 

      if (!SetClipboardData(CF_VRTF, hg)) 
       GlobalFree(hg); 

     } 
    } 
    __finally 
    { 
     CloseClipboard(); 
    } 
} 

Если посмотреть на исходный код для CopyToClipboard() метода VirtualTreeView, он использует совершенно иную реализацию, чем описанный выше. Он извлекает данные дерева в COM-объект IDataObject (TVTDataObject), представляющий форматы буфера обмена, перечисленные в свойстве ClipboardFormats VirtualTreeView, и любые дополнительные форматы, предоставляемые событием OnGetUserClipboardFormats VirtualTreeView. Это включает в себя текст, HTML, RTF и CSV. Затем он вызывает OleSetClipboard(), чтобы поместить этот COM-объект в буфер обмена. Если какое-либо приложение использует GetClipboardData() вместо OleGetClipboard(), Windows автоматически извлекает данные по мере необходимости. Так что, возможно, реализация версии TVTDataObject была нарушена в v6.2. Вы должны связаться с JAM Software (текущими поддерживателями VirtualTreeView) и сообщить об этом об ошибке.

+0

Привет, Реми, я пропустил трюк SetClipboardData. Однако вызов только VST-> ContentToRTF (TVSTTextSourceType :: tstAll); 'приводит к нарушению доступа. Я расскажу о проблеме CopyToClipboard для Jam Software. Спасибо за вашу помощь! –

+0

FYI вот отчет об ошибке и исправление, анонсированное в версии 6.2.1: [link] (https://github.com/Virtual-TreeView/Virtual-TreeView/issues/588) –

 Смежные вопросы

  • Нет связанных вопросов^_^