Adding events to NSWindow using Cocoa and Objective-C++ - objective-c

I've seen a lot of questions, but I couldn't find anything what helped me. I've looked at many Apple developer pages, but I find those to be a bit unclear.
I want to make applications in Objective-C++ without Xcode or any other IDE that does all the work for me. My IDE is Atom, and I compile with g++. I have the following class to create a window:
//Window.mm
#ifndef WINDOW_H
#define WINDOW_H
#import "Cocoa/Cocoa.h"
class Window
{
private: NSWindow* window;
public: Window(const char* title, int x, int y, int w, int h, NSColor* bg = [NSColor colorWithCalibratedRed:0.3f green:0.3f blue:0.3f alpha:1.0f])
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
[NSApplication sharedApplication];
NSRect frame = NSMakeRect(x, y, w, h);
NSUInteger windowStyle = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable;
NSRect rect = [NSWindow contentRectForFrameRect:frame styleMask:windowStyle];
this->window = [[[NSWindow alloc] initWithContentRect:rect styleMask:windowStyle backing:NSBackingStoreBuffered defer:NO] autorelease];
[this->window makeKeyAndOrderFront: this->window];
[this->window setBackgroundColor: bg];
[this->window setTitle: [NSString stringWithUTF8String:title]];
[this->window orderFrontRegardless];
[pool drain];
[NSApp run];
}
};
#endif
From what I did understand is that I need to do something with an NSView, but I'm not sure what I'm supposed to do. How will I be able to get key input from my window?

