A Windows vágólap (clipboard) adatok átvitelét teszi lehetővé egyik programból a másikba. Az átvitel nagyon egyszerű, mivel csak néhány utasítást lehet használni a programban a vágólap kezelésére. Két utasítást (Cut,Copy), amely adatot helyez a vágólapra, és egyet (Paste), amely ezt leemeli onnan. A vágólapon lévő adat technikailag minden programtól független, a rendszer által birtokolt memóriablokkok halmaza, kezelése az API függvények segítségével történik.

A vágólap magyar elnevezés nem általános, lehet még vágóasztal, illetve átmeneti tároló fordításokkal is találkozni. Én igyekszem a vágólap elnevezéshez tartani magam.

A gyakorlatban a vágólapot kezelő parancsok minden programban az Edit menüben találhatóak. A Cut (CTRL+X/ SHIFT+DEL)illetve Copy (CTRL+C/CTRL+INS) parancsra a program a kiválasztott adatot a vágólapra másolja, miután törölte annak tartalmát. A vágólapon lévő adat csak meghatározott formátumú lehet (szöveg, bittérkép, metafile, stb... és persze saját formátumot is tudunk létrehozni). Mikor a felhasználó a Paste (CTRL+V/SHIFT+INS) parancsot kiadja (ugyanazon, vagy bármely más programból) a vágólapon lévő adat kimásolódik, de annak tartalma nem változik. A program csak akkor használja fel a vágólap tartalmát, ha ismeri az ott lévő adat formátumát.

Az iméntiek mindenkinek nyilvánvalóak, de azért gondolkodjunk el rajta. Levonhatjuk például azt a hasznos tanulságot, hogy mikor kifogyunk a memóriából a legelső dolog amit megtehetünk, hogy töröljük a vágólap tartalmát úgy, hogy valami nagyon kicsit (egy karaktert) rakunk bele. (ha egy 800X600-as színes kép maradt a vágólapon, az 1.37 Mb memória!)

A szabványos vágólap-formátumok:

Az azonosítók a windows.h -ban vannak definiálva. Vannak olyan formátumok, amik használata általános (ASCII, bitmap), és persze vannak olyanok is ahol a tárolt adatok értelmezése a programra van bízva. Ilyenkor előfordul, hogy hibásan értelmezi az adatot (pl. kép minden byte-ját egy szöveges karakterként teszi be).

Nem írom le az összeset, csak a gyakran használatosakat:
 

CF_BITMAP Windows kompatibilis bittérkép. A bittérkép leírót kezeljük.
CF_DIB Használata hasonló a bittérképhez, a leíró eszköz-független bittérképre vonatkozik.
CF_DIF A leíró globális memóriablokkra vonatkozik, ami ASCII formátumú adatot tárol, minden sort CR LF (kocsivissza, soremelés 10,13) zár le. A string végét NULL jelzi.
CF_OEMTEXT OEM karaktereket tartalmazó string. Kocsivissza, és soremelés is lehet benne.
CF_PALETTE Paletta. A paletta leírója van a vágólapnál.
CF_TEXT Egy globális memóriablokkban elhelyezett ANSI karaktereket tartalmazó string. minden sort CR LF (kocsivissza, soremelés 10,13) zár le. A string végét NULL jelzi.
CF_WAVE Az adatok hangokat írnak le.

Szöveges adatok írása a vágólapra.

A Cut illetve Copy parancsok üzenetkezelőit kell átírnunk, mert ezen parancsok hatására kerülhet adat a vágólapra. Először azt kell megoldanunk, hogy ezeknek a parancsoknak a menüpontjai csak akkor éljenek, ha van valami kiválasztva. A ClassWizard-ból rendeljünk kezelőfüggvényeket a menüpontok UPDATE_COMMAND_UI üzeneteihez. (A példában feltételezzük, hogy a m_bSelection változó akkor igaz, ha van kijelölés):

void CMyView::OnUpdateEditCut(CCmdUI* pCmdUI)
{
  pCmdUI->Enable(m_bSelection);
}

