نافذة تحريك وتغيير حجم واجهات برمجة التطبيقات في نظام التشغيل OS X

StackOverflow https://stackoverflow.com/questions/614185

  •  03-07-2019
  •  | 
  •  

سؤال

أنا أحاول العثور على توثيق (أو غير موثقة ، إذا كان هذا هو الخيار الوحيد) واجهات برمجة التطبيقات على نظام التشغيل OS X الاستعلام في قائمة ويندوز من نافذة الخادم ثم يسبب ويندوز تحريك و تغيير الحجم.يمكن لأي شخص أن لي نقطة في الاتجاه الصحيح ؟ أظن أنه سيكون بدءا من شيء مثل FindWindowEx و MoveWindow تحت Win32.

علما بأنني أريد أن أفعل هذا من عملية خارجية - أنا لا أطلب منك كيفية التحكم فقط بلدي التطبيق في نافذة حجم الموقف.

هل كانت مفيدة؟

المحلول

استخدام إمكانية الوصول إلى API.باستخدام API يمكنك الاتصال عملية الحصول على قائمة ويندوز (في الواقع مجموعة) ، والحصول على المناصب والأحجام من كل نافذة و أيضا تغيير خصائص النافذة إذا كنت تحب.

غير أن التطبيق يمكن أن يكون إلا باستخدام API هذا إذا كان المستخدم لديه تمكين وصول الأجهزة المساعدة في تفضيلات (بادئات النظام -> الوصول الشامل) ، في هذه الحالة جميع التطبيقات استخدام API ، أو إذا كان التطبيق الخاص بك هو موثوق assitive تطبيق (عندما يكون موثوق به ، فإنه قد تستخدم API, حتى إذا لم يتم تحديد هذا الخيار).إمكانية الوصول إلى API نفسه يوفر الوظائف اللازمة لجعل التطبيق الخاص بك موثوق بها - في الأساس يجب أن تصبح الجذر (باستخدام خدمات الأمن إلى طلب أذونات الجذر المستخدم) ثم علامة العملية الخاصة بك موثوق به.مرة واحدة في التطبيق الخاص بك تم وضع علامة موثوق به ، فإنه يجب إعادة تشغيل به الدولة هو فحص فقط على بدء و لا يمكن أن تتغير أثناء تشغيل التطبيق.ثقة الدولة الدائم, إلا إذا كان المستخدم يتحرك التطبيق في مكان آخر أو تجزئة تطبيق تغييرات الثنائية (مثلبعد التحديث).إذا كان المستخدم لديه المعينات تمكين في بادئات, جميع الطلبات تعامل كما لو كانت ثقة.عادة التطبيق الخاص بك سوف تحقق إذا تم تمكين هذا الخيار, إذا كان على فعل الأشياء الخاصة بك.إذا لم يكن قد تحقق مما إذا كان هو بالفعل موثوق به ، إذا كان هذا هو مرة أخرى فقط تفعل الأشياء الخاصة بك.إذا لا تحاول أن تجعل من نفسها ثقة ثم إعادة تشغيل التطبيق إلا إذا كان المستخدم انخفضت إذن الجذر.API يوفر جميع الوظائف اللازمة للتحقق من كل هذا.

توجد وظائف خاصة أن تفعل الشيء نفسه باستخدام نظام التشغيل Mac OS مدير النافذة ، ولكن الميزة الوحيدة التي سوف تشتري لك هو أنك لا تحتاج إلى أن تكون موثوق إمكانية تطبيق (وهو وقت واحد عملية على الإطلاق الأولى في معظم الحالات).مساوئ هي أن هذا المعهد قد تتغير في أي وقت (وقد تغيرت بالفعل في الماضي) ، كل شيء غير الشرعيين و الوظائف هي المعروفة فقط من خلال الهندسة العكسية.إمكانية الوصول ومع ذلك هو الجمهور ، تم توثيقه و لم تتغير كثيرا منذ أول OS X الإصدار التي أدخلت عليه (بعض وظائف جديدة أضيفت في 10.4 ثانية في 10.5 ، ولكن ليس كثيرا آخر لم يتغير).

وإليك المثال التعليمات البرمجية.وسوف انتظر 5 ثوان ، بحيث يمكنك التبديل إلى إطار آخر قبل أن يفعل أي شيء آخر (وإلا فإنه سوف يعمل دائما مع إطار المحطة الطرفية, مملة نوعا ما للاختبار).ثم أنها سوف تحصل على الجبهة الأكثر عملية ، أمام معظم نافذة من هذه العملية ، طباعته موقف و حجم و أخيرا تحرك قبل 25 بكسل إلى اليمين.ترجمة على سطر الأوامر مثل ذلك (على افتراض أنه يدعى test.ج)

