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