توافق الطرف الثالث

Developer Guide

إذا كنت تقوم بالتطوير باستخدام لغة C++‎، فيمكنك استخدام ملف الترويسة ipchelper.h مباشرة من Seer SDK والذي يغلف جميع واجهات برمجة تطبيقات Win32 IPC الموضحة أدناه.

يدعم Seer التكامل مع تطبيقات الطرف الثالث ومديري الملفات المخصصين باستخدام Win32 IPC عبر رسائل WM_COPYDATA.

التكامل مع التطبيقات المخصصة (ACustomApp)

يمكن للتطبيق المخصص مطالبة Seer بعرض معاينة لمسار ملف معين.

الخطوة 1: العثور على مقبض نافذة Seer

ابحث عن مقبض النافذة باستخدام FindWindowW :

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

الخطوة 2: إرسال المسار المطلق للملف المحدد

أرسل المسار المطلق للملف إلى مقبض نافذة 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);
}

التكامل مع مدير ملفات مخصص (ACustomExplorer)

يمكن لمديري الملفات المخصصين تسجيل اسم فئة النافذة الخاصة بهم (classname) حتى يستمع Seer للضغط على مفتاح المسافة (Spacebar) داخلها، ويطلب مسار الملف المحدد حاليًا لعرض المعاينة.

الخطوة 1: تسجيل اسم الفئة

أنشئ ملف JSON في المسار %USERPROFILE%/Documents/Seer/explorers/. عند بدء تشغيل Seer، يقوم بتحميل جميع ملفات JSON في هذا الدليل. يجب أن يحتوي ملف JSON على اسم فئة النافذة المستهدفة:

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

الخطوة 2: معالجة الضغط على مفتاح المسافة

عندما يضغط المستخدم على مفتاح المسافة in نافذة مدير الملفات الخاص بك، يعترض Seer هذه الضغطة ويستدعي GetForegroundWindow لمطابقة classname. إذا كانت متطابقة، يرسل Seer رسالة WM_COPYDATA إلى مقبض نافذتك مع تعيين dwData إلى SEER_REQUEST_PATH (4000) و cbData = 0 و lpData = nullptr.

يرسل Seer هذه الرسالة باستخدام SendMessageTimeout مع مهلة قدرها 150ms لمنع واجهة المستخدم من التعليق في حال لم يستجب تطبيقك.

الخطوة 3: الاستجابة بالمسار المحدد

يجب أن يتعامل تطبيقك مع رسالة WM_COPYDATA ويتحقق مما إذا كانت dwData هي SEER_REQUEST_PATH ويستجيب بإرسال رسالة WM_COPYDATA إلى Seer مع تعيين dwData إلى SEER_RESPONSE_PATH (4001) تحتوي على المسار الكامل للملف المحدد كـ null-terminated wide string.

الخطوة 4: عرض المعاينة

بمجرد أن يتلقى Seer المسار، يتم عرض نافذة المعاينة وتنتهي العملية.


مرجع أوامر IPC (SeerCommand)

تم تعريف الأوامر التالية في seer/ipc.h للتواصل مع Seer:

اسم الأمر القيمة الوصف
SEER_REQUEST_PATH 4000 يتم إرسالها من Seer إلى المستكشف المخصص لطلب مسار الملف المحدد حاليًا.
SEER_RESPONSE_PATH 4001 يتم إرسالها من المستكشف المخصص مرة أخرى إلى Seer محملة بمسار الملف المحدد.
SEER_INVOKE_W32 5000 يتم إرسالها من تطبيق مخصص إلى Seer لبدء المعاينة في النافذة الرئيسية (الحد الأدنى للفاصل الزمني هو 200 مللي ثانية).
SEER_INVOKE_W32_SEP 5001 يتم إرسالها من تطبيق مخصص إلى Seer لبدء المعاينة في نافذة منفصلة.
SEER_IS_VISIBLE 5004 يتحقق مما إذا كانت نافذة المعاينة الرئيسية مرئية. يعيد VISIBLE_TRUE (1) أو VISIBLE_FALSE (0).
SEER_HIDE 5005 يخفي نافذة المعاينة الرئيسية إذا كانت مرئية.
SEER_GET_CURRENT_FILE 5006 يستعلم من Seer عن مسار الملف الذي تتم معاينته حاليًا (عبر الذاكرة المشتركة المسماة).
SEER_GET_VERSION 5007 يستعلم عن إصدار Seer (على سبيل المثال، يعيد 40001 للإصدار 4.0.1).
SEER_IS_TRACKING_ENABLED 5008 يستعلم عما إذا كان وضع تتبع الملفات ممكناً.

طلب الملف الذي تتم معاينته حاليًا

نظراً لأن WM_COPYDATA لا يمكنه إرجاع سلاسل نصية متغيرة الطول مباشرة، فإن الاستعلام عن الملف الذي تتم معاينته حالياً (SEER_GET_CURRENT_FILE) يستخدم بروتوكول تخطيط الملف (الذاكرة المشتركة المسماة).

مثال على التطبيق بلغة C++‎

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

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

    // إنشاء اسم فريد لتخطيط الملف
    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';

    // إرسال الأمر إلى Seer مع اسم التخطيط الفريد كـ 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;
}