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

Format HTML do schowka

dział ogólny

Format HTML do schowka

Nowy postprzez Mironas » środa, 9 maja 2018, 14:51

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);
Avatar użytkownika
Mironas
Programista I
Programista I
 
Posty: 427
Dołączył(a): poniedziałek, 2 stycznia 2012, 19:02
Podziękował : 17
Otrzymał podziękowań: 61
System operacyjny: Windows XP
Kompilator: C++Builder XE
Gadu Gadu: 4289125
    WindowsChrome

Re: Format HTML do schowka

Nowy postprzez Cyfrowy Baron » czwartek, 10 maja 2018, 03:17

W C++Builder jest inaczej niż w Delphi.

http://docs.embarcadero.com/products/ra ... andle.html
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4721
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 443
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows 7Firefox

Re: Format HTML do schowka

Nowy postprzez Mironas » poniedziałek, 14 maja 2018, 09:14

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.
Avatar użytkownika
Mironas
Programista I
Programista I
 
Posty: 427
Dołączył(a): poniedziałek, 2 stycznia 2012, 19:02
Podziękował : 17
Otrzymał podziękowań: 61
System operacyjny: Windows XP
Kompilator: C++Builder XE
Gadu Gadu: 4289125
    WindowsChrome

Re: Format HTML do schowka

Nowy postprzez polymorphism » poniedziałek, 14 maja 2018, 11:10

Ten uchwyt to chyba powinien być uchwyt do pamięci przydzielonej funkcją GlobalAlloc (z flagą GMEM_MOVEABLE).
C++ Reference - opis wszystkich klas STL-a i funkcji C.

Za ten post autor polymorphism otrzymał podziękowanie od:
Mironas
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2165
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 7 Pro
Windows 8.1
Linux Mint 19
Kompilator: Visual Studio 2015 Community
CodeLite (MinGW)
MSYS2 (MinGW, clang)
g++
Gadu Gadu: 0
    Windows 7Firefox

Re: Format HTML do schowka

Nowy postprzez Cyfrowy Baron » sobota, 26 maja 2018, 12:22

A czemu nie chcesz się posługiwać klasą TClipboard?
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4721
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 443
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows 7Firefox

Re: Format HTML do schowka

Nowy postprzez Mironas » poniedziałek, 28 maja 2018, 09:51

Cyfrowy Baron napisał(a):A czemu nie chcesz się posługiwać klasą TClipboard?

Chcę, i to robię. Clipboard() przecież jest obiektem klasy TClipboard.
Avatar użytkownika
Mironas
Programista I
Programista I
 
Posty: 427
Dołączył(a): poniedziałek, 2 stycznia 2012, 19:02
Podziękował : 17
Otrzymał podziękowań: 61
System operacyjny: Windows XP
Kompilator: C++Builder XE
Gadu Gadu: 4289125
    WindowsChrome

Re: Format HTML do schowka

Nowy postprzez Cyfrowy Baron » wtorek, 29 maja 2018, 16:56

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
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4721
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 443
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows 7Firefox

Re: Format HTML do schowka

Nowy postprzez polymorphism » wtorek, 29 maja 2018, 18:49

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ć.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2165
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 7 Pro
Windows 8.1
Linux Mint 19
Kompilator: Visual Studio 2015 Community
CodeLite (MinGW)
MSYS2 (MinGW, clang)
g++
Gadu Gadu: 0
    Windows 7Firefox

Re: Format HTML do schowka

Nowy postprzez Mironas » środa, 30 maja 2018, 14:40

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:
Avatar użytkownika
Mironas
Programista I
Programista I
 
Posty: 427
Dołączył(a): poniedziałek, 2 stycznia 2012, 19:02
Podziękował : 17
Otrzymał podziękowań: 61
System operacyjny: Windows XP
Kompilator: C++Builder XE
Gadu Gadu: 4289125
    WindowsChrome

Re: Format HTML do schowka

Nowy postprzez Cyfrowy Baron » poniedziałek, 4 czerwca 2018, 22:24

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.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4721
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 443
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows 7Firefox

Re: Format HTML do schowka

Nowy postprzez Mironas » wtorek, 5 czerwca 2018, 11:04

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;
}
//---------------------------------------------------------------------------
 
Avatar użytkownika
Mironas
Programista I
Programista I
 
Posty: 427
Dołączył(a): poniedziałek, 2 stycznia 2012, 19:02
Podziękował : 17
Otrzymał podziękowań: 61
System operacyjny: Windows XP
Kompilator: C++Builder XE
Gadu Gadu: 4289125
    WindowsChrome


  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

Powrót do Ogólne problemy z programowaniem

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 1 gość

cron