You need to subclass NSWindow in order to receive key input events, for example:
KWCustomWindow.h:
#import <Cocoa/Cocoa.h>
#interface KWCustomWindow : NSWindow
#end
KWCustomWindow.m
#import "KWCustomWindow.h"
#implementation KWCustomWindow
- (void)keyDown:(NSEvent *)event
{
NSLog(#"Key Down");
}
#end

Related

I can't write text to NSTextField Objective C

I've spent much time finding an answer but I don't understand how right it googling.
I just need to create a simple text field. I've done it but I can't write some text.
After build and run I tried to write but the text was written in x-code window.
What's wrong?
I guess it's related to focus NSWindow or NSApplication.
It's very strange because I can call the context menu and I see cut/copy/paste functions. I even can use those but I can write text by the keyboard.
All code already in main.m
#include <Cocoa/Cocoa.h>
#interface Window : NSWindow {
NSTextField* textBox1;
NSTextField* textBox2;
}
- (instancetype)init;
- (BOOL)windowShouldClose:(id)sender;
#end
#implementation Window : NSWindow
- (instancetype)init {
NSTextField* textBox1 = [[[NSTextField alloc] initWithFrame:NSMakeRect(10, 270, 100, 20)] autorelease];
[textBox1 setStringValue:#"textBox1"];
NSTextField* textBox2 = [[[NSTextField alloc] initWithFrame:NSMakeRect(10, 230, 100, 20)] autorelease];
[textBox2 setStringValue:#"textBox2"];
[super initWithContentRect:NSMakeRect(100, 100, 300, 300)
styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable | NSWindowStyleMaskUnifiedTitleAndToolbar
backing:NSBackingStoreBuffered
defer:NO];
[self setTitle:#"TextBox Example"];
[[self contentView] addSubview:textBox1];
[[self contentView] addSubview:textBox2];
[self makeFirstResponder:textBox2];
[self setIsVisible:YES];
return self;
}
- (BOOL)windowShouldClose:(id)sender {
[NSApp terminate:sender];
return YES;
}
#end
int main(int argc, char* argv[]) {
[[[Window alloc] init] autorelease];
NSApplication *application = [NSApplication sharedApplication];
[application activateIgnoringOtherApps:YES];
[NSApp run];
}
Thank you for your help but it didn't help me... :(
I could resolve my problem.
I just added the method call setActivationPolicy.
int main(int argc, char* argv[]) {
[[[Window alloc] init] autorelease];
NSApplication *application = [NSApplication sharedApplication];
[application activateIgnoringOtherApps:YES];
[application setActivationPolicy:NSApplicationActivationPolicyRegular];
[NSApp run];
}

How to add stoplight buttons to an OS X application programmatically

I'm building an OS X cocoa application and I'm not using interface builder (for a variety of reasons). I've got the application to the point of loading a menu, title bar and main window, but I can't seem to figure out how to add the stoplight buttons to the title bar (programmatically).
My AppDelegate.m looks like this:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
MainViewController *mVC = [MainViewController new];
[mVC showMainViewController];
}
Then code in the MainViewController then creates the menu, window, and loads the application, as follows:
//
// MainViewController.m
// TestApp
//
#import "MainViewController.h"
#implementation MainViewController
#synthesize menubar;
#synthesize appMenu;
#synthesize appMenuItem;
#synthesize quitMenuItem;
#synthesize appName;
#synthesize quitTitle;
#synthesize window;
#synthesize homeViewController;
#synthesize resolutionHeight;
#synthesize resolutionWidth;
#synthesize width;
#synthesize height;
- (id)init
{
self = [super init];
if (self) {
appName = #"TestApp";
[self setupMenubar];
[self setupMainWindow];
}
return self;
}
- (void)setupMenubar
{
// Set up the main menu
menubar = [NSMenu new];
appMenu = [NSMenu new];
appMenuItem = [NSMenuItem new];
quitTitle = [NSString stringWithFormat:#"Quit %#", appName];
quitMenuItem = [[NSMenuItem alloc] initWithTitle:quitTitle
action:#selector(terminate:)
keyEquivalent:#"q"];
[menubar addItem:appMenuItem];
[appMenu addItem:quitMenuItem];
[appMenuItem setSubmenu:appMenu];
[NSApp setMainMenu:menubar];
}
- (void)setupMainWindow
{
// set the dimensions of the application
resolutionWidth = [[NSScreen mainScreen] frame].size.width;
resolutionHeight = [[NSScreen mainScreen] frame].size.height;
width = resolutionWidth * 0.75;
height = resolutionHeight * 0.75;
window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, width, height)
styleMask:NSTitledWindowMask
backing:NSBackingStoreBuffered defer:NO];
[window cascadeTopLeftFromPoint:NSMakePoint(10, 10)];
// add window buttons
closeButton = [NSWindow standardWindowButton:NSWindowCloseButton forStyleMask:NSTitledWindowMask];
// set metadata for the window
[window setTitle:appName];
[window makeKeyAndOrderFront:nil];
}
- (void)showMainViewController
{
// Set app settings
[NSApplication sharedApplication];
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
[NSApp activateIgnoringOtherApps:YES];
[NSApp run];
}
#end
I've looked around and I'm kind of at a loss for how to proceed.
You might try changing your NSWindow init method to the following:
window = [[NSWindow alloc]
initWithContentRect:NSMakeRect(0, 0, width, height)
styleMask:NSTitledWindowMask | NSClosableWindowMask |
NSMiniaturizableWindowMask | NSResizableWindowMask
backing:NSBackingStoreBuffered defer:NO];
I believe that ORing in the additional masks automatically adds the corresponding buttons to the title bar for you: NSClosableWindowMask adds the close button, NSMiniaturizableWindowMask adds the minimize (center) button, and NSResizableWindowMask adds the zoom (rightmost) button.

How do I go about handling Cocoa Events in a fullscreen application

I have been trying to create an app for Cocoa without a nib/xib (No, I don't want to use a nib/xib. I want to be in full control programatically) and I can't seem to be able to catch the Events such as keystrokes and mouse clicks. Here is the code I have so far:
Main.m
#import <Cocoa/Cocoa.h>
#import "AppDelegate.h"
int main(int argc, char *argv[])
{
#autoreleasepool {
NSApplication *app = [NSApplication sharedApplication];
AppDelegate *appDelegate = [[AppDelegate alloc] init];
[app setDelegate:appDelegate];
[app activateIgnoringOtherApps:YES];
[app run];
}
return EXIT_SUCCESS;
}
AppDelegate.h/m
#import <Cocoa/Cocoa.h>
#interface AppDelegate : NSObject <NSApplicationDelegate>
{
NSWindow *window;
}
#end
#import "AppDelegate.h"
#import "GLView.h"
#implementation AppDelegate
- (id)init{
self = [super init];
if (!self) {
return nil;
}
NSRect bounds = [[NSScreen mainScreen] frame];
GLView *view = [[GLView alloc]initWithFrame:bounds];
window = [[NSWindow alloc] initWithContentRect:bounds
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:NO];
[window setReleasedWhenClosed:YES];
[window setAcceptsMouseMovedEvents:YES];
[window setContentView:view];
return self;
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
[window makeKeyAndOrderFront:self];
}
#end
GLView.h/m
#import <Cocoa/Cocoa.h>
#interface GLView : NSView
#end
#import "GLView.h"
#implementation GLView
- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code here.
}
return self;
}
- (void)drawRect:(NSRect)dirtyRect
{
// Drawing code here.
}
- (BOOL)canBecomeKeyView
{
return YES;
}
- (BOOL)acceptsFirstResponder
{
return YES;
}
- (BOOL)becomeFirstResponder
{
return YES;
}
- (BOOL)resignFirstResponder
{
return YES;
}
- (void)keyDown:(NSEvent *)theEvent
{
NSString* const character = [theEvent charactersIgnoringModifiers];
unichar const code = [character characterAtIndex:0];
NSLog(#"Key Down: %hu", code);
switch (code)
{
case 27:
{
EXIT_SUCCESS;
break;
}
}
}
- (void)keyUp:(NSEvent *)theEvent
{
}
#end
Nothing I have tried for it has worked. I thought that by setting the view as the first responder I would be able to get the events. So far... Not working. Any ideas on how I can fix this? Remember, NO NIB.
Thanks,
Tyler
First, you need to make sure that your window can actually become key, by subclassing and returning YES from canBecomeKeyWindow, because windows without title bars cannot become key by default.
Next, your build target needs to be an application. I would guess that you're starting from the Command-Line Tool template in Xcode. This is fine, but you need to produce an application bundle in order for your app to recieve key events. Create a new target in your project that will build a Cocoa Application. It needs to have an Info.plist file (from which you'll want to delete the "Main nib file base class" entry) and have a "Copy Bundle Resources" Build Phase.
I can't quite figure out what all the other differences are in the build process, but starting from your code, I got the window to accept key events with these two steps.

