Jak korzystać ze Schowka


Wstęp

W dokumencie tym znajdują się informacje w oparciu, o które można w łatwy sposób stworzyć dla własnej aplikacji metody obsługujące zapis i odczyt danych ze Schowka.

 

Informacje podstawowe

Schowek (ang. Clipboard) jest jedną z metod komunikacji pomiędzy procesami dostępnych w systemie Windows, umożliwia wymianę danych między aplikacją źródłową (umieszczającą dane w Schowku) i docelową (odczytującą dane). Schowek jest również używany do przekazywania danych w operacjach OLE.

Do obsługi Schowka przeznaczone są polecenia Wklej (ang. Paste) z Wytnij (ang. Cut), Kopiuj (ang. Copy) z menu Edycja (ang. Edit), odpowiednio powiązane w MFC z następującymi identyfikatorami: ID_EDIT_PASTE, ID_EDIT_CUT, ID_EDIT_COPY.  Można dodać do klasy widoku (format zapisywanych za pomocą kreatora ClassWizard danych może być zależny od widoku) metody obsługi uruchamiane po wybraniu odpowiedniej opcji z menu. W metodach tych musi zostać zaimplementowana realizacja następujących czynności:

Wycinanie i kopiowanie danych do Schowka:

Wklejanie danych ze Schowka do dokumentu:

 

Podstawowe metody wykorzystywane przy obsłudze Schowka

OpenClipboard BOOL OpenClipboard()
Otwiera Schowek, jeśli operacja przebiegnie prawidłowo zostaje zwrócona wartość TRUE w przeciwnym przypadku FALSE (aby uzyskać szczegółowe informacje o zaistniałym błędzie można skorzystać z funkcji GetLastError).

CloseClipboard BOOL CloseClipboard()
Zamyka Schowek, gdy operacja zakończy się sukcesem zwraca wartość różną od zera w przeciwnym przypadku zero.

SetClipboardData HANDLE SetClipboardData(UINT uFormat, HANDLE hMem)
Metoda wstawia do Schowka dane w określonym formacie, jeśli wszystko przebiegnie prawidłowo zwraca uchwyt do danych, jeśli wystąpi błąd zwraca NULL.
Argument uFormat specyfikuje format danych, jeśli nie jest to standardowy format obsługiwany przez Schowek musi zostać wcześniej zarejestrowany (RegisterClipboardFormat)
hMem identyfikuje dane zapisane w wyspecyfikowanym formacie, jest to uchwyt do globalnie zaalokowanego obszaru pamięci RAM, np. obiekt typu CMemFile

GetClipboardData HANDLE GetClipboardData(UINT uFormat)
Pobiera ze Schowka dane w wyspecyfikowanym formacie, jeśli działanie zakończy się sukcesem zwraca uchwyt do pobranych danych, w przeciwnym przypadku NULL
Argument uFormat określa format danych, które mają zostać pobrane ze Schowka

 

Przykładowe formaty zapisu danych

Poniżej przedstawiono przykładowe formaty zapisu danych do Schowka standardowo zarejestrowane w systemie Windows:

Nazwa formatu Znaczenie
CF_BITMAP Uchwyt do bitmapy (HBITMAP).
CF_DIB Obiekt w pamięci zawierający strukturę BITMAPINFO definiującą wymiary i kolory bitmapy.
CF_ENHMETAFILE Uchwyt do obrazu typu enhanced metafile (HENHMETAFILE).
CF_METAFILEPICT Uchwyt do struktury definiującej format obrazu zapisanego w metapliku (METAFILEPICT).
CF_PALETTE Uchwyt do palety kolorów. Jeśli aplikacja zapisuje do schowka informacje zależne od palety należy w schowku umieścić również odpowiednią paletę.
CF_OEMTEXT Format tekstu zawierający znaki w trybie OEM. Każda linia kończy się kombinacją "powrót karetki + nowa linia (ang. linefeed)" (CR+LF) a znak NULL określa koniec danych.
CF_TEXT Format tekstowy. Każda linia kończy się kombinacją (CR+LF) a znak NULL określa koniec danych. Ten format należy stosować dla tekstu ANSI.
CF_WAVE Reprezentuje dane audio w standardowym formacie wave, próbkowane z częstotliwością 11 lub 22 kHz.

