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 Copy menü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!