void CMyView::OnUpdateEditCopy(CCmdUI* pCmdUI)
{
  pCmdUI->Enable(m_bSelection);
}

Ez eddig egyszerű. Vegyük sorra, milyen műveleteket kell elvégeznünk ASCII adatnak a vágólapra másolása során:

  • Memória lefoglalása, amelybe belefér a másolandó szöveg. Ehhez a ::GlobalAlloc API függvényt használhatjuk.

  • HGLOBAL GlobalAlloc(
UINT uFlags,
// memóriablokk tulajdonságai
DWORD dwBytes 
// blokk mérete byte-okban
);  
A visszatérési érték a lefoglalt memóriaterület azonosítója (handle). Az első paraméterként átadott tulajdonság vágólap esetében GMEM_MOVEABLE | GMEM_DDESHARE |GMEM_ZEROINIT legyen.
  • Zároljuk a memóriablokkot a :: GlobalLock API függvénnyel.
LPVOID GlobalLock( HGLOBAL hMem);
Az átadott paraméter a ::GlobalAlloc függvény által visszaadott leíró (handler). Ha a zárolás sikeres volt, akkor a visszaadott mutató a memóriablokk első byte-jára mutat. Ha sikertelen, akkor NULL.
A zárolásra azért van szükség, mert ekkor biztos, hogy csak mi használjuk a memóriát, és nem lesz elmozgatva (ki swappel-ve), azonkívül így kapjuk meg a rá mutató pointert.
  • Az adatot a memóriaterületre másoljuk. Az imént megkapott pointer ismeretében egyszerű. Szöveg esetében egy ::lstrcpy függvény is megteszi.
  • Feloldjuk a memóriaterület zárolását a ::GlobalUnLock API függvénnyel.
BOOL GlobalUnlock(HGLOBAL hMem);
Az átadott paraméter az eddig is használt leíró (handler), a visszatérési érték akkor igaz, ha az eljárás sikeres volt. A feloldás után többet nem hivatkozhatunk a memóriaterületre az előbb használt pointerrel.
  • Megnyitjuk a vágólapot a Cwnd::OpenClipboard MFC függvénnyel. Amíg le nem zárjuk, addig más alkalmazás már nem férhet hozzá!
BOOL Cwnd::OpenClipboard( );
A visszatérési érték igaz, ha sikeres volt a megnyitás.
  • Töröljük a vágólap tartalmát az ::EmptyClipboard API függvénnyel. Ezzel a vágólap egyedüli birtokosává váltunk. A függvény felszabadít minden olyan memóriablokkot, amely kapcsolódott a vágólaphoz. A függvény meghívása előtt meg kell nyitnunk a vágólapot.
BOOL EmptyClipboard(void);
A visszatérési érték akkor igaz, ha az ürítés sikeres volt.
  • A vágólap tartalmát a mi adatunkra állítjuk a ::SetClipboardData API függvénnyel. Paraméterként megadjuk a memóriaterület azonosítóját (handler), és az adat formátumát.
HANDLE SetClipboardData(UINT uFormat, HANDLE hData);
A visszakapott leíró (handle) a felírt adat azonosítója. Azért van rá szükség, mert az átadott azonosítót többet nem használhatjuk, mivel már nem a miénk a memóriablokk.
  • Lezárjuk a vágólapot a ::CloseClipboard API függvénnyel.
BOOL CloseClipboard(void);
A visszatérési értéke igaz, ha sikerült lezárni. Bármely más program csak ezután éri el a vágólapot, ezért fontos, hogy ne felejtsük el lezárni.
Ennek a működése:

Lefoglalunk a Windows-tól egy memóriablokkot, visszakapjuk a leíróját (handler), zároljuk a memóriát, rámásoljuk az adatot, majd feloldjuk. A vágólap megnyitása és törlése után meghívjuk a ::SetClipboardData API függvényt a memóriablokk leírójával. A memóriablokk eddig úgy volt regisztrálva, hogy a mi programunkhoz tartozik. Ilyen esetekben a Windows törli a memóriablokkot, ha a program futása véget ér. Esetünkben a Windows átveszi magának a memóriablokkot, a ::GlobalReAlloc API függvénnyel. Ezek után a memóriaterület már nem létrehozó programé, így nem is hivatkozhat rá!

