CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - Format HTML do schowka
Strona 1 z 1

Format HTML do schowka

Nowy postNapisane: środa, 9 maja 2018, 14:51
przez Mironas
Mam problem z wstawieniem tekstu sformatowanego w HTML (proste znaczniki typu <b>) do schowka Clipboard().

Treść (typu String) przygotowałem zgodnie z tym opisem oraz zarejestrowałem format:
KOD cpp:     UKRYJ  
UINT format = RegisterClipboardFormat(L"HTML Format");


Tak przygotowaną treść chcę wrzucić do schowka metodą SetAsHandle. Nie wiem jednak, jak przygotować drugi parametr dla metody:
KOD cpp:     UKRYJ  
  UINT uchwyt = ???;
  Clipboard()->SetAsHandle(format, uchwyt);
 


W mojej wersji C++Builder XE drugi parametr jest typu unsigned a wszystkie dostępne przykłady są albo dla Delphi (a tam jest THandle) albo dotyczą wstawiania do schowka obrazu - ale tam odpowiednia zmienna (tutaj 'DataHandle') przygotowana jest przez metodę SaveToClipboardFormat należącą do TBitmap:
KOD cpp:     UKRYJ  
Bitmap->SaveToClipboardFormat( MyFormat, DataHandle, APalette);

Re: Format HTML do schowka

Nowy postNapisane: czwartek, 10 maja 2018, 03:17
przez Cyfrowy Baron
W C++Builder jest inaczej niż w Delphi.

http://docs.embarcadero.com/products/ra ... andle.html

Re: Format HTML do schowka

Nowy postNapisane: poniedziałek, 14 maja 2018, 09:14
przez Mironas
Cyfrowy Baron napisał(a):W C++Builder jest inaczej niż w Delphi.

No właśnie.

Pytanie jak to zrobić w Builderze.
W podlinkowanym przykładzie DataHandle jest zdefiniowane w Bitmap->SaveToClipboardFormat(...). A np **TStringList** (w którym mam treść HTML) nie ma takiej metody.

Re: Format HTML do schowka

Nowy postNapisane: poniedziałek, 14 maja 2018, 11:10
przez polymorphism
Ten uchwyt to chyba powinien być uchwyt do pamięci przydzielonej funkcją GlobalAlloc (z flagą GMEM_MOVEABLE).

Re: Format HTML do schowka

Nowy postNapisane: sobota, 26 maja 2018, 12:22
przez Cyfrowy Baron
A czemu nie chcesz się posługiwać klasą TClipboard?

Re: Format HTML do schowka

Nowy postNapisane: poniedziałek, 28 maja 2018, 09:51
przez Mironas
Cyfrowy Baron napisał(a):A czemu nie chcesz się posługiwać klasą TClipboard?

Chcę, i to robię. Clipboard() przecież jest obiektem klasy TClipboard.

Re: Format HTML do schowka

Nowy postNapisane: wtorek, 29 maja 2018, 16:56
przez Cyfrowy Baron
Przecież w przykładzie do którego cię odesłałem masz wyraźnie podane użycie SetAsHandle w C++. Kolejność jest tam taka:

KOD cpp:     UKRYJ  
unsigned short MyFormat;

Bitmap->SaveToClipboardFormat(
      MyFormat,
      DataHandle,
      APalette);

Clipboard()->SetAsHandle(MyFormat, DataHandle);
 
Jak widzisz to Bitmap zapisuje format w MyFormat, a potem SetAshandle używa tego formatu.

SetAsHandle zapisuje dane, reprezentowane przez określony uchwyt, do schowka przy użyciu określonego formatu. Parametr Format może określać dowolny z formatów wymienionych w metodzie HasFormat. A HasFormat w C++ nie zawiera wartości typu HTML. Dostępne są tylko:

CF_TEXT
CF_BITMAP
CF_METAFILEPICT
CF_PICTURE
CF_COMPONENT

Gdzieś natknąłem się jeszcze na CF_HTML, ale nie wiem czy to działa.

RegisterClipboradFormat stosuje się w Delphi, ale w C++ już nie. Masz w to pomocy do środowiska:

