我的问题是…如何计算这个位置,就像这个应用程序一样放置你的NSWindow的位置?
我已经尝试过以下内容:
>子类NSMenu
>设置菜单的第一个项目的视图poedy(工作但足够)
>使用addSubvIEw而不是NsstatusItem的图标这个工作,但不能高于20px
以这种方式执行它可能看起来很疯狂,但是速度相对较小,这是找到没有未记录API的状态项的唯一方法.
如果您传递状态项目的当前图像,此方法应该找到它.
@implementation NSScreen (LTStatusItemLocator)// Find the location of img on the screen's status bar.// If the image is not found,returns NSZeroPoint- (NSPoint)originofStatusItemWithImage:(NSImage *)img{ CGcolorSpaceRef csK = CGcolorSpaceCreateDeviceGray(); NSPoint ret = NSZeroPoint; CGDirectdisplayID screenID = 0; CGImageRef displayimg = NulL; CGImageRef compareimg = NulL; CGRect screenRect = CGRectZero; CGRect barRect = CGRectZero; uint8_t *bm_bar = NulL; uint8_t *bm_bar_ptr; uint8_t *bm_compare = NulL; uint8_t *bm_compare_ptr; size_t bm_compare_w,bm_compare_h; BOol inverted = NO; int numberOfScanlines = 0; CGfloat *meanValues = NulL; int presumptiveMatchIDx = -1; CGfloat presumptiveMatchMeanVal = 999; // If the computer is set to Dark Mode,set the "inverted" flag NSDictionary *globalPrefs = [[NSUserDefaults standardUserDefaults] persistentDomainForname:NSGlobalDomain]; ID style = globalPrefs[@"AppleInterfaceStyle"]; if ([style isKindOfClass:[Nsstring class]]) { inverted = (NSOrderedSame == [style caseInsensitiveCompare:@"dark"]); } screenID = (CGDirectdisplayID)[self.deviceDescription[@"NSScreenNumber"] integerValue]; screenRect = CGdisplayBounds(screenID); // Get the menubar rect barRect = CGRectMake(0,screenRect.size.wIDth,22); displayimg = CGdisplayCreateImageForRect(screenID,barRect); if (!displayimg) { NSLog(@"Unable to create image from display"); CGcolorSpaceRelease(csK); return ret; // I would normally use goto(bail) here,but this is public code so let's not ruffle any feathers } size_t bar_w = CGImageGetWIDth(displayimg); size_t bar_h = CGImageGetHeight(displayimg); // Determine scale factor based on the CGImageRef we got back from the display CGfloat scaleFactor = (CGfloat)bar_h / (CGfloat)22; // Greyscale bitmap for menu bar bm_bar = malloc(1 * bar_w * bar_h); { CGContextRef bmCxt = NulL; bmCxt = CGBitmapContextCreate(bm_bar,bar_w,bar_h,8,1 * bar_w,csK,kCGBitmapAlphaInfoMask&kCGImageAlphaNone); // Draw the menu bar in grey CGContextDrawImage(bmCxt,CGRectMake(0,bar_h),displayimg); uint8_t minVal = 0xff; uint8_t maxVal = 0x00; // Walk the bitmap uint64_t running = 0; for (int yi = bar_h / 2; yi == bar_h / 2; yi++) { bm_bar_ptr = bm_bar + (bar_w * yi); for (int xi = 0; xi < bar_w; xi++) { uint8_t v = *bm_bar_ptr++; if (v < minVal) minVal = v; if (v > maxVal) maxVal = v; running += v; } } running /= bar_w; uint8_t threshold = minVal + ((maxVal - minVal) / 2); //threshold = running; // Walk the bitmap bm_bar_ptr = bm_bar; for (int yi = 0; yi < bar_h; yi++) { for (int xi = 0; xi < bar_w; xi++) { // Threshold all the pixels. Values > 50% go white,values <= 50% go black // (opposite if Dark Mode) // Could unroll this loop as an optimization,but probably not worthwhile *bm_bar_ptr = (*bm_bar_ptr > threshold) ? (inverted?0x00:0xff) : (inverted?0xff:0x00); bm_bar_ptr++; } } CGImageRelease(displayimg); displayimg = CGBitmapContextCreateImage(bmCxt); CGContextRelease(bmCxt); } { CGContextRef bmCxt = NulL; CGImageRef img_cg = NulL; bm_compare_w = scaleFactor * img.size.wIDth; bm_compare_h = scaleFactor * 22; // Create out comparison bitmap - the image that was passed in bmCxt = CGBitmapContextCreate(NulL,bm_compare_w,bm_compare_h,1 * bm_compare_w,kCGBitmapAlphaInfoMask&kCGImageAlphaNone); CGContextSetBlendMode(bmCxt,kCGBlendModenormal); NSRect imgRect_og = NSMakeRect(0,img.size.wIDth,img.size.height); NSRect imgRect = imgRect_og; img_cg = [img CGImageForProposedRect:&imgRect context:nil hints:nil]; CGContextClearRect(bmCxt,imgRect); CGContextSetFillcolorWithcolor(bmCxt,[NScolor whitecolor].CGcolor); CGContextFillRect(bmCxt,9999,9999)); CGContextScaleCTM(bmCxt,scaleFactor,scaleFactor); CGContextTranslateCTM(bmCxt,(22. - img.size.height) / 2.); // Draw the image in grey CGContextSetFillcolorWithcolor(bmCxt,[NScolor blackcolor].CGcolor); CGContextDrawImage(bmCxt,imgRect,img_cg); compareimg = CGBitmapContextCreateImage(bmCxt); CGContextRelease(bmCxt); } { // We start at the right of the menu bar,and scan left until we find a good match int numberOfScanlines = barRect.size.wIDth - img.size.wIDth; bm_compare = malloc(1 * bm_compare_w * bm_compare_h); // We use the meanValues buffer to keep track of how well the image matched for each point in the scan meanValues = calloc(sizeof(CGfloat),numberOfScanlines); // Walk the menubar image from right to left,pixel by pixel for (int scanx = 0; scanx < numberOfScanlines; scanx++) { // Optimization,if we recently found a really good match,bail on the loop and return it if ((presumptiveMatchIDx >= 0) && (scanx > (presumptiveMatchIDx + 5))) { break; } CGfloat xOffset = numberOfScanlines - scanx; CGRect displayRect = CGRectMake(xOffset * scaleFactor,img.size.wIDth * scaleFactor,22. * scaleFactor); CGImageRef displayCrop = CGImageCreateWithImageInRect(displayimg,displayRect); CGContextRef compareCxt = CGBitmapContextCreate(bm_compare,kCGBitmapAlphaInfoMask&kCGImageAlphaNone); CGContextSetBlendMode(compareCxt,kCGBlendModecopy); // Draw the image from our menubar CGContextDrawImage(compareCxt,22. * scaleFactor),displayCrop); // Blend mode difference is like an XOR CGContextSetBlendMode(compareCxt,kCGBlendModeDifference); // Draw the test image. Because of blend mode,if we end up with a black image we matched perfectly CGContextDrawImage(compareCxt,compareimg); CGContextFlush(compareCxt); // Walk through the result image,to determine overall blackness bm_compare_ptr = bm_compare; for (int i = 0; i < bm_compare_w * bm_compare_h; i++) { meanValues[scanx] += (CGfloat)(*bm_compare_ptr); bm_compare_ptr++; } meanValues[scanx] /= (255. * (CGfloat)(bm_compare_w * bm_compare_h)); // If the image is very dark,it matched well. If the average pixel value is < 0.07,we consIDer this // a presumptive match. Mark it as such,but continue looking to see if there's an even better match. if (meanValues[scanx] < 0.07) { if (meanValues[scanx] < presumptiveMatchMeanVal) { presumptiveMatchMeanVal = meanValues[scanx]; presumptiveMatchIDx = scanx; } } CGImageRelease(displayCrop); CGContextRelease(compareCxt); } } // After we're done scanning the whole menubar (or we bailed because we found a good match),// return the origin point. // If we dIDn't match well enough,return NSZeroPoint if (presumptiveMatchIDx >= 0) { ret = CGPointMake(CGRectGetMaxX(self.frame),CGRectGetMaxY(self.frame)); ret.x -= (img.size.wIDth + presumptiveMatchIDx); ret.y -= 22; } CGImageRelease(displayimg); CGImageRelease(compareimg); CGcolorSpaceRelease(csK); if (bm_bar) free(bm_bar); if (bm_compare) free(bm_compare); if (meanValues) free(meanValues); return ret;}@end总结
以上是内存溢出为你收集整理的objective-c – 如何获取NSStatusItem的屏幕位置全部内容,希望文章能够帮你解决objective-c – 如何获取NSStatusItem的屏幕位置所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)