A felsorolt lépések szöveges adatok átvitelét végzik, egy bittérkép annyiban különbözik, hogy ott egy bittérkép leíróját kell átadni a ::SetClipboardData API függvénynek. Így az első 4 lépés máshogy alakul.

Példa szöveg felmásolására a vágólapra. A Copy menüpont COMMAND üzenetéhez rendelt kezelőfüggvény:

void CClipboardView::OnEditCopy()
{
 HANDLE HText; //leiro a globalis memoriablokkhoz
 char *pText;  //mutato a memoriblokkra
 char *pBuf;  //a kivalsztott szoveg atmeneti tarolasara
 
 //A dokumentum
 CClipboardDoc* pDoc = GetDocument();
 ASSERT_VALID(pDoc);

 //a kivalasztott szoveg
 pBuf=new char[pDoc->SelectedSize()+1];
 pDoc->GetSelectedText(pBuf);

 //Globalis memoriablokk
 HText=::GlobalAlloc(
  GMEM_MOVEABLE | GMEM_DDESHARE |GMEM_ZEROINIT,
  strlen(pBuf)+1);
 //memoriablokkra mutato pointer
 pText=(char *)::GlobalLock(HText);
 
 //szoveg atmasolasa a globalis memoriablokkra
 ::lstrcpy(pText,pBuf);

 //feloldas
 ::GlobalUnlock(HText);

 if (!OpenClipboard()) //vagolap megnyitasa CWnd::OpenClipboard
 {   //csak akor sikerul, ha mas eppen nem hasznalja.
  GlobalFree(HText);
  AfxMessageBox("A vagolapot nem sikerult megnyitni");
  delete [] pBuf;
  return;
 }

 //clipboard torlese, tulajdonosai leszunk
 ::EmptyClipboard();
 //leiro atadasa a clipboardnak
 ::SetClipboardData(CF_TEXT, HText);
 //vagolap lezarasa
 ::CloseClipboard();

 delete [] pBuf;
}

Szöveges adatok olvasása, beillesztése a vágólapról.

Az adatok olvasása kicsit bonyolultabb, mint az írás. Először azt kell megtudni, hogy van -e a vágólapon általunk ismert formátumú adat. Ezt a ::IsClipboardFormatAvailable API függvény tudja megmondani.

BOOL IsClipboardFormatAvailable(UINT format);
Paraméterként csak a keresett formátumot kell megadni, a visszatérési érték akkor igaz, ha van keresett formátumú adat a vágólapon. Használata előtt nem kell megnyitnunk a vágólapot.

Ezt a függvényt használhatjuk arra, hogy ha nem ismert formátum van a vágólapon, akkor a Paste menü le legyen tiltva. Rendeljünk kezelőfüggvényt a Paste menü UPDATE_COMMAND_UI üzenetéhez.

void CMyView::OnUpdateEditPaste(CCmdUI* pCmdUI)
{
  pCmdUI->Enable(::IsClipboardFormatAvailable(CF_TEXT));
}

A fenti kódrészlet akkor engedi élni a Paste menüpontot, ha a vágólapon létezik szöveges formátumú adat.

Eddig még nem említettem, de a vágólapon egyszerre több formátumban is fent lehet ugyanaz az adat, azonos formátumban több adat viszont nem. Hogy pontosan hány féle formátum van a vágólapon, azt a ::CountClipboardFormats API függvény segítségével tudjuk lekérdezni.

int CountClipboardFormats(void);
A függvény visszatérési értéke a formátumok száma.

Az adatok formátumát a ::EnumCliboardFormats API függvény adja vissza. Meghívása előtt meg kell nyitni a vágólapot a ::OpenClipboard API függvénnyel.

UINT EnumCliboardFormats(UINT format);
Ha NULL-t adunk meg paraméterként, akkor a függvény az első formátumot adja vissza. Ha a vágólapon megtalálható formátumot adunk meg, akkor a következő formátumot kapjuk visszatérési értékként. Ha már nincs többféle formátum, akkor NULL-al tér vissza.

