Zgodność firm trzecich

Developer Guide

Jeśli tworzysz oprogramowanie w C++, możesz bezpośrednio użyć pliku nagłówkowego ipchelper.h z Seer SDK, który hermetyzuje wszystkie opisane poniżej interfejsy API Win32 IPC.

Seer obsługuje integrację z aplikacjami firm trzecich i niestandardowymi menedżerami plików za pomocą Win32 IPC za pośrednictwem komunikatów WM_COPYDATA.

Integracja z niestandardową aplikacją (ACustomApp)

Niestandardowa aplikacja może wyzwolić Seer w celu wyświetlenia podglądu dla określonej ścieżki pliku.

Krok 1: Znalezienie uchwytu okna Seer

Znajdź uchwyt okna za pomocą FindWindowW :

HWND seer = FindWindowW(L"SeerWindowClass", nullptr);

Krok 2: Wysłanie ścieżki absolutnej wybranego pliku

Wyślij ścieżkę absolutną pliku do uchwytu okna Seer:

void sendPath2Seer(HWND seer, LPCWSTR path)
{
    COPYDATASTRUCT cd;
    cd.cbData = (wcslen(path) + 1) * sizeof(wchar_t);
    cd.lpData = (LPVOID)path;
    cd.dwData = SEER_INVOKE_W32; // 5000
    SendMessageW(seer, WM_COPYDATA, 0, (LPARAM)&cd);
}

Integracja z niestandardowym menedżerem plików (ACustomExplorer)

Niestandardowe menedżery plików mogą zarejestrować nazwę klasy swojego okna (classname), dzięki czemu Seer nasłuchuje naciśnięcia spacji (Spacebar) w tym oknie i żąda ścieżki aktualnie wybranego pliku w celu wyświetlenia podglądu.

Krok 1: Rejestracja nazwy klasy

Utwórz plik JSON w folderze %USERPROFILE%/Documents/Seer/explorers/. Po uruchomieniu Seer ładuje wszystkie pliki JSON z tego katalogu. Plik JSON musi zawierać nazwę klasy docelowego okna:

{
  "classname": "YourCustomExplorerClass",
  "windowtext": "OptionalWindowTextToMatch",
  "appname": "YourAppName"
}

Krok 2: Obsługa naciśnięcia spacji

Gdy użytkownik naciśnie spację w oknie menedżera plików, Seer przechwytuje naciśnięcie klawisza i wywołuje GetForegroundWindow w celu dopasowania nazwy klasy. Jeśli pasuje, Seer wysyła komunikat WM_COPYDATA do uchwytu okna z dwData ustawionym na SEER_REQUEST_PATH (4000), cbData = 0 i lpData = nullptr.

Seer wysyła ten komunikat za pomocą SendMessageTimeout z limitem czasu 150ms, aby zapobiec zawieszeniu interfejsu, jeśli aplikacja nie odpowiada.

Krok 3: Odpowiedź z wybraną ścieżką

Aplikacja musi obsłużyć komunikat WM_COPYDATA, sprawdzić, czy dwData to SEER_REQUEST_PATH, i odpowiedzieć wysyłając komunikat WM_COPYDATA z powrotem do Seer z dwData ustawionym na SEER_RESPONSE_PATH (4001), zawierający pełną ścieżkę wybranego pliku jako ciąg znaków szerokich zakończony znakiem null.

Krok 4: Wyświetlenie podglądu

Gdy Seer otrzyma ścieżkę, wyświetla okno podglądu i proces się kończy.


Słownik poleceń IPC (SeerCommand)

Następujące polecenia są zdefiniowane w seer/ipc.h do komunikacji z Seer:

Nazwa polecenia Wartość Opis
SEER_REQUEST_PATH 4000 Wysyłane z Seer do niestandardowego eksploratora z żądaniem ścieżki aktualnie wybranego pliku.
SEER_RESPONSE_PATH 4001 Wysyłane z niestandardowego eksploratora z powrotem do Seer, zawierające ścieżkę wybranego pliku.
SEER_INVOKE_W32 5000 Wysyłane z niestandardowej aplikacji do Seer w celu wyzwolenia podglądu w oknie głównym (minimalny odstęp 200 ms).
SEER_INVOKE_W32_SEP 5001 Wysyłane z niestandardowej aplikacji do Seer w celu wyzwolenia podglądu w osobnym oknie.
SEER_IS_VISIBLE 5004 Sprawdza, czy główne okno podglądu jest widoczne. Zwraca VISIBLE_TRUE (1) lub VISIBLE_FALSE (0).
SEER_HIDE 5005 Ukrywa główne okno podglądu, jeśli jest widoczne.
SEER_GET_CURRENT_FILE 5006 Zapytuje Seer o ścieżkę aktualnie podglądanego pliku (poprzez nazwaną pamięć współdzieloną).
SEER_GET_VERSION 5007 Zapytuje o wersję Seer (np. zwraca 40001 dla wersji 4.0.1).
SEER_IS_TRACKING_ENABLED 5008 Zapytuje, czy tryb śledzenia plików jest włączony.

Żądanie aktualnie podglądanego pliku

Ponieważ WM_COPYDATA nie może bezpośrednio zwracać ciągów znaków o zmiennej długości, zapytanie o aktualnie podglądany plik (SEER_GET_CURRENT_FILE) korzysta z nazwanego protokołu mapowania plików (pamięci współdzielonej).

Przykładowa implementacja w C++

#include <windows.h>
#include <string>

std::wstring getSeerCurrentFile(HWND seer_hwnd)
{
    if (!seer_hwnd) return L"";

    // Utwórz unikalną nazwę dla mapowania plików
    wchar_t map_name[MAX_PATH] = {0};
    swprintf_s(map_name, L"SeerCurFile_%u_%llu", GetCurrentProcessId(), GetTickCount64());

    constexpr size_t buf_bytes = MAX_PATH * sizeof(wchar_t);
    HANDLE map = CreateFileMappingW(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, buf_bytes, map_name);
    if (!map) return L"";

    auto view = static_cast<wchar_t*>(MapViewOfFile(map, FILE_MAP_ALL_ACCESS, 0, 0, buf_bytes));
    if (!view) {
        CloseHandle(map);
        return L"";
    }
    view[0] = L'\0';

    // Wyślij polecenie do Seer z unikalną nazwą mapowania jako danymi
    COPYDATASTRUCT cds;
    cds.dwData = 5006; // SEER_GET_CURRENT_FILE
    cds.cbData = buf_bytes;
    cds.lpData = map_name;

    SendMessageW(seer_hwnd, WM_COPYDATA, 0, reinterpret_cast<LPARAM>(&cds));

    std::wstring current_file;
    if (view[0] != L'\0') {
        current_file = view;
    }

    UnmapViewOfFile(view);
    CloseHandle(map);
    return current_file;
}