KOD cpp:     UKRYJ  
TClipboard *cb = Clipboard();
  if (cb->HasFormat(CF_BITMAP))
  {
        std::auto_ptr<Graphics::TBitmap> Bitmap(new Graphics::TBitmap());
        try
        {
          Bitmap->LoadFromClipboardFormat(CF_BITMAP, cb->GetAsHandle(CF_BITMAP), 0);
          Canvas->Draw(5, 5, Bitmap.get());
    }
        catch (...)
        {
          MessageBeep(0);
          ShowMessage("Error reading image from clipboard!");
        }
        cb->Clear();
  }


KOD delphi:     UKRYJ  
Bitmap : TBitmap;
  s : string;
  Icon: TIcon;
begin
 Bitmap := TBitMap.Create;
 try
   Image1.Picture.RegisterClipboardFormat(cf_BitMap,TIcon);
   Bitmap.LoadFromClipBoardFormat(
     cf_BitMap,ClipBoard.GetAsHandle(cf_Bitmap),0);
   Canvas.draw(0,0,Bitmap);
 finally
   Bitmap.free;
   Clipboard.Clear;


Mironas napisał(a):Mam problem z wstawieniem tekstu sformatowanego w HTML (proste znaczniki typu <b>) do schowka Clipboard().


Jak rozumiem kopiując tekst ze strony HTML chcesz skopiować również kod HTML, który się pod nim ukrywa? Używam schowka od zawsze, ale nigdy nie zauważyłem by w taki sposób działa. Gdy kopiuję tekst ze strony, to kopiuje się on do schowka bez formatowania. Skopiowanie z formatowaniem wymaga chyba jakiejś specjalnej funkcji w przeglądarce?

Nie bardzo rozumiem co chciałeś przez to powiedzieć, bo jawnie kod HTML można bez problemu skopiować do schowka, gdyż jest to zwykły tekst.

O co więc chodzi z tym kopiowaniem HTML do schowka, bo nie bardzo rozumiem?

Tutaj masz przykład w Visual C++ z użyciem formatu CF_HTML: https://support.microsoft.com/en-us/help/274308/how-to-add-html-code-to-the-clipboard-by-using-visual-c

Re: Format HTML do schowka

Nowy postNapisane: wtorek, 29 maja 2018, 18:49
przez polymorphism
Skopiowanie z formatowaniem wymaga chyba jakiejś specjalnej funkcji w przeglądarce?

Przeglądarka może kopiować w dwóch formatach - jako tekst niesformatowany i jako HTML. To często widać w forumowych edytorach WYSIWYG, że jak wklejasz jakiś tekst skopiowany ze strony, zachowuje formatowanie. Visual Studio Code też kopiuje w formacie HTML, co by kolorowanie składni zachować.

Re: Format HTML do schowka

Nowy postNapisane: środa, 30 maja 2018, 14:40
przez Mironas
Cyfrowy Baron napisał(a):Jak rozumiem kopiując tekst ze strony HTML chcesz skopiować również kod HTML, który się pod nim ukrywa?

Nie.
Chodzi o to, aby w programie skopiować do schowka tekst (1) niesformatowany, aby móc go wklejać np do notatnika, i jednocześnie (2) ten sam tekst ale sformatowany w HTML tak aby móc go wklejać np jako treść maila (w programie pocztowym) z zachowanych formatowaniem.
Czyli aby programowo zapakować do schowka tekst w takich samych formatach, jakbym je skopiował ze strony www.