A vágólapon lévő formátumokból egy listát is kaphatunk a ::GetPriorityClipboardFormat API függvénytől, és ebben keresgélhetünk kedvünkre való formátumot. Használata előtt meg kell nyitni a vágólapot a ::OpenClipboard API függvénnyel.

int GetPriorityClipboardFormat(UINT *PriorityList, int cEntries);
Az első paraméter a tömb címe, ahová a listát várjuk, a második pedig a lista elemeinek száma. A lista végét egy NULL elem jelzi (ha belefért a tömbbe). A tömb méretének meghatározásához használhatjuk a ::CountClipboardFormats API függvény-t. A tömb mérete egyel nagyobb kell hogy legyen, így elfér a lezáró NULL is.

Az adatot definiáló leírót (handler) a ::GetClipboardData API függvény adja vissza. Szöveges adat esetén a leíró egy globális memóriablokkra vonatkozik, kép esetén pedig egy bittérképre. Használata előtt meg kell nyitni a vágólapot a ::OpenClipboard API függvénnyel.

HANDLE GetClipboardData(UINT format);
Paraméterként csak a formátumot kell megadnunk. Ezt a formátumot a fenti függvények bármelyikével meghatározhatjuk. Ha még sem talál megadott formátumot, akkor NULL-t ad vissza.

Mivel a visszaadott leírót nem a miénk, csak addig használhatjuk, míg le nem zártuk a vágólapot. Ha későbbre is meg akarjuk őrizni, akkor a memóriablokk tartalmáról másolatot kell készítenünk.

Tehát szövegnek a vágólapról való beolvasásához végezendő lépések.

  • Megnyitjuk a vágólapot a ::OpenClipboard API függvénnyel.
  • A ::GetClipboardData API függvénnyel lekérdezzük a memóriablokk leíróját.
  • Lekérdezzük a memóriára mutató pointert a memóriablokk zárolásával. ::GlobalLock
  • Kimásoljuk az adatot magunknak, szöveg esetében a ::lstrcpy API függvénnyel. A másolás előtt szükség lehet az adat hosszának a lekérdezésére. Ezt a ::GlobalSize API függvény végzi el.
DWORD GlobalSize(HGLOBAL hMem);
Paraméterként a memóriablokk leíróját (handle) kell megadni. Visszatérési érték a blokk mérete.
  • Feloldjuk a memóriaterület zárolását a ::GlobalUnLock API függvénnyel.
  • Bezárjuk a vágólapot a ::CloseClipboard API függvénnyel.
void CClipboardView::OnEditPaste()
{
 HANDLE HPaste;  //leiro a globalis memoriblokkhoz
 char *pBuf;  //atmeneti buffer, a szovegnek
 char *pText;  //pointer a globalis memoriblokkon levo szovegre
 
 CClipboardDoc* pDoc = GetDocument();
 ASSERT_VALID(pDoc);

 if (OpenClipboard()) //vagolap megnyitasa
 {   //csak akor sikerul, ha mas eppen nem hasznalja.
  HPaste=::GetClipboardData(CF_TEXT);//memoriablokk leirojat kapjuk
  if (HPaste==NULL)   //NULL, ha nincs olyan formatum
  {
   ::CloseClipboard(); //be kel zarni, mert mar megnyitottuk!!
   AfxMessageBox("Nincs szoveg formatum a vagolapon !");
   return;
  }
 
  //buffer, ahova bemasoljuk a beszurando adatot:
  pBuf=new char[::GlobalSize(HPaste)];
  //az adatra mutato pointer:
  pText=(char *)::GlobalLock(HPaste);

  //szoveg atmasolasa:
  ::lstrcpy(pBuf, pText);
  //feloldas:
  ::GlobalUnlock(HPaste);
  //vagolap lezarasa:
  ::CloseClipboard();

  //szoveg beszurasa
  pDoc->InsertText(pBuf);

  //buffer legyilkolasa
  delete [] pBuf;

  Invalidate();
 }
}

