Tương thích bên thứ 3

Developer Guide

Nếu bạn đang phát triển bằng C++, bạn có thể sử dụng trực tiếp tệp tiêu đề ipchelper.h từ Seer SDK, tệp này đóng gói tất cả các Win32 IPC API được mô tả bên dưới.

Seer hỗ trợ tích hợp với các ứng dụng bên thứ ba và trình quản lý tệp tùy chỉnh bằng cách sử dụng Win32 IPC thông qua tin nhắn WM_COPYDATA.

Tích hợp ứng dụng tùy chỉnh (ACustomApp)

Một ứng dụng tùy chỉnh có thể kích hoạt Seer để hiển thị bản xem trước cho một đường dẫn tệp cụ thể.

Bước 1: Tìm handle cửa sổ của Seer

Tìm handle cửa sổ bằng cách sử dụng FindWindowW :

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

Bước 2: Gửi đường dẫn tuyệt đối của tệp được chọn

Gửi đường dẫn tuyệt đối của tệp tới handle cửa sổ của 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);
}

Tích hợp trình quản lý tệp tùy chỉnh (ACustomExplorer)

Các trình quản lý tệp tùy chỉnh có thể đăng ký tên lớp cửa sổ (classname) của họ để Seer lắng nghe thao tác nhấn phím cách (Spacebar) bên trong chúng và yêu cầu đường dẫn của tệp hiện được chọn để hiển thị bản xem trước.

Bước 1: Đăng ký Classname

Tạo một tệp JSON dưới thư mục %USERPROFILE%/Documents/Seer/explorers/. Khi Seer khởi động, nó sẽ tải tất cả các tệp JSON trong thư mục này. Tệp JSON phải chứa tên lớp cửa sổ mục tiêu:

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

Bước 2: Xử lý nhấn phím cách

Khi người dùng nhấn phím cách trong cửa sổ trình quản lý tệp của bạn, Seer sẽ chặn phím nhấn đó và gọi GetForegroundWindow để khớp với classname. Nếu khớp, Seer sẽ gửi tin nhắn WM_COPYDATA tới handle cửa sổ của bạn với dwData được đặt thành SEER_REQUEST_PATH (4000), cbData = 0lpData = nullptr.

Seer gửi tin nhắn này bằng cách sử dụng SendMessageTimeout với thời gian chờ là 150ms để ngăn giao diện bị treo nếu ứng dụng của bạn không phản hồi.

Bước 3: Phản hồi bằng đường dẫn đã chọn

Ứng dụng của bạn phải xử lý tin nhắn WM_COPYDATA, kiểm tra xem dwData có phải là SEER_REQUEST_PATH không và phản hồi bằng cách gửi tin nhắn WM_COPYDATA quay lại Seer với dwData được đặt thành SEER_RESPONSE_PATH (4001) chứa đường dẫn đầy đủ của tệp được chọn dưới dạng chuỗi ký tự rộng kết thúc bằng ký tự null.

Bước 4: Hiển thị bản xem trước

Khi Seer nhận được đường dẫn, nó sẽ hiển thị cửa sổ xem trước và quá trình hoàn tất.


Tài liệu tham khảo lệnh IPC (SeerCommand)

Các lệnh sau được định nghĩa trong seer/ipc.h để giao tiếp với Seer:

Tên lệnh Giá trị Mô tả
SEER_REQUEST_PATH 4000 Được gửi từ Seer đến trình khám phá tùy chỉnh để yêu cầu đường dẫn tệp được chọn hiện tại.
SEER_RESPONSE_PATH 4001 Được gửi từ trình khám phá tùy chỉnh trở lại Seer chứa dữ liệu đường dẫn tệp được chọn.
SEER_INVOKE_W32 5000 Được gửi từ ứng dụng tùy chỉnh đến Seer để kích hoạt xem trước trong cửa sổ chính (khoảng thời gian tối thiểu 200ms).
SEER_INVOKE_W32_SEP 5001 Được gửi từ ứng dụng tùy chỉnh đến Seer để kích hoạt xem trước trong một cửa sổ riêng biệt.
SEER_IS_VISIBLE 5004 Kiểm tra xem cửa sổ xem trước chính có hiển thị hay không. Trả về VISIBLE_TRUE (1) hoặc VISIBLE_FALSE (0).
SEER_HIDE 5005 Ẩn cửa sổ xem trước chính nếu nó hiển thị.
SEER_GET_CURRENT_FILE 5006 Truy vấn Seer để lấy đường dẫn của tệp hiện được xem trước (thông qua bộ nhớ chia sẻ được đặt tên).
SEER_GET_VERSION 5007 Truy vấn phiên bản Seer (ví dụ: trả về 40001 cho phiên bản 4.0.1).
SEER_IS_TRACKING_ENABLED 5008 Truy vấn xem chế độ theo dõi tệp có được bật hay không.

Yêu cầu tệp hiện đang được xem trước

WM_COPYDATA không thể trực tiếp trả về các chuỗi có độ dài thay đổi, nên việc truy vấn tệp hiện được xem trước (SEER_GET_CURRENT_FILE) sử dụng giao thức ánh xạ tệp (bộ nhớ chia sẻ) được đặt tên.

Ví dụ triển khai C++

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

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

    // Tạo một tên duy nhất cho ánh xạ tệp
    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';

    // Gửi lệnh đến Seer với tên ánh xạ duy nhất làm dữ liệu
    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;
}