【问题标题】:How to badge file and folder using Cocoa如何使用 Cocoa 标记文件和文件夹
【发布时间】:2019-07-29 21:37:40
【问题描述】:

我想用某种颜色(图像)标记文件和文件夹。如何实现?

我尝试使用图标服务,它适用于文件,但不适用于文件夹。

我看到这种行为在 Dropbox(10.4、10.5 和 10.6)中起作用 - 怎么做?

博客文章 Cocoa Tutorial: Custom Folder Icons 对我来说非常接近,但它没有按预期工作。

除了图标服务还有其他解决方案吗?

【问题讨论】:

  • 我得到了解决方案:为文件夹中的徽章图标添加资源分支,并将其加载为文件夹图标的徽章。注意:资源分叉名称应以 '\r' 结尾
  • 您介意添加答案并展示您所做的吗?我有兴趣看看。谢谢!
  • @Dave DeLong 请在下面找到我的解决方案,传递文件夹路径你想要徽章和来自徽章图标的 NSData。如果您希望它在 PPC 中工作,则该代码仅在英特尔中工作,替换关于 PPC 的使用“NSUTF16LittleEndianStringEncoding”。希望您发现此代码有用。

标签: objective-c cocoa macos


【解决方案1】:

下面的函数是我找到的问题的解决方案

BOOL AddBadgeToItem(NSString* path,NSData* tag)

{   
    FSCatalogInfo info;
    FSRef par;
    FSRef ref;
    Boolean dir = false;

    if (tag&&(FSPathMakeRef([path fileSystemRepresentation],&par,&dir)==noErr)) 
    {
        HFSUniStr255 fork = {0,{0}};
        sint16 refnum = kResFileNotOpened;
        FSGetResourceForkName(&fork);

        if (dir) 
        {

            NSString *name = @"Icon\r";
            memset(&info,0,sizeof(info));
            ((FileInfo*)(&info.finderInfo))->finderFlags = kIsInvisible;

            OSErr error = FSCreateResourceFile(&par,[name lengthOfBytesUsingEncoding:NSUTF16LittleEndianStringEncoding],(UniChar*)[name cStringUsingEncoding:NSUTF16LittleEndianStringEncoding],kFSCatInfoFinderXInfo,&info,fork.length, fork.unicode,&ref,NULL);

            if( error == dupFNErr )
            {
                // file already exists; prepare to try to open it
                const char *iconFileSystemPath = [[path stringByAppendingPathComponent:@"\000I\000c\000o\000n\000\r"] fileSystemRepresentation];

                OSStatus status = FSPathMakeRef((const UInt8 *)iconFileSystemPath, &ref, NULL);
                if (status != noErr)
                {
                    fprintf(stderr, "error: FSPathMakeRef() returned %d for file \"%s\"\n", (int)status, iconFileSystemPath);

                }
            }else if ( error != noErr)
            {
                return NO;
            }

        } 
        else 
        {
            BlockMoveData(&par,&ref,sizeof(FSRef));
            if (FSCreateResourceFork(&ref,fork.length,fork.unicode,0)!=noErr) 
            {
                //test

                if (FSOpenResourceFile(&ref,fork.length,fork.unicode,fsRdWrPerm,&refnum)!=noErr) {
                    return NO;
                }
                if (refnum!=kResFileNotOpened) {

                    UpdateResFile(refnum);
                    CloseResFile(refnum);

                    if (FSGetCatalogInfo(&par,kFSCatInfoFinderXInfo,&info,NULL,NULL,NULL)==noErr) {
                        ((ExtendedFileInfo*)(&info.extFinderInfo))->extendedFinderFlags = kExtendedFlagsAreInvalid;
                        FSSetCatalogInfo(&par,kFSCatInfoFinderXInfo,&info);
                    }
                }

                //Test end
                return NO;
            }
        }
        OSErr errorr = FSOpenResourceFile(&ref,fork.length,fork.unicode,fsRdWrPerm,&refnum);
        if (errorr!=noErr) {
            return NO;
        }
        if (refnum!=kResFileNotOpened) {
            CustomBadgeResource* cbr;

            int len = [tag length]; 
            Handle h = NewHandle(len);
            if (h) {
                BlockMoveData([tag bytes],*h,len);
                AddResource(h,kIconFamilyType,128,"\p");
                WriteResource(h);
                ReleaseResource(h);
            }

            h = NewHandle(sizeof(CustomBadgeResource)); 
            if (h) {
                cbr = (CustomBadgeResource*)*h;
                memset(cbr,0,sizeof(CustomBadgeResource));
                cbr->version = kCustomBadgeResourceVersion;
                cbr->customBadgeResourceID = 128;
                AddResource(h,kCustomBadgeResourceType,kCustomBadgeResourceID,"\p");
                WriteResource(h);
                ReleaseResource(h);
            }

            UpdateResFile(refnum);
            CloseResFile(refnum);

            if (FSGetCatalogInfo(&par,kFSCatInfoFinderXInfo,&info,NULL,NULL,NULL)==noErr) {
                ((ExtendedFileInfo*)(&info.extFinderInfo))->extendedFinderFlags = kExtendedFlagHasCustomBadge;
                FSSetCatalogInfo(&par,kFSCatInfoFinderXInfo,&info);
            }
        }
    }
    return NO;
}

【讨论】:

  • 嗨 Girish,我正在尝试使用附件图标徽章在 finder 中标记文件夹,但到目前为止没有成功。我尝试了这段代码,但结果是文件夹中有一个名为“Icon”的文件。知道我可能做错了什么吗?谢谢!
  • @Joe Ricioppo : 作为徽章文件夹的一部分创建的图标文件资源分支。
  • @JoeRicioppo 我也面临同样的问题。代码运行没有任何错误,但没有任何反应。你是怎么解决这个问题的???
  • 还是很好奇,你们发现它有效了吗?
【解决方案2】:

您可以使用 NSWorkspace 上的 -setIcon:forFile:options: 方法来执行此操作,该方法让您只需指定一个 NSImage 以应用于您提供的路径中的文件/文件夹。

【讨论】:

    【解决方案3】:

    预期的方法是创建一个Finder Sync app extension

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-10
      • 2011-08-16
      • 2015-12-09
      • 2011-01-11
      • 1970-01-01
      • 2013-06-30
      • 1970-01-01
      • 2020-08-21
      相关资源
      最近更新 更多