Kép másolása a vágólapra.

A Cut és Copymenüpontokat csak akkor kell engedélyeznünk, ha van másolásra kijelölt kép. Ezt a menüpontok UPDATE_COMMAND_UI üzeneteihez rendelt kezelőfüggvényekben oldhatjuk meg.

void CMyView::OnUpdateEditCopy(CCmdUI* pCmdUI)
{
  pCmdUI->Enable(m_bSelection);
}

Bittérkép vágólapra másolása annyiban különbözik a szöveg kezelésétől, hogy egy globális memóriablokk leírója helyett itt egy bittérkép leíróját kell átadnunk. Tehát a lépések a Copy illetve Cut menüpontok COMMAND üzenetének kezelőfüggvényében:

  • Egy bittérkép létrehozása. MFC-ben a CBitmap osztály CreateCompaitbleBitmap tagfüggvényével.
BOOL CBitmap::CreateCompatibleBitmap( CDC* pDC, int nWidth, int nHeight );
Az első paraméter egy mutató egy eszköz-környezet objektumra (Device Context). Ezzel kompatibilis lesz a létrehozott bittérkép. A második és harmadik paraméter a létrehozandó bittérkép méretét (szélesség, magasság) határozzák meg.
  • Egy eszköz-környezet objektum létrehozása. Ennek segítségével tudunk majd műveleteket végezni a képen, ha majd hozzárendeltük. Pl. rámásolni a másolásra kijelölt bittérképet. A létrehozást a CDC osztály CreateCompatibleDC tagfüggvénye végzi.
virtual BOOL CDC::CreateCompatibleDC( CDC* pDC );
Az egyetlen paraméter egy másik eszköz-környezet objektum címe, amellyel a létrehozott kompatíbilis lesz. Itt ugyanannak az objektumnak a címét kell megadni, amit a bittérkép létrehozásakor, mert ekkor lesz kompatíbilis a bittérkép az új eszköz-környezettel.
  • A bittérkép hozzárendelése az imént létrehozott eszköz-környezethez. A CDC osztály SelectObject tagfüggvényével. A függvénynek többféle definíciója van, esetünkben erre lesz szükség:
CBitmap* CDC::SelectObject( CBitmap* pBitmap );
Paraméterként az első lépésben létrehozott bittérkép objektumot kell átadnunk. Így hozzárendeltük az eszköz-környezethez. A visszatérési érték az eddig hozzárendelt bittérkép. Nem lesz rá szükségünk.
  • Átmásoljuk a másolásra kijelölt bittérképet a létrehozott bittérképre. Ezt a bittérképhez rendelt eszköz-környezet objektum BitBlt tagfüggvényével tudjuk elvégezni.
BOOL BitBlt( int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, DWORD dwRop );
Az első és második paraméter a bittérképre másolt kép bal felső sarkának koordinátáit határozzák meg, a harmadik és negyedik a kép méreteit, az ötödik az eszköz-környezet, amelyen a kép található, a hatodik és hetedik a kép bal felső sarka az eszköz-környezeten, az utolsó a másolás módját határozza meg (most legyen SRCCOPY).
  • Megnyitjuk a vágólapot a CWnd::OpenClipboard függvénnyel.
  • Ürítjük a vágólapot a ::EmptyClipboard API függvénnyel, ezzel egyedüli tulajdonosai lettünk.
  • Megadjuk a vágólapnak a bittérkép leíróját, és az adat formátumát (most CF_BITMAP) a ::SetClipboardData API függvénnyel. A bittérkép leíróját a bittérkép objektum m_Object adattagjában találjuk.
  • Meghívjuk a bittérkép objektum Detach() tagfüggvényét. Ezzel elérjük, hogy nem törlődik a bittérkép, amint a program az objektumot tartalmazó blokkból kilép (mert ugye normális esetben ez történne).
  • Lezárjuk a vágólapot a ::CloseClipboard API függvénnyel.
