Wyłapywanie kopiowanych/wklejanych plików

0

Na początku chciałbym wszystkich przywitać, jestem nowy na forum :)

Mam za zadanie tworzenie backup'ów wszystkich kopiowanych/wklejanych plików w systemie. Pierwsze co przyszło mi do głowy to odbieranie wiadomości WM_DRAWCLIPBOARD, tak więc zrobiłem i wyskrobałem takie coś:

 
case WM_DRAWCLIPBOARD:
        {
            if(IsClipboardFormatAvailable(CF_HDROP) == true && OpenClipboard(NULL) == true)
            {
                HGLOBAL hGlobal = GetClipboardData(CF_HDROP);
                if(hGlobal != NULL)
                {
                    std::vector<std::string> copiedFiles;
                    UINT numberCopiedFiles;
                    char filePath[MAX_PATH + 1];

                    HDROP hDrop = (HDROP)GlobalLock(hGlobal);
                    if(hDrop != NULL)
                    {
                        numberCopiedFiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0);
                        for(UINT i = 0; i < numberCopiedFiles; i++)
                        {
                            DragQueryFile(hDrop, i, filePath, MAX_PATH + 1);
                            // tutaj operacje 
                        }
                        GlobalUnlock(hGlobal);
                    }
                }
                CloseClipboard();
            }
        }

Lecz po kilku testach zorientowałem się, iż WM_DRAWCLIPBOARD jest wysyłana zarówno podczas kopiowania jak i wycinania. Od razu spostrzegłem, że może to powodować błąd w pewnych sytuacjach, np przypuśćmy taki scenariusz: użytkownik wyciął plik, mój program pobiera jego ścieżkę, następnie użytkownik wkleja ten plik do innego folderu, a więc mój program zawiera już nieistniejącą ścieżkę pliku. Dlatego ten pomysł raczej odpada. Pomyślałem, że lepszym rozwiązaniem było by otrzymywać listę plików(ich ścieżki) kiedy zostaną już gdzieś wklejone, a nie kiedy zostały skopiowane/wycięte, lecz za bardzo nie wiem jak się za to zabrać.

EDIT: znalazłem coś o co mi chodzi: Clipboard.GetFileDropList(), lecz jest to funkcją framework'u .NET, ja potrzebuje takiego odpowiednika dla C++.

0

WM_CHANGECBCHAIN, SetClipboardViewer()

0
_13th_Dragon napisał(a):

WM_CHANGECBCHAIN, SetClipboardViewer()

Oczywiście odbieram WM_CHANGECBCHAIN, jak i wywołałem SetClipboardViewer().

 
case WM_CHANGECBCHAIN:
        {
            if(hWndNextClipboardViewer == (HWND)wParam) hWndNextClipboardViewer = (HWND)lParam;
            else if(hWndNextClipboardViewer != NULL) SendMessage(hWndNextClipboardViewer, message, wParam, lParam);
            break;
        }
        case WM_CREATE:
        {
            hWndNextClipboardViewer = SetClipboardViewer(hWnd);
            break;
        }
        case WM_DESTROY:
        {
            ChangeClipboardChain(hWnd, hWndNextClipboardViewer);
            PostQuitMessage(0);
            break;
        }

Ale jakie to ma odniesienie do mojego problemu ?

0

I jak nikt nic nie poradzi ? Szukałem czegoś w necie, lecz niestety nic nie znalazłem :(

0

Skoro zajmujesz się plikami to bardziej ci pasuje:
FindFirstChangeNotification();
FindCloseChangeNotification();

0

a tak w ogóle to jeśli użytkownik zassie plik z netu przez firefoxa lub downloader jakiś to wykryjesz to? albo jak przez komunikator ktoś wyśle mu plik, wykryjesz to? wtedy nikt ctrl+c nie używa.
btw. a co z dropbox? wyłączyć dropboxa możesz, nawklejać plików i odpalić dropboxa i dropbox wykryje nowe pliki, wykryje też zmiany w bajtach np. w dokumencie tekstowym, który zmodyfikowałeś.

0

meViu, nie znajdujesz, bo szukasz nie tego, co trzeba! Sięgnij głębiej, do OLE, do interfejsu shella:

virtual void OnClipboardChanged()//WM_DRAWCLIPBOARD
{
	IDataObject *clipdata;
	SetWindowText(TEXT(""));

	if (!OleGetClipboard(&clipdata))
	{
		static FORMATETC fmt = {0,0,DVASPECT_CONTENT,-1,TYMED_HGLOBAL};
		// CFSTR_PREFERREDDROPEFFECT = TEXT("Preferred DropEffect")
		fmt.cfFormat = RegisterClipboardFormat(CFSTR_PREFERREDDROPEFFECT); 
		STGMEDIUM medium;

		if (!clipdata->GetData(&fmt, &medium))
		{
			DWORD PreferredDropEffect = *(DWORD*)GlobalLock(medium.hGlobal);
			GlobalUnlock(medium.hGlobal);
			ReleaseStgMedium(&medium);

			TCHAR info[64];
			_sntprintf(info, sizeof...(info), TEXT("type: %s (%p)"),
				PreferredDropEffect & DROPEFFECT_MOVE ? TEXT("move"):
				PreferredDropEffect & DROPEFFECT_COPY ? TEXT("copy"):
				TEXT("unknown"), PreferredDropEffect);
			SetWindowText(info);
		}
		clipdata->Release();
	}
}

Powyższy snippet pochodzi z innego języka programowania, możliwe drobne błędy składniowe.
Więcej znajdziesz w sieci szukając frazy Shell Clipboard Formats. Poniżej jest kilka przykładów.

Do RegisterClipboardFormat możesz podstawić w podobny sposób kilka poniższych nazw formatów, wtedy GetData zwraca to co w prawej kolumnie, ale gdzieniegdzie trzeba lindex w FORMATETC zmieniać w pętli od zera do ilości oczekiwanych danych:

clipboard format data format
"FileGroupDescriptor" struct FILEGROUPDESCRIPTORA
"FileGroupDescriptorW" struct FILEGROUPDESCRIPTORW
"FileContents" char[] path
"UniformResourceLocator" char[] path
"UniformResourceLocatorW" WCHAR[] path

1 użytkowników online, w tym zalogowanych: 0, gości: 1