Finalne rozwiązanie wygląda następująco:
KOD cpp:     UKRYJ  
//---------------------------------------------------------------------------
//                          HTML >> Clipboard()
//---------------------------------------------------------------------------
// HTML >> Clipboard()
void __fastcall TForm1::ToolButton2Click(TObject *Sender)
{
  // Wstawia tekst do schowka jako zwykły tekst (CF_TEXT) i jako formatowany HTML
  String teksthtml = "Ala <b>ma</b> kota!";
  String tekstnorm = "Ala ma kota!";
  HtmlDoSchowka(teksthtml, tekstnorm);
}
//---------------------------------------------------------------------------
// Wstaw tekst HTML do schowka 'Clipboard()'
void TForm1::HtmlDoSchowka(String teksthtml, String tekstnorm)
{
  Clipboard()->Clear();
  Clipboard()->Open();

  // HTML Format
  String treschtml = FormatSchowkaHTML(teksthtml);
  UINT format = RegisterClipboardFormat(L"HTML Format");
  WstawDoSchowkaWgFormatu(treschtml, format);

  // CF_TEXT
  WstawDoSchowkaWgFormatu(tekstnorm, CF_TEXT);

  Clipboard()->Close();
}
//---------------------------------------------------------------------------
// Wstawia tekst do schowka w podanym formacie
void TForm1::WstawDoSchowkaWgFormatu(String tekst, UINT format)
{
  int len = tekst.Length();
  HGLOBAL hTekst = GlobalAlloc(GMEM_MOVEABLE, len+4);
  char* ptr = (char*)GlobalLock(hTekst);
  char* buf = ((AnsiString)tekst).c_str();
  strcpy(ptr, buf);
  Clipboard()->SetAsHandle(format, (UINT)hTekst);
  GlobalUnlock(hTekst);
}
//---------------------------------------------------------------------------
// Zwraca pełny format (nagłówek + tekst) dla schowka 'HTML Format'
String TForm1::FormatSchowkaHTML(String teksthtml)
{
  TStrings* treschtml = new TStringList();

  treschtml->Add("Version:0.9");
  treschtml->Add("StartHTML:AAAAAAAAAA");        // h1
  treschtml->Add("EndHTML:BBBBBBBBBB");          // h2
  treschtml->Add("StartFragment:CCCCCCCCCC");    // f1
  treschtml->Add("EndFragment:DDDDDDDDDD");      // f2
  int h1 = treschtml->Text.Length();
  treschtml->Add("<HTML>");
  treschtml->Add("<BODY>");
  int f1 = treschtml->Text.Length();
  treschtml->Add("<!--StartFragment-->");
  treschtml->Add(teksthtml);
  treschtml->Add("<!--EndFragment-->");
  int f2 = treschtml->Text.Length()-2;
  treschtml->Add("</BODY>");
  treschtml->Add("</HTML>");
  int h2 = treschtml->Text.Length()-2;

  String tresc = treschtml->Text;
  tresc = StringReplace(tresc, "AAAAAAAAAA", SF("%.10d",h1), RF);
  tresc = StringReplace(tresc, "BBBBBBBBBB", SF("%.10d",h2), RF);
  tresc = StringReplace(tresc, "CCCCCCCCCC", SF("%.10d",f1), RF);
  tresc = StringReplace(tresc, "DDDDDDDDDD", SF("%.10d",f2), RF);

  delete treschtml;
  return tresc;
}
//---------------------------------------------------------------------------
 


Funkcja SF() zwraca sformatowany tekst i można ją zastąpić jakimś printf-em. Ja używam w takiej formie bo jest mi tak wygodniej.
Jak by ktoś interesowało, to wygląda tak:
KOD cpp:     UKRYJ  
// Zwraca tekst sformatowany
String TForm1::SF(String format, ...)
{
  String tekst;

  va_list list;
  va_start(list, format);               // zainicjuj liste
  tekst.vprintf(format.w_str(), list);  // formatuj tekst
  va_end(list);                         // zwolnij liste

  return tekst;
}
 


EDIT:
Tylko z kodowaniem jeszcze jest jakiś problem, bo jak w tekście są polskie znaki to po wklejeniu do maila mam krzaki. :zawiedziony:

Re: Format HTML do schowka

Nowy postNapisane: poniedziałek, 4 czerwca 2018, 22:24
przez Cyfrowy Baron
Kod HTML kopiuje się tak samo jak zwykły tekst, bo to jest zwykły tekst. Krzaczki występują bo jest problem z kodowaniem. Kiedyś na tym forum był już poruszany temat ustawiania strony kodowej dla tekstu.

Re: Format HTML do schowka