A következő példa az egész client area-t kirakja a vágólapra.
void CClipboardView::OnEditCopy()
{
 CClientDC ClientDC(this); //eszkoz kornyezet a client area-ra
 CBitmap Bitmap;  //bitterkep objektum
 BITMAP BitmapInfo;  //bitterkep informaciok
 CDC MemDC;   //Memoria eszkoz kornyezet
 CRect Rect;

 //client-area merete
 GetClientRect(&Rect);
 //bitterkep letrehozasa, amire rafer az egesz client area
 Bitmap.CreateCompatibleBitmap(&ClientDC, Rect.Width(), Rect.Height());

 //eszkoz-kornyezet letrehozasa
 MemDC.CreateCompatibleBitmap(&ClientDC);
 //eszkoz-kornyezet hozzarendelese a bitmap-hez
 MemDC.SelectObject(&Bitmap);

  MemDC.BitBlt(0, 0,
   Rect.Width(),
   Rect.Height(),
   &ClientDC,
   0, 0, SRCCOPY);

 if (OpenClipboard()) //vagolap megnyitasa
 {   //csak akor sikerul, ha mas eppen nem hasznalja.
 
//vagolap torlese
::EmptyClipboard();
 //leiro atadasa a vagolapnak
::SetClipboardData(CF_BITMAP, Bitmap.m_hObject);
  //hogy ne semmisuljon meg a kep
  Bitmap.Detach();
  //vagolap lezarasa
  ::CloseClipboard();
 }
}
Kép beillesztése a vágólapról.

A beillesztés Paste menüponttal történik. A menüpontot csak akkor szabad engedélyezni, ha a vágólapon van bittérkép formátumú adat. A Paste menü UPDATE_COMMAND_UI üzenetéhez rendelt kezelőfüggvény:

void CMyView::OnUpdateEditPaste(CCmdUI* pCmdUI)
{
  pCmdUI->Enable(::IsClipboardFormatAvailable(CF_BITMAP));
}

A beillesztés a menüpontok COMMAND üzeneteinek kezelőfüggvényében történik. A lépések:

  • A vágólap megnyitása az ::OpenClipboard API függvénnyel.
  • A bittérkép leírójának lekérdezése a ::GetClipboardData API függvénynél. A függvényt CF_BITMAP paraméterrel hívjuk.
  • A leíróhoz hozzá tudunk rendelni egy CBitmap objektumot. CGDIObject (innen van származtatva a CBitmap) osztály Attach tagfüggvényének segítségével.
BOOL Attach( HGDIOBJ hObject );
A függvény egyetlen paramétere a leíró.
  • Létre kell hozni, és a CBitmap objektumhoz hozzá kell rendelni egy eszköz-környezetet. A CDC osztály CreateCompatibleDC, és SelectObject tagfüggvényeivel. A képet ne próbáljuk meg módosítani, hiszen nem a miénk, csak a leíróját kaptuk meg.
  • Kimásoljuk a képet egy másik eszközkörnyezetre a CDC osztály BitBlt tagfüggvényével.
  • Megszüntetjük az összerendelést a CBitmap objektum és a vágólapon lévő leíró között. Az objektum Detach tagfüggvényével. Ha nem tennénk, a kezelőfüggvényből való kilépéskor az objektum törlésekor a kép is törlődni akarna, pedig a képet nem írhatjuk, hiszen nem a miénk.
  • Lezárjuk a vágólapot a ::CloseClipboard API függvénnyel.
