两种方法操作其它mac应用的窗口

16880003de1c4ef5ae0c(图文基本无关)
如果单纯说简单方便,其使用AppleScript更好,特别是现在有了JS的加入,比如:

(*

This Apple script will resize any program window to an exact size and the window is then moved to the center of your screen.
Specify the program name, height and width below and run the script.

Written by Amit Agarwal on December 10, 2013

*)

set theApp to "Google Chrome"
set appHeight to 1080
set appWidth to 1920

tell application "Finder"
    set screenResolution to bounds of window of desktop
end tell

set screenWidth to item 3 of screenResolution
set screenHeight to item 4 of screenResolution

tell application theApp
    activate
    reopen
    set yAxis to (screenHeight - appHeight) / 2 as integer
    set xAxis to (screenWidth - appWidth) / 2 as integer
    set the bounds of the first window to {xAxis, yAxis, appWidth + xAxis, appHeight + yAxis}
end tell

觉得增加脚本会让你的工程比较繁琐的话,还可以把脚本写入到object-c用对象调用的方法完成,比如:

NSApplescript * as = [[NSApplescript alloc] initWithSource:@"tell application \"TheApplication\"\nclose every window\nend tell"];
NSDictionary * errInfo;
NSAppleEventDescriptor * res = [as executeAndReturnError:&err];
if( !res ){
    // An error occurred. Inspect errInfo and perform necessary actions
}

[as release];

但是如果真的开发一个产品,使用纯的c/object-c还是更规范、可控一些,因此上面这个两个脚本的方法不算在内。闲话不说,直接贴代码:

#include <stdio.h>

#import <Foundation/Foundation.h>
#import <CoreFoundation/CoreFoundation.h>
#import <ApplicationServices/ApplicationServices.h>
#import <CoreGraphics/CoreGraphics.h>

typedef int CGSConnection;
extern CGSConnection _CGSDefaultConnection(void);
extern CGError CGSCopyWindowProperty(const CGSConnection cid, NSInteger wid, CFStringRef key, CFStringRef *output);

void getTitleList1(){
    CFStringRef titleValue;
    CGSConnection connection = CGSDefaultConnectionForThread();
    NSInteger windowCount, *windows;
    char cTitle[256] = {0};
    
    NSCountWindows(&windowCount);
    windows = (NSInteger*) malloc(windowCount * sizeof(NSInteger));
    if (windows) {
        NSWindowList(windowCount, windows);
        for (int i = 0; i < windowCount; ++i)
        {
            CGSCopyWindowProperty(connection, windows[i], CFSTR("kCGSWindowTitle"), &titleValue);
            if(!titleValue) //Not every window has a title
                continue;

            //CFStringGetCString(titleValue,cTitle,127,kCFStringEncodingMacRoman);
            CFStringGetCString(titleValue,cTitle,256,kCFStringEncodingUTF8);
            printf("title: %s\n",cTitle);
        }
        free(windows);
    }
}

void getTitleList2(){
    @autoreleasepool {
    // Get all the windows
    CFArrayRef windowListAll = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
    NSArray* arr = CFBridgingRelease(windowListAll);
    NSUInteger count = [arr count]; //CFArrayGetCount(arr);
    // Loop through the windows
    for (NSMutableDictionary* entry in arr){
        if (entry == nil){
            break;
        }
        NSLog(@"enter:%@",entry);
        NSString *wndName=[entry objectForKey:(id)kCGWindowName];
        NSInteger wndNumber=[[entry objectForKey:(id)kCGWindowNumber] intValue];
        NSLog(@"wndName:%@ number:%ld",wndName,wndNumber);
        if (![wndName isEqualToString: @"~/test.txt"]){
            //不是自己想要的窗口继续下一个循环
            continue;
        }
        //下面这个方法是手册中最先查到的,但仅对属于自己app的窗口有效,其它app的窗口无效,所以不能采用
        //NSWindow * wind=[NSApp windowWithWindowNumber: wndNumber];
        //NSLog(@"wnd:%@",wind);
        CGRect bounds;
        CGRectMakeWithDictionaryRepresentation((CFDictionaryRef)[entry objectForKey:@"kCGWindowBounds"], &bounds);
        NSLog(@"bounds: %@",NSStringFromRect(bounds));   
        //根据pid获取窗口所属的app
        pid_t pid = [[entry objectForKey:(id)kCGWindowOwnerPID] intValue];
        AXUIElementRef appRef = AXUIElementCreateApplication(pid);
        NSLog(@"Ref = %@",appRef);
        //获取app所有的窗口
        CFArrayRef windowList;
        AXUIElementCopyAttributeValue(appRef, kAXWindowsAttribute, (CFTypeRef *)&windowList);
        //NSLog(@"WindowList = %@", windowList);
        CFRelease(appRef);
        if (!windowList){
            //NSLog(@"windowList is nil");
            continue;
        }
        for (int i=0;i<CFArrayGetCount(windowList);i++){
            //遍历app所有窗口,查找跟全局遍历所获得窗口的实体
            AXUIElementRef windowRef = (AXUIElementRef) CFArrayGetValueAtIndex( windowList, i);
            NSLog(@"windowRef:%@",windowRef);
            CGWindowID application_window_id = 0;
            _AXUIElementGetWindow(windowRef, &application_window_id);
            if (application_window_id == wndNumber){
                //找到
                NSLog(@"Found a wnd that number is:%u",application_window_id);
                //根据需要来操作窗口的位置,仅用作示例,这里可以修改成其它操作
                CFTypeRef position;
                CGPoint newPoint;
                newPoint.x = 0;
                newPoint.y = 0;
                NSLog(@"Create new position");
                position = (CFTypeRef)(AXValueCreate(kAXValueCGPointType, (const void *)&newPoint));
                //setting new position
                AXUIElementSetAttributeValue(windowRef, kAXPositionAttribute, position);
            }
            CFRelease(windowRef);
        }
     NSLog(@"end a loop ----------------------------");
    } //for windowListAll
    } //autorelease
}