gcc -framework Carbon -o test test.c

يرجى ملاحظة أن لا تؤدي أي التحقق خطأ في رمز البساطة (هناك العديد من الأماكن التي يمكن أن تسبب البرنامج إلى تعطل إذا كان هناك شيء يذهب على نحو خاطئ و بعض الأمور التي قد/يمكن أن تذهب الخطأ).هنا كود:

/* Carbon includes everything necessary for Accessibilty API */
#include <Carbon/Carbon.h>

static bool amIAuthorized ()
{
    if (AXAPIEnabled() != 0) {
        /* Yehaa, all apps are authorized */
        return true;
    }
    /* Bummer, it's not activated, maybe we are trusted */
    if (AXIsProcessTrusted() != 0) {
        /* Good news, we are already trusted */
        return true;
    }
    /* Crap, we are not trusted...
     * correct behavior would now be to become a root process using
     * authorization services and then call AXMakeProcessTrusted() to make
     * ourselves trusted, then restart... I'll skip this here for
     * simplicity.
     */
    return false;
}


static AXUIElementRef getFrontMostApp ()
{
    pid_t pid;
    ProcessSerialNumber psn;

    GetFrontProcess(&psn);
    GetProcessPID(&psn, &pid);
    return AXUIElementCreateApplication(pid);
}


int main (
    int argc,
    char ** argv
) {
    int i;
    AXValueRef temp;
    CGSize windowSize;
    CGPoint windowPosition;
    CFStringRef windowTitle;
    AXUIElementRef frontMostApp;
    AXUIElementRef frontMostWindow;

    if (!amIAuthorized()) {
        printf("Can't use accessibility API!\n");
        return 1;
    }

    /* Give the user 5 seconds to switch to another window, otherwise
     * only the terminal window will be used
     */
    for (i = 0; i < 5; i++) {
        sleep(1);
        printf("%d", i + 1);
        if (i < 4) {
            printf("...");
            fflush(stdout);
        } else {
            printf("\n");
        }
    }

    /* Here we go. Find out which process is front-most */
    frontMostApp = getFrontMostApp();

    /* Get the front most window. We could also get an array of all windows
     * of this process and ask each window if it is front most, but that is
     * quite inefficient if we only need the front most window.
     */
    AXUIElementCopyAttributeValue(
        frontMostApp, kAXFocusedWindowAttribute, (CFTypeRef *)&frontMostWindow
    );

    /* Get the title of the window */
    AXUIElementCopyAttributeValue(
        frontMostWindow, kAXTitleAttribute, (CFTypeRef *)&windowTitle
    );

    /* Get the window size and position */
    AXUIElementCopyAttributeValue(
        frontMostWindow, kAXSizeAttribute, (CFTypeRef *)&temp
    );
    AXValueGetValue(temp, kAXValueCGSizeType, &windowSize);
    CFRelease(temp);

    AXUIElementCopyAttributeValue(
        frontMostWindow, kAXPositionAttribute, (CFTypeRef *)&temp
    );
    AXValueGetValue(temp, kAXValueCGPointType, &windowPosition);
    CFRelease(temp);

    /* Print everything */
    printf("\n");
    CFShow(windowTitle);
    printf(
        "Window is at (%f, %f) and has dimension of (%f, %f)\n",
        windowPosition.x,
        windowPosition.y,
        windowSize.width,
        windowSize.height
    );

    /* Move the window to the right by 25 pixels */
    windowPosition.x += 25;
    temp = AXValueCreate(kAXValueCGPointType, &windowPosition);
    AXUIElementSetAttributeValue(frontMostWindow, kAXPositionAttribute, temp);
    CFRelease(temp);

    /* Clean up */
    CFRelease(frontMostWindow);
    CFRelease(frontMostApp);
    return 0;
}

جيب بن سئل كيف يمكنك الحصول على قائمة من جميع النوافذ في التعليقات ما يلي:

بدلا من "kAXFocusedWindowAttribute" يمكنك استخدام "kAXWindowsAttribute" عن AXUIElementCopyAttributeValue وظيفة.ثم النتيجة لا AXUIElementRef ، ولكن CFArray من AXUIElementRef العناصر ، واحدة لكل نافذة من هذا التطبيق.

نصائح أخرى

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

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top