void CClipboardView::OnEditPaste()
{
 CClientDC ClientDC(this); //eszkoz kornyezet a client area-ra
 CBitmap Bitmap;  //bitterkep objektum
 BITMAP BitmapInfo;  //bitterkep informaciok
 HANDLE HBitmap;  //bitterkep azonositoja
 CDC MemDC;   //Memoria eszkoz kornyezet

 if (OpenClipboard()) //vagolap megnyitasa
 {   //csak akor sikerul, ha mas eppen nem hasznalja.
  HBitmap= ::GetClipboardData(CF_BITMAP); //bitterkep leirojat megkapjuk
  if (HBitmap==NULL) //ha nincs bitterkep a vagolapon
  {
   ::CloseClipboard();
   return;
  }
 
  //objektum hozzarendelese a leirohoz
  Bitmap.Attach(HBitmap);
  //kep informacioi
  Bitmap.GetObject(sizeof(BITMAP),&BitmapInfo);
  //eszkoz kornyezet letrehozasa
  MemDC.CreateCompatibleDC(&ClientDC);
 //hozzarendelese a bitterkephez
  MemDC.SelectObject(&Bitmap);
 
  //kimasolas a kepernyore
  ClientDC.BitBlt(0, 0,
   BitmapInfo.bmWidth,
   BitmapInfo.bmHeight,
   &MemDC,
   0, 0, SRCCOPY);
 
  //hozzarendeles megszuntetese
  Bitmap.Detach();
  //vagolap lezarasa
  ::CloseClipboard();
 }
}

Saját vágólap formátumok regisztrálása.

Előfordulhat, hogy a megengedett formátumok nem felelnek meg a továbbítani kívánt adat sajátosságainak. Ekkor saját formátumot kell regisztrálni. Ennek az a hátulütője, hogy a vágólapon lévő ilyen formátumú adatot csak az általunk írt programok tudják helyesen értelmezni, hiszen más nem ismeri a formátumot. Erre az lehet a megoldás, ha szabványos formátumban is felrakjuk ugyanazt az adatot.

Saját formátum regisztrálására a ::RegisterCliboardFormat API függvény való.

UINT RegisterClipboardFormat(LPCTSTR lpszFormat);
Paraméterként a formátum nevét kell megadni, visszatérési érték pedig a formátum-azonosító. Ezt az azonosítót kell átadni például a ::SetClipboardData és ::GetClipboardData függvényeknek. Példa:
UINT MyFormat;

MyFormat=::RegisterClipboardFormat("MyClipboardFormat");

Ezt a visszakapott azonosítót kell használnunk, a vágólapra másolásnál, illetve vágólapról való beillesztésnél.
::SetClipboardData(MyFormat, Hmydata);
Az átadott leíró (Hmydata) egy globális memóriablokk leírója.

A ::RegisterClipboardFormat meghívásakor, ha ugyanilyen névvel már létezik formátum, nem hoz létre újat, hanem visszaadja a már létező azonosítóját.
 
 

Késleltetett adatszolgáltatás röviden

Amint eddig is látszott, amikor adatot helyezünk el a vágólapon, az adatról előtte másolatot készítünk, és csak a másolatot adjuk át a vágólapnak. Ez gyakorlatilag annyit jelent, hogy az adat kétszer annyi memóriát foglal, mint amin elfér. Megvan egyszer annak a programnak, ami felrakta a vágólapra, meg megvan a vágólapnak. Ez főleg nagyméretű képek esetében zavaró. (nem mindegy, hogy 1.5, vagy 3 Mb-al kevesebb a szabad memória)

A problémára a késleltetett adatszolgáltatás a kerülőút.

Ekkor a ::SetClipboardData függvénynek a leíró helyett nullát adunk át paraméterként. Tehát semmi nem kerül a vágólapra. Ha más program meghívja a ::GetClipboardData függvényt, akkor a Windows értesíti az adatszolgáltató programot, mire az felpakolja az adatot a vágólapra.

Ekkor a szolgáltató program egy WM_RENDERFORMAT üzenetet kap amelynek wParam paramétere a formátum, nem kell megnyitnia a vágólapot, csak egy ::SetClipboardData függvényhívással felrakja az adatot a vágólapra. Itt történik meg az adat másolása. Elkerülni nem tudtuk, csak késleltettük.

Ha egy másik program törli a vágólapot, akkor a szolgáltató program adataira már nem lesz szükség, ekkor a WM_DESTROYCLIPBOARD üzenetet kapja.

Ha a szolgáltató program futása befejeződik, akkor kap egy WM_RENDERALLFORMAT üzenetet, ami azt jelenti, hogy fel kell raknia a vágólapra az összes egyébként általa szolgáltatott adatot.
 
 

Hát ennyit a vágólapról.

A forráskód ITT van!