W większości przypadków aplikacja korzysta ze schowka przekazując bądź odczytując dane zapisane we własnym, nietypowym formacie, konieczne jest wówczas zgłoszenie w systemie takiego formatu co umożliwi jednoznaczną identyfikacje typu danych zawartych w schowku..
Operacja rejestracji własnego formatu danych przechowywanych w schowku wymaga wykorzystania funkcji:

UINT CWnd::RegisterClipboardFormat(LPCTSTR lpszFormat);

Metoda ta jako argument przyjmuje niezerowy string będący nazwą nowo rejestrowanego formatu danych przechowywanych w schowku a zwraca wartość typu UINT będącą identyfikatorem tego formatu. W przypadku błędu podczas rejestracji zostaje zwrócona wartość 0. Wywołanie tej metody z odpowiednim argumentem należy umieścić w konstruktorze klasy widoku.

////////////////////////////////////////////////////////

// CClipSampleView.cpp - klasa widoku.

// konstruktor klasy widoku,



CClipSampleView::CClipSampleView()

{

    // zarejestrowanie formatu danych w schowku,

    m_nClipboardFormat = ::RegisterClipboardFormat(_T("BGAK.ClipSample.1"));



    ...

}

 

Przykład wykorzystania Schowka

Poniżej zostały przedstawione metody ilustrujące korzystanie ze Schowka. Realizują one kopiowanie i wklejanie danych charakterystycznych dla pewnej aplikacji, zapisanych w zgłoszonym wcześniej formacie m_nClipboardFormat. Po zaimplementowaniu funkcji my_SaveData, my_LoadData i zgłoszeniu odpowiedniego formatu danych przedstawiony kod może służyć jako szkielet dla rzeczywistych metod realizujących obsługę Schowka.

////////////////////////////////////////////////////////

// CClipSampleView.cpp - klasa widoku.



...



// Kopiowanie danych do Schowka.

void CClipSampleView::OnEditCopy() 

{

    // utworzenie pliku w pamięci RAM "memFile" i obiektu 

    // archiwizacji danych "ar" powiązanego z tym plikiem,

    CSharedFile memFile;

    CArchive ar(&memFile, CArchive::store|CArchive::bNoFlushOnDelete);



    // własna funkcja serializująca do "ar" wymagane informacje

    my_SaveData(ar);

    ar.Flush();



    // zamknięcie pliku w pamięci (uchwyt do pliku zapisany w hData),

    HGLOBAL hData = memFile.Detach();



    // otwarcie Schowka,

    if (OpenClipboard())

    {

        // przesłanie do schowka wymaganych danych i zamknięcie Schowka,

        ::SetClipboardData(m_nClipboardFormat, hData);

        CloseClipboard();



    }

    else

        AfxMessageBox(IDS_CANNOT_OPEN_CLIPBOARD, MB_OK | MB_ICONWARNING);

}



// Pobranie danych ze Schowka.

void CGraphView::OnEditPaste()

{

    // otwarcie Schowka

    if (OpenClipboard())

    {

        // pobranie uchwytu do danych o wybranym formacie przechowywanych 

        // w Schowku

        HANDLE hData = ::GetClipboardData(m_nClipboardFormat);

        if (hData != NULL)

        {

            // właściwy odczyt danych ze Schowka,

            CSharedFile memFile;

            memFile.SetHandle(hData, FALSE);

            CArchive ar(&memFile, CArchive::load);



            // własna procedura zapisująca odczytane dane do dokumentu,

            my_LoadData(ar);



            ar.Close();

            memFile.Detach();

        }

        else

            AfxMessageBox(IDS_CANNOT_GET_CLIPBOARD_DATA, MB_OK | MB_ICONWARNING);



        // zamknięcie Schowka

        CloseClipboard();

    }

    else

        AfxMessageBox(IDS_CANNOT_OPEN_CLIPBOARD, MB_OK | MB_ICONWARNING);

}

 


Strona główna