NSTextField doesn't respond to keyboard input

I tried to write a single-window application using Objective-C in OS X 10.8 to test some thing. Everything works fine except that the NSTextField I created does not respond to keyboard input. The code is as follows:
#import <Cocoa/Cocoa.h>
#interface customizedView:NSView
+(customizedView *)aCustomizedView; // changed method name to follow convention
#end
#implementation customizedView
+(customizedView *)aCustomizedView{
customizedView *newView = [[[customizedView alloc] initWithFrame:NSMakeRect(0,0,400,300)] autorelease];
NSTextField *tf = [[[NSTextField alloc] initWithFrame:NSMakeRect(200,150,150,50)] autorelease];
[newView addSubview: tf positioned:NSWindowBelow relativeTo:newView];
return newView;
}
-(void)windowWillClose:(NSNotification *)aNot{
[NSApp terminate:self];
}
#end
void setup(){
NSWindow *aWindow = [[[NSWindow alloc] initWithContentRect:NSMakeRect(0,0,400,300) styleMask:NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask backing:2 defer:NO] autorelease];
customizedView *aView = [customizedView aCustomizedView];
[aWindow setContentView:aView];
[aWindow setDelegate:aView];
[aView setNeedsDisplay:YES];
[aWindow makeKeyAndOrderFront:nil];
}
int main(int argc, char **argv){
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSApplication *NSApp = [NSApplication sharedApplication];
setup();
[NSApp run]; [NSApp release]; [pool release];
exit(EXIT_SUCCESS);
}
Compile using
gcc -w filename.m -o tmp -framework Cocoa
Everything works except that I cannot input using keyboard to input into the textfield in my customized NSView. Paste using mouse is okay. So far I still have no ideal why this happens and I give my thanks in advance to all who read this tip sincerely.

get NSString from UITextField

