3rd Party Compatibility

Developer Guide

If you are developing in C++, you can directly integrate the ipchelper.h helper from the Seer SDK to use these APIs out of the box.

Seer supports integration with third-party applications and custom file managers using Win32 IPC via WM_COPYDATA messages.

Custom App Integration (ACustomApp)

A custom application can trigger Seer to display a preview for a specific file path.

Step 1: Find the window handle of Seer

Find the window handle using FindWindowW:

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

Step 2: Send the selected file's absolute path

Send the absolute path of the file to Seer's window handle:

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);
}

Custom File Manager Integration (ACustomExplorer)

Custom file managers can register their window classname so that Seer listens for the Spacebar keypress within them, and requests the path of the currently selected file to display a preview.

Step 1: Register the Classname

Create a JSON file under %USERPROFILE%/Documents/Seer/explorers/. When Seer starts up, it loads all JSON files in this directory. The JSON must contain the target window class name:

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

Step 2: Handle Spacebar Press

When the user presses the Spacebar in your file manager window, Seer intercepts the keystroke and calls GetForegroundWindow to match the classname. If it matches, Seer sends a WM_COPYDATA message to your window handle with dwData set to SEER_REQUEST_PATH (4000), cbData = 0, and lpData = nullptr.

Seer sends this message using SendMessageTimeout with a timeout of 150ms to prevent the interface from hanging if your application is unresponsive.

Step 3: Respond with Selected Path

Your application must handle the WM_COPYDATA message, check if dwData is SEER_REQUEST_PATH, and respond by sending a WM_COPYDATA message back to Seer with dwData set to SEER_RESPONSE_PATH (4001) containing the full path of the selected file as a null-terminated wide string.

Step 4: Preview Display

Once Seer receives the path, it displays the preview window and the process completes.


IPC Command Reference (SeerCommand)

The following commands are defined in seer/ipc.h for communicating with Seer:

Command Name Value Description
SEER_REQUEST_PATH 4000 Sent from Seer to custom explorer requesting the current selected file path.
SEER_RESPONSE_PATH 4001 Sent from custom explorer back to Seer containing the selected file path payload.
SEER_INVOKE_W32 5000 Sent from custom app to Seer to trigger preview in the main window (minimum 200ms interval).
SEER_INVOKE_W32_SEP 5001 Sent from custom app to Seer to trigger preview in a separate window.
SEER_IS_VISIBLE 5004 Check if the main preview window is visible. Returns VISIBLE_TRUE (1) or VISIBLE_FALSE (0).
SEER_HIDE 5005 Hide the main preview window if visible.
SEER_GET_CURRENT_FILE 5006 Query Seer for the path of the currently previewed file (via named shared memory).
SEER_GET_VERSION 5007 Query Seer version (e.g. returns 40001 for version 4.0.1).
SEER_IS_TRACKING_ENABLED 5008 Query if file tracking mode is enabled.

Requesting the Currently Previewed File

Because WM_COPYDATA cannot directly return variable-length strings, querying the currently previewed file (SEER_GET_CURRENT_FILE) uses a named file mapping (shared memory) protocol.

C++ Example Implementation

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

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

    // Create a unique name for the file mapping
    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';

    // Send command to Seer with the unique mapping name as payload
    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;
}