Nowy postNapisane: wtorek, 5 czerwca 2018, 11:04
przez Mironas
Problem z kodowaniem - wystarczy tam gdzie znajduje się tekst HTML zamiast String (UnicodeString) stosować UTF8String.

Przerobiony przykład:
KOD cpp:     UKRYJ  
//---------------------------------------------------------------------------
//                          HTML >> Clipboard()
//---------------------------------------------------------------------------
// HTML >> Clipboard()
void __fastcall TForm1::ToolButton2Click(TObject *Sender)
{
  // Wstawia tekst do schowka jako zwykły tekst (CF_TEXT) i jako formatowany HTML
  String teksthtml = "Zażółć <b>gęślą</b> jaźń\r\nZAŻÓŁĆ <b>GĘŚLĄ</b> JAŹŃ";
  String tekstnorm = "Zażółć gęślą jaźń\r\nZAŻÓŁĆ GĘŚLĄ JAŹŃ";
  HtmlDoSchowka(teksthtml, tekstnorm);
}
//---------------------------------------------------------------------------
// Wstaw tekst HTML do schowka 'Clipboard()'
void TForm1::HtmlDoSchowka(UTF8String teksthtml, String tekstnorm)
{
  Clipboard()->Clear();
  Clipboard()->Open();

  // HTML Format
  UTF8String treschtml = FormatSchowkaHTML(teksthtml);
  UINT format = RegisterClipboardFormat(L"HTML Format");

  int len1 = treschtml.Length();
  HGLOBAL hHtml = GlobalAlloc(GMEM_MOVEABLE, len1+4);
  char* ptr1 = (char*)GlobalLock(hHtml);
  char* buf1 = treschtml.c_str();
  strcpy(ptr1, buf1);
  Clipboard()->SetAsHandle(format, (UINT)hHtml);
  GlobalUnlock(hHtml);

  // CF_TEXT
  int len2 = tekstnorm.Length();
  HGLOBAL hTekst = GlobalAlloc(GMEM_MOVEABLE, len2+4);
  char* ptr2 = (char*)GlobalLock(hTekst);
  char* buf2 = ((AnsiString)tekstnorm).c_str();
  strcpy(ptr2, buf2);
  Clipboard()->SetAsHandle(CF_TEXT, (UINT)hTekst);
  GlobalUnlock(hTekst);

  Clipboard()->Close();
}
//---------------------------------------------------------------------------
// Zwraca pełny format (nagłówek + tekst) dla schowka 'HTML Format'
UTF8String TForm1::FormatSchowkaHTML(String teksthtml)
{
  teksthtml = StringReplace(teksthtml, "\r\n", "<br>", RF1);

  TStrings* treschtml = new TStringList();

  treschtml->Add("Version:0.9");
  treschtml->Add("StartHTML:AAAAAAAAAA");        // h1
  treschtml->Add("EndHTML:BBBBBBBBBB");          // h2
  treschtml->Add("StartFragment:CCCCCCCCCC");    // f1
  treschtml->Add("EndFragment:DDDDDDDDDD");      // f2
  int h1 = treschtml->Text.Length();
  treschtml->Add("<HTML>");
  treschtml->Add("<BODY>");
  int f1 = treschtml->Text.Length();
  treschtml->Add("<!--StartFragment-->");
  treschtml->Add(teksthtml);
  treschtml->Add("<!--EndFragment-->");
  int f2 = treschtml->Text.Length()-2;
  treschtml->Add("</BODY>");
  treschtml->Add("</HTML>");
  int h2 = treschtml->Text.Length()-2;

  UTF8String tresc = treschtml->Text;
  tresc = StringReplace(tresc, "AAAAAAAAAA", SF("%.10d",h1), RF1);
  tresc = StringReplace(tresc, "BBBBBBBBBB", SF("%.10d",h2), RF1);
  tresc = StringReplace(tresc, "CCCCCCCCCC", SF("%.10d",f1), RF1);
  tresc = StringReplace(tresc, "DDDDDDDDDD", SF("%.10d",f2), RF1);

  delete treschtml;
  return tresc;
}
//---------------------------------------------------------------------------