I'm trying to write a little weightwatchers points calculator app for myself. I know you can just download one from the appstore but i am trying to learn objective-c and thought this would be a fairly easy first app. I just want to use text entered into a textbox and save it as a variable and use said variable to perform basic math with the intValues. I've tried using the 'text' property of UITextField with no luck, could someone help and tell me what i've done wrong here? well this is awkward...it seems i forgot to tell you what the problem is. i've included the errors i'm receiving on their corresponding lines. What i'm getting out of these errors is that i shouldn't be using the "NSString" to define my variables, maybe "int" instead?
.h file:
#import <UIKit/UIKit.h>
#class FirstViewController;
NSString*txtProtein = nil;
NSString *txtCarbs = nil;
NSString *txtFat = nil;
NSString *txtFiber = nil;
NSString *txtPoints = nil;
NSString *txtproteinCalc = nil;
NSString *txtcarbCalc = nil;
NSString *txtfatCalc = nil;
NSString *txtfiberCalc = nil;
#interface AppDelegate : NSObject
<UIApplicationDelegate> {
UIWindow *window;
FirstViewController
*viewController;
UITextField *protein;
UITextField *carbs;
UITextField *fat;
UITextField *fiber;
UITextView *points;
}
#property (nonatomic, retain)
IBOutlet UIWindow *window;
#property (nonatomic, retain)
IBOutlet FirstViewController *viewController;
#end
and the .m file:
#import "FirstViewController.h"
#import "AppDelegate.h"
#implementation AppDelegate
#synthesize window;
#synthesize viewController;
#pragma mark -
#pragma mark Application lifecycle
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//Here is where all of the textboxes are defined.
//All of the strings are in the viewController.h
//This is the protein part
txtProtein = [[[UITextField alloc] initWithFrame:CGRectMake(10.0, 10.0, 50.0, 25.0)]; (expected identifier)
txtProtein.backgroundColor = [UIColor whiteColor]; (property "backgroundcolor" not found on object of type 'NSString')
txtProtein.placeholder = #"Protein"; (property "placeholder" not found on object of type 'NSString')
[viewController.view addSubview:txtProtein]; (property 'view' can not be found in forward class object "FirstViewController")
//This is the carbs part
txtCarbs = [[[UITextField alloc] initWithFrame:CGRectMake(30.0, 10.0, 50.0, 25.0)];
txtCarbs.backgroundColor = [UIColor whiteColor];
txtCarbs.placeholder = #"Carbs";
[viewController.view addSubview:txtCarbs];
//This is the Fat part
txtFat = [[[UITextField alloc] initWithFrame:CGRectMake(50.0, 10.0, 50.0, 25.0)];
txtFat.backgroundColor = [UIColor whiteColor];
txtFat.placeholder = #"Fat";
[viewController.view addSubview:txtFat];
//This is the Fiber
txtFiber = [[[UITextField alloc] initWithFrame:CGRectMake(70.0, 10.0, 50.0, 25.0)];
txtFiber.backgroundColor = [UIColor whiteColor];
txtFiber.placeholder = #"Fiber";
[viewController.view addSubview:txtFiber];
//Total Points
txtPoints = [[[UITextField alloc] initWithFrame: CGRectMake(150.0, 10.0, 50.0, 25.0)]autorelease];
txtPoints.backgroundColor = [UIColor greenColor];
txtPoints.editable = NO;
[viewController.view addSubview:txtPoints];
//Protein divided by 10.9375
txtproteinCalc = [txtProtein.text intValue] / [10.9375];
//Carbs divided by 9.2105
txtcarbCalc = [txtCarbs.text intValue] / [9.2105];
//Fat divided by 3.8889
txtfatCalc = [txtFat.text intValue] / [3.8889];
//Fiber divided by 12.5
txtfiberCalc = [txtFiber.text intValue] / [12.5];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(calculatePoints)
name:UITextFieldTextDidChangeNotification
object:nil];
//Add the view controller's view to the window and display
[self.window addSubview:viewController.view];
[self.window makeKeyAndVisible];
//Make keyboard show up in the Protein (The first) box
[txtProtein becomeFirstResponder];
return YES;
}
#pragma mark -
#pragma mark Memory management
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
/*
Free up as much Memory as possible by purging cached data objects that can be recreated (or reloaded from disk) later/
*/
}
-(void)dealloc {
[txtProtein release];
[txtFiber release];
[txtFat release];
[txtCarbs release];
[txtPoints release];
[viewController release];
[window release];
[super dealloc];
}
#pragma mark -
#pragma mark Other Methods
-(void)calculatePoints {
NSLog(#"Calculating FoodTrakr Value...");
txtPoints.text = #"";
if (txtProtein.text.length > 0 && [txtProtein.text intValue]>0 && txtFiber.text.length >0 && [txtFiber.text intValue]>0 && txtFat.text.length >0 && [txtFat.text intValue]>0 && txtCarbs.text.length >0 && [txtCarbs.text intValue]>0
)
{
int Points = [txtproteinCalc.text intValue] + [txtcarbCalc.text intValue] + [txtfatCalc.text intValue] - [txtfiberCalc.text intValue];
txtPoints.text = [[NSNumber numberWithInt:points] stringValue];
}
}
#end
Thanks in advance for any help!
also, if you guys have any recommended books for learning objective c, i've done some reading but i know i obviously need to read up some more, if you could leave any suggestions that helped you learn that would be awesome. Thanks!
To be blunt, the posted code has a lot of serious issues. Let's start with the immediate compile errors.
You have:
txtProtein = [[[UITextField alloc] initWithFrame:CGRectMake(10.0, 10.0, 50.0, 25.0)]; (expected identifier)
txtProtein.backgroundColor = [UIColor whiteColor]; (property "backgroundcolor" not found on object of type 'NSString')
txtProtein.placeholder = #"Protein"; (property "placeholder" not found on object of type 'NSString')
[viewController.view addSubview:txtProtein]; (property 'view' can not be found in forward class object "FirstViewController")
The first line has one too many open brackets. The other major problem with this is you are creating a UITextField but you are assigning it to a variable for an NSString. Instead of txtProtein you should use your protein variable which has the property type. So the code should be:
protein = [[UITextField alloc] initWithFrame:CGRectMake(10.0, 10.0, 50.0, 25.0)];
protein.backgroundColor = [UIColor whiteColor];
protein.placeholder = #"Protein";
[viewController.view addSubview:protein];
You have the same issues repeated over and over in this code.
The next big issue is why is all of this code in your app delegate? Most, if not all, of this code belongs in the FirstViewController.m file. Your app delegate should not be responsible for setting up the view controller. Let the view controller set itself up.
Next, why do you have all of these global variables?
I suggest you find some good tutorials on Objective-C programming then some good tutorials on iOS app development.