首先,我必须告诉您,我是Objective-C和Cocoa的新手。
我已经阅读了一些关于这方面的书籍,并且现在能够构建相当简单的程序。
我已经卡在一个程序上15天了,我正在尝试构建它,但我真的不知道该去哪里寻找更多信息。
我想构建一个可以使用DDC/CI改变我的显示器亮度的程序,并且我想显示/隐藏一个窗口(其中写有亮度级别),就像Leopard或Snow Leopard的苹果亮度簸箕一样,具有完全相同的样式。
使用RegisterEventHotKey和各种IOservices函数,我已经能够在按下F2时增加亮度,在按下F1时降低亮度。
使用自定义NSWindow(TransparentWindow)和自定义NSView(RoundedView),我已经能够获得与苹果亮度簸箕完全相同的窗口。我将其放在awakeFromNib中,它会正确地显示并保留在那里。
我无法实现的是仅在按下F1或F2时显示窗口(我已经实现了一个NSTimer来隐藏它,但现在不是重点)。
我尝试了不同的方式:
1) 从NSObject类中,我实现了RegisterEventHotKey,并创建了一个TransparentWindow实例,然后向该实例发送orderOut。
2) 我使用NSNotificationCenter直接向TransparentWindow类发送通知,并从那里调用orderOut。
3) 还有许多我现在不记得的方式。
现在我正在尝试通过在awakeFromNib中创建窗口(这可以工作),然后使用orderOut将其隐藏(这从未起作用)来使窗口出现。
这些是涉及的类:
TransparentWindow.h:
我已经阅读了一些关于这方面的书籍,并且现在能够构建相当简单的程序。
我已经卡在一个程序上15天了,我正在尝试构建它,但我真的不知道该去哪里寻找更多信息。
我想构建一个可以使用DDC/CI改变我的显示器亮度的程序,并且我想显示/隐藏一个窗口(其中写有亮度级别),就像Leopard或Snow Leopard的苹果亮度簸箕一样,具有完全相同的样式。
使用RegisterEventHotKey和各种IOservices函数,我已经能够在按下F2时增加亮度,在按下F1时降低亮度。
使用自定义NSWindow(TransparentWindow)和自定义NSView(RoundedView),我已经能够获得与苹果亮度簸箕完全相同的窗口。我将其放在awakeFromNib中,它会正确地显示并保留在那里。
我无法实现的是仅在按下F1或F2时显示窗口(我已经实现了一个NSTimer来隐藏它,但现在不是重点)。
我尝试了不同的方式:
1) 从NSObject类中,我实现了RegisterEventHotKey,并创建了一个TransparentWindow实例,然后向该实例发送orderOut。
2) 我使用NSNotificationCenter直接向TransparentWindow类发送通知,并从那里调用orderOut。
3) 还有许多我现在不记得的方式。
现在我正在尝试通过在awakeFromNib中创建窗口(这可以工作),然后使用orderOut将其隐藏(这从未起作用)来使窗口出现。
这些是涉及的类:
TransparentWindow.h:
#import <Cocoa/Cocoa.h>
@interface TransparentWindow : NSWindow
{
IBOutlet NSWindow *window;
}
@property (retain) IBOutlet NSWindow *window;
@end
TransparentWindow.m:
#import "TransparentWindow.h"
@implementation TransparentWindow
@synthesize window;
- (id)initWithContentRect:(NSRect)contentRect
styleMask:(unsigned int)aStyle
backing:(NSBackingStoreType)bufferingType
defer:(BOOL)flag {
window = [super initWithContentRect:contentRect
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:NO];
if (window != nil) {
[window setLevel: NSStatusWindowLevel];
[window setBackgroundColor: [NSColor clearColor]];
[window setAlphaValue:1.0];
[window setOpaque:NO];
[window setHasShadow:NO];
[window setIgnoresMouseEvents: YES];
NSLog(@"%p", window);
}
return window;
}
- (BOOL) canBecomeKeyWindow
{
return YES;
}
- (void)notify {
[[NSNotificationCenter defaultCenter] postNotificationName:@"MyNotification" object:self];
}
- (void)handleNotification:(NSNotification*)note {
[window orderOut:self];
}
@end
RoundedView.h:
#import <Cocoa/Cocoa.h>
@interface RoundedView : NSView
{
}
@end
RoundedView.m:
#import "RoundedView.h"
@implementation RoundedView
- (void)drawRect:(NSRect)rect
{
NSColor *bgColor = [NSColor colorWithCalibratedWhite:0.0 alpha:0.25];
NSRect bgRect = rect;
int minX = NSMinX(bgRect);
int midX = NSMidX(bgRect);
int maxX = NSMaxX(bgRect);
int minY = NSMinY(bgRect);
int midY = NSMidY(bgRect);
int maxY = NSMaxY(bgRect);
float radius = 20.0; // correct value to duplicate Panther's App Switcher
NSBezierPath *bgPath = [NSBezierPath bezierPath];
// Bottom edge and bottom-right curve
[bgPath moveToPoint:NSMakePoint(midX, minY)];
[bgPath appendBezierPathWithArcFromPoint:NSMakePoint(maxX, minY)
toPoint:NSMakePoint(maxX, midY)
radius:radius];
// Right edge and top-right curve
[bgPath appendBezierPathWithArcFromPoint:NSMakePoint(maxX, maxY)
toPoint:NSMakePoint(midX, maxY)
radius:radius];
// Top edge and top-left curve
[bgPath appendBezierPathWithArcFromPoint:NSMakePoint(minX, maxY)
toPoint:NSMakePoint(minX, midY)
radius:radius];
// Left edge and bottom-left curve
[bgPath appendBezierPathWithArcFromPoint:bgRect.origin
toPoint:NSMakePoint(midX, minY)
radius:radius];
[bgPath closePath];
[bgColor set];
[bgPath fill];
}
MainProgram.h:
#import <Cocoa/Cocoa.h>
#import <carbon/carbon.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <IOKit/IOKitLib.h>
#include <ApplicationServices/ApplicationServices.h>
#include <IOKit/i2c/IOI2CInterface.h>
@interface MainProgram : NSObject {
}
@end
MainProgram.m:
#import "MainProgram.h"
#import <Carbon/Carbon.h>
#import "TransparentWindow.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <IOKit/IOKitLib.h>
#include <ApplicationServices/ApplicationServices.h>
#include <IOKit/i2c/IOI2CInterface.h>
static OSStatus OnHotKeyEvent(EventHandlerCallRef nextHandler,EventRef theEvent,void *userData);
extern int level;
@implementation MainProgram
- (void)awakeFromNib
{
EventHotKeyRef gMyHotKeyRef;
EventHotKeyID gMyHotKeyID;
EventTypeSpec eventType;
eventType.eventClass=kEventClassKeyboard;
eventType.eventKind=kEventHotKeyPressed;
InstallApplicationEventHandler(&OnHotKeyEvent, 1, &eventType, NULL, NULL);
gMyHotKeyID.signature='htk1';
gMyHotKeyID.id=1;
//RegisterEventHotKey(122, controlKey, gMyHotKeyID, GetApplicationEventTarget(), 0, &gMyHotKeyRef);
RegisterEventHotKey(122, NULL, gMyHotKeyID, GetApplicationEventTarget(), 0, &gMyHotKeyRef);
gMyHotKeyID.signature='htk2';
gMyHotKeyID.id=2;
RegisterEventHotKey(120, NULL, gMyHotKeyID, GetApplicationEventTarget(), 0, &gMyHotKeyRef);
}
OSStatus OnHotKeyEvent(EventHandlerCallRef nextHandler,EventRef theEvent,
void *userData)
{
EventHotKeyID hkCom;
GetEventParameter(theEvent,kEventParamDirectObject,typeEventHotKeyID,NULL,
sizeof(hkCom),NULL,&hkCom);
int l = hkCom.id;
switch (l) {
case 1:
//NSLog(@"Hotkey 1");
level = level - 5;
if (level<0) {
level = 0;
}
else {
BrightnessMain(level);
}
break;
case 2:
//NSLog(@"Hotkey 2");
level = level + 5;
if (level>100) {
level = 100;
}
else {
BrightnessMain(level);
TransparentWindow *object3 = [[TransparentWindow alloc] init];
//[object3 orderOut:nil];
[[NSNotificationCenter defaultCenter] addObserver:object3 selector:@selector(handleNotification:) name:@"MyNotification" object:nil];
[object3 notify];
}
break;
}
return noErr;
}
@end
哪里出错了? 我不是一个专业的程序员,但我认为这可能是一个愚蠢而简单的错误,但我无法找出来。
MainProgram.m的更新:
我已经用这个替换了
TransparentWindow *object3 = [[TransparentWindow alloc] init]
;
用这个代替:
NSRect contentRect;
NSSize contentSize;
contentSize.width = 210;
contentSize.height = 205;
contentRect.origin = NSMakePoint(855, 140);
contentRect.size = contentSize;
TransparentWindow *object3 = [[TransparentWindow alloc] initWithContentRect:contentRect
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:NO];
我不确定这是否是您的意思...
修正后的TransparentWindow.h:
#import <Cocoa/Cocoa.h>
@interface TransparentWindow : NSWindow
{
}
@end
已更正的TransparentWindow.m文件:
#import "TransparentWindow.h"
@implementation TransparentWindow
- (id)initWithContentRect:(NSRect)contentRect
styleMask:(unsigned int)aStyle
backing:(NSBackingStoreType)bufferingType
defer:(BOOL)flag {
self = [super initWithContentRect:contentRect
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:NO];
if (self != nil) {
[self setLevel: NSStatusWindowLevel];
[self setBackgroundColor: [NSColor clearColor]];
[self setAlphaValue:1.0];
[self setOpaque:NO];
[self setHasShadow:NO];
[self setIgnoresMouseEvents: YES];
NSLog(@"%p", self);
}
return self;
}
- (BOOL) canBecomeKeyWindow
{
return YES;
}
- (void)notify {
[[NSNotificationCenter defaultCenter] postNotificationName:@"MyNotification" object:self];
}
- (void)handleNotification:(NSNotification*)note {
[self orderOut:self];
}
@end
更新2:
如果我使用makeKeyAndOrderFront而不是orderFront,就会发生一件非常奇怪的事情。
在按下F1或F2按钮的前3或4次之后,什么都不会发生,但当我再次按下F1或F2时,仍然没有窗口出现,但我会在控制台中获得这些奇怪的错误信息:
RoundedFloatingPanel[2346] <Warning>: CGSResolveShmemReference : window.RO.dirtyRegion : Reference offset (38464) exceeds bounds (32768) on shmem obj 0x229
RoundedFloatingPanel[2346] <Warning>: CGSResolveShmemReference : window.RO : Reference offset (38144) exceeds bounds (32768) on shmem obj 0x229
RoundedFloatingPanel[2346] <Error>: kCGErrorFailure: CGSNewWindowWithOpaqueShape: Cannot map window information shmem
RoundedFloatingPanel[2346] <Error>: kCGErrorFailure: Set a breakpoint @ CGErrorBreakpoint() to catch errors as they are logged.
2011-02-17 16:01:42.895 RoundedFloatingPanel[2346:a0f] HIToolbox: ignoring exception 'Error (1000) creating CGSWindow' that raised inside Carbon event dispatch
(
0 CoreFoundation 0x91f186ba __raiseError + 410
1 libobjc.A.dylib 0x999e3509 objc_exception_throw + 56
2 CoreFoundation 0x91f183e8 +[NSException raise:format:arguments:] + 136
3 CoreFoundation 0x91f1835a +[NSException raise:format:] + 58
4 AppKit 0x93408915 _NXCreateWindow + 316
5 AppKit 0x93408720 _NSCreateWindow + 59
6 AppKit 0x93407946 -[NSWindow _commonAwake] + 1784
7 AppKit 0x9340456e -[NSWindow _commonInitFrame:styleMask:backing:defer:] + 1524
8 AppKit 0x934031c1 -[NSWindow _initContent:styleMask:backing:defer:contentView:] + 1568
9 AppKit 0x93402b9b -[NSWindow initWithContentRect:styleMask:backing:defer:] + 71
10 RoundedFloatingPanel 0x000029a6 -[TransparentWindow initWithContentRect:styleMask:backing:defer:] + 119
11 RoundedFloatingPanel 0x000031ec OnHotKeyEvent + 447
12 HIToolbox 0x95ff0ecf _ZL23DispatchEventToHandlersP14EventTargetRecP14OpaqueEventRefP14HandlerCallRec + 1567
13 HIToolbox 0x95ff0196 _ZL30SendEventToEventTargetInternalP14OpaqueEventRefP20OpaqueEventTargetRefP14HandlerCallRec + 411
14 HIToolbox 0x95fefff5 SendEventToEventTargetWithOptions + 58
15 HIToolbox 0x96024c18 _ZL29ToolboxEventDispatcherHandlerP25OpaqueEventHandlerCallRefP14OpaqueEventRefPv + 3006
16 HIToolbox 0x95ff1320 _ZL23DispatchEventToHandlersP14EventTargetRecP14OpaqueEventRefP14HandlerCallRec + 2672
17 HIToolbox 0x95ff0196 _ZL30SendEventToEventTargetInternalP14OpaqueEventRefP20OpaqueEventTargetRefP14HandlerCallRec + 411
18 HIToolbox 0x96012a07 SendEventToEventTarget + 52
19 AppKit 0x93460c3e -[NSApplication sendEvent:] + 7494
20 AppKit 0x933f42a7 -[NSApplication run] + 917
21 AppKit 0x933ec2d9 NSApplicationMain + 574
22 RoundedFloatingPanel 0x00002368 main + 30
23 RoundedFloatingPanel 0x0000231e start + 54
24 ??? 0x00000001 0x0 + 1
order...:
即可。那应该可以工作。 - YujiorderOut:
发送到在nib内创建的TransparentWindow类的特定实例。 - Yuji[window setLevel: NSScreenSaverWindowLevel]
和[window setCollectionBehavior:NSWindowCollectionBehaviorStationary]
解决了这个问题。 非常感谢! - Andrea3000