int main(int argc, char **argv){
    getTitleList1();    //第一种方法,重点在遍历
    getTitleList2();    //第二种方法,重点在获取窗口后可以进一步控制

    return 0;   
}

重点的内容直接看注释,其中的第二种方法可控性要好很多,不过程序也复杂一些。大概流程是先遍历所有屏幕的窗口->然后根据窗口获取该窗口所属的应用->再次获取应用所属的所有窗口->在这些窗口中找到自己想要的->控制,第二步的确做的会有大量重复遍历,不过从提供的api上看,目前只有这个办法才能够控制窗口。代码中有大量的日志信息,正式使用的话调试完成可以删掉。
这段代码使用object-c和c混编,后缀为.m,因为只是测试代码,没有建立xcode项目,是在命令行编译的,编译方法可能有的人不太熟悉,也贴出来:

clang -fobjc-arc  -o wndjob wndjob.m -framework CoreGraphics -framework AppKit

参考链接:
https://www.labnol.org/software/resize-mac-windows-to-specific-size/28345/
https://stackoverflow.com/questions/8898430/close-all-windows-of-another-app-using-accessibility-api
https://stackoverflow.com/questions/21069066/move-other-windows-on-mac-os-x-using-accessibility-api

转载于:https://www.cnblogs.com/andrewwang/p/8635292.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Unity是一款跨平台的游戏开发引擎,它不仅支持Windows平台,还支持Mac平台。当在Mac平台上使用Unity进行游戏开发时,如何让窗口前置成为一个重要问题。 在Unity中实现窗口前置有多种方法。首先,可以通过代码控制窗口的显示和隐藏来实现前置效果。通过调用相关的GUI函数,可以在游戏启动时将游戏窗口置于最前方,从而使其成为焦点窗口。这种方法适用于需要在特定场景或事件下实现窗口前置的情况。 另外,Unity还提供了一个PlayerSettings类,其中包含了一些用于设置窗口行为的属性。通过修改这些属性,也能实现窗口前置。例如,在PlayerSettings类中,有一个属性名为`defaultIsFullScreen`,通过将其设置为`true`,可以使游戏窗口一直处于全屏模式,从而实现前置效果。 除了以上方法,还可以通过修改Mac系统的相关设置,实现窗口前置。在Mac系统的“系统偏好设置”中,可以设置窗口行为,包括窗口的前置与否。通过调整这些设置,也能使Unity的窗口前置。 总的来说,Unity在Mac平台上实现窗口前置是可行的。我们可以通过编码、修改PlayerSettings、或者调整Mac系统设置来实现窗口前置效果。具体采用哪种方法,取决于实际的需求和开发环境。 ### 回答2: 要使Unity在Mac窗口前置,可以按照以下步骤操作: 1. 点击Unity编辑器菜单栏的"Edit"(编辑)选项,并选择"Preferences"(首选项)。 2. 在出现的首选项窗口中,选择"General"(常规)选项卡。 3. 在选项卡中,找到"Window focus"(窗口焦点)部分。 4. 在"Window focus"部分,你将看到两个选项:"Click to focus"(点击获得焦点)和"Auto minimize"(自动最小化)。 5. 选择"Click to focus"选项,这将使Unity窗口在点击时立即获得焦点。 6. 如果你希望Unity窗口在失去焦点时自动最小化,可以选择"Auto minimize"选项。这样,当你切换到其他窗口时,Unity窗口会自动最小化。 通过执行以上步骤,你可以在Mac上实现Unity窗口的前置。这能够帮助你更方便地操作Unity编辑器和进行开发工作。 ### 回答3: 要实现在Unity中使Mac窗口前置,可以使用以下方法: 首先,在Unity的Project窗口中找到你的游戏场景,双击打开它。 然后,在Hierarchy窗口中找到你想要前置的游戏对象。 接下来,在Inspector窗口中找到这个游戏对象的脚本,或者手动添加一个新的脚本。 然后,在脚本中添加以下代码: ``` #if UNITY_EDITOR using UnityEditor; using UnityEditor.iOS.Extensions; #else using UnityEngine; #endif public class WindowFront : MonoBehaviour { // 在游戏启动时调用 void Start() { #if UNITY_EDITOR UnityEditor.EditorApplication.ExecuteMenuItem("Window/Focus"); #else UnityEngine.Application.Focus(); #endif } } ``` 最后,保存并运行游戏,你现在就可以在Mac上实现Unity窗口前置了。 这段代码的作用是,在游戏启动时使用Unity Editor命令“Window/Focus”将窗口前置,或者使用Unity API函数“Application.Focus()”来实现相同的效果。 注意,这段代码中使用了条件编译指令“#if UNITY_EDITOR”和“#else”,因为在Unity编辑器中运行和在实际的Mac应用程序中运行是不同的。所以我们需要根据运行环境选择合适的代码。 希望以上方法能够帮助你实现Unity Mac窗口前置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值