OSX keyboard shortcut background application, how to - macos

I want my OSX application to sit in the background and wait for a keyboard shortcut to go into action. It should be configurable similar to Growl in the preferences, or accessible as dropbox in the statusbar.
What kind of xcode template do I have to use?
How do I capture keyboard shortcuts globally?

Have a look at Dave DeLong's DDHotKey class on GitHub.
DDHotKey is an easy-to-use Cocoa class for registering an application to respond to system key events, or "hotkeys".
A global hotkey is a key combination that always executes a specific action, regardless of which app is frontmost. For example, the Mac OS X default hotkey of "command-space" shows the Spotlight search bar, even if Finder is not the frontmost application.
A generous licence as well.

If you want to access it in preferences, use the Preference Pane template. If you want it in the status bar, create a normal application, set the LSUIElement key to 1 in Info.plist, and use NSStatusItem to create the item.
To capture shortcuts globally, you need to include the Carbon framework also. Use RegisterEventHotKey and UnregisterEventHotKey to register for the events.
OSStatus HotKeyEventHandlerProc(EventHandlerCallRef inCallRef, EventRef ev, void* inUserData) {
OSStatus err = noErr;
if(GetEventKind(ev) == kEventHotKeyPressed) {
[(id)inUserData handleKeyPress];
} else if(GetEventKind(ev) == kEventHotKeyReleased) {
[(id)inUserData handleKeyRelease];
} else err = eventNotHandledErr;
return err;
}
//EventHotKeyRef hotKey; instance variable
- (void)installEventHandler {
static BOOL installed = NO;
if(installed) return;
installed = YES;
const EventTypeSpec hotKeyEvents[] = {{kEventClassKeyboard,kEventHotKeyPressed},{kEventClassKeyboard,kEventHotKeyReleased}};
InstallApplicationEventHandler(NewEventHandlerUPP(HotKeyEventHandlerProc),GetEventTypeCount(hotKeyEvents),hotKeyEvents,(void*)self,NULL);
}
- (void)registerHotKey {
[self installEventHandler];
UInt32 virtualKeyCode = ?; //The virtual key code for the key
UInt32 modifiers = cmdKey|shiftKey|optionKey|controlKey; //remove the modifiers you don't want
EventHotKeyID eventID = {'abcd','1234'}; //These can be any 4 character codes. It can be used to identify which key was pressed
RegisterEventHotKey(virtualKeyCode,modifiers,eventID,GetApplicationEventTarget(),0,(EventHotKeyRef*)&hotKey);
}
- (void)unregisterHotKey {
if(hotkey) UnregisterEventHotKey(hotKey);
hotKey = 0;
}
- (void)handleHotKeyPress {
//handle key press
}
- (void)handleHotKeyRelease {
//handle key release
}

Related

Which Windows API in C++ will help me in identifying which Dialog Class the Current ComboBox is using?

How can I know that for a particular ComboBox which Dialog Style is being used? Is there any Win32 API which can give me that information?
I am using CDialog for a few ComboBox, CDialogEx for some, and an in-house Dialog class, let's say Ctl3dDialogEx, for others. GetClassName() will return the Class name of the ComboBox (if I am passing a ComboBox Handler) which can be "CComboBox".
Is there any Win32 API where I will pass the ComboBox Handler and it will return back to me the Dialog class name, for eg : "CDialog", "CDialogEx", "Ctl3dDialogEx", etc?
Below code will help to understand maybe:
void ComboBox_DoSomeManipulation( HWND hldg , int n )
{
/*"hldg" is the handler of the Current ComBobox */
LPTSTR lpClassName;
int nMaxCount = 256;
/*This will return "CComboBox" as value in lpClassName */
GetClassName(hldg , lpClassName , _count_of(nMaxCount));
/*Is there any WIN API like above which can give */
/* Dialog class information like CDialog, CDialogEx */
/* which the ComboBox is using ? */
}
If your combo-box can somehow get hold of a genuine pointer to its parent window, then you can use dynamic_cast<CDialogEx*>(pParent) to see if it's CDialogEx (returns nullptr if not). You will need several separate checks, starting from the most derived class! So, if your Ctl3dDialogEx is derived from CDialogEx, then:
. . .
CWnd *pParent = pCombo->GetParent(); // This, as is, is not valid code!
if (dynamic_cast<Ctl3dDialogEx*>(pParent) != nullptr) {
// It's a Ctl3dDialogEx parent
}
else if (dynamic_cast<CDialogEx*>(pParent) != nullptr) {
// It's a CDialogEx
}
else { // Assuming no other options …
// It's a CDialog
}
I would recommend making an accessible (static?) copy of the parent window's this pointer during initialisation, if you can. But there are other ways …
For example, assuming you have control over the definition of ComboBox_DoSomeManipulation and when it's called, change the first argument from an HWND to a CWnd* and, when you call it, use this rather than this->m_hwnd. (But this depends on the structure of your code!)
There is no Windows API help since all those dialogs will be subclassing the Windows DIALOG class. If this is all in process, and you are using the same MFC instance, you might be able to do this:
CWnd* pWnd = CWnd::FromHandlePermanent(hdlg);
if (pWnd != NULL)
{
if (pWnd->GetRuntimeClass() == RUNTIME_CLASS(CDialog))
{
}
else if (pWnd->GetRuntimeClass() == RUNTIME_CLASS(CDialogEx))
{
}
else if (pWnd->GetRuntimeClass() == RUNTIME_CLASS(CDialogxyz))
{
}
}
Back in the old days, MS compilers used with MFC didn't play well with dynamic_cast<>, so generally, when using MFC, I don't use it. I probably should have more trust in it, but I was stuck using Visual C++ 6 until 2008, so I am probably a little jaded. The more "standard" "MFC way" is to use the MFC macros...
Another possible ways is something like:
if (CDialogxyz* pDlgxyz = DYNAMIC_DOWNCAST(CDialogxyz, pWnd))
{
}
else if (CDialogEx* pDlgEx = DYNAMIC_DOWNCAST(CDialogEx, pWnd))
{
}
else if (CDialog* pDlg = DYNAMIC_DOWNCAST(CDialog, pWnd))
{
}

macOS: Is there any way to know when the user has tried to quit an application via its Dock icon?

Is there any way for a Cocoa application to detect when the user has tried to quit it via its Dock menu, and not by some other method?
Normally it's possible to catch and respond to quit events using the application delegate's applicationShouldTerminate: method. However, this method doesn't seem to distinguish between the request to quit coming from the application's main menu, from its Dock icon, from an Apple event, or any other conventional method of quitting the application. I'm curious if there's any way to know precisely how the user has tried to quit the application.
It is in fact possible for an app to know the reason why it's quitting by checking to see if there is current AppleEvent being handled and, if so, checking to see whether it's a quit event and whether it was the Dock that sent it. (See this thread discussing how to tell if an app is being quit because the system is logging out or shutting down.)
Here is an example of a method that, when called from the application delegate's applicationShouldTerminate: method, will return true if the app is being quit via the Dock:
- (bool)isAppQuittingViaDock {
NSAppleEventDescriptor *appleEvent = [[NSAppleEventManager sharedAppleEventManager] currentAppleEvent];
if (!appleEvent) {
// No Apple event, so the app is not being quit by the Dock.
return false;
}
if ([appleEvent eventClass] != kCoreEventClass || [appleEvent eventID] != kAEQuitApplication) {
// Not a 'quit' event
return false;
}
NSAppleEventDescriptor *reason = [appleEvent attributeDescriptorForKeyword:kAEQuitReason];
if (reason) {
// If there is a reason for this 'quit' Apple event (such as the current user is logging out)
// then it didn't occur because the user quit the app through the Dock.
return false;
}
pid_t senderPID = [[appleEvent attributeDescriptorForKeyword:keySenderPIDAttr] int32Value];
if (senderPID == 0) {
return false;
}
NSRunningApplication *sender = [NSRunningApplication runningApplicationWithProcessIdentifier:senderPID];
if (!sender) {
return false;
}
return [#"com.apple.dock" isEqualToString:[sender bundleIdentifier]];
}

Is there a Keyboard Shortcut to Focus on a Known Tabindex

When a Windows Form has the focus you can step through any Controls that have their TabStop Property set True, in Tabindex Order, by pressing the {TAB} Key.
Similarly, you can step through them in reverse order using {Shift+ TAB}
Is there any Keyboard Shortcut to move the Focus to a Known, or Absoulte, Tabindex (for example the Lowest or Highest), rather than moving it Relative to the Active Control?
If so does MS document this anywhere?
There's nothing out of the box to do this, AFAIK. You'd need to do it yourself. However, it's not that difficult, you just need to check for a hotkey by overriding the ProcessCmdKey method and then call Control.Focus() for the appropriate control:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == (Keys.Control | Keys.D1))
{
textBox1.Focus();
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
You can even take it a step further to have shortcuts for several controls and also have the ability to manage the controls and their shortcuts at run-time by having a dictionary that holds the shortcuts and the controls to be focused:
Dictionary<Keys, Control> FocusShortcuts;
public Form1()
{
InitializeComponent();
FocusShortcuts = new Dictionary<Keys, Control>();
FocusShortcuts.Add(Keys.Control | Keys.D1, textBox1);
FocusShortcuts.Add(Keys.Control | Keys.D2, textBox2);
FocusShortcuts.Add(Keys.Control | Keys.D3, textBox3);
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
Control control;
if (FocusShortcuts.TryGetValue(keyData, out control))
{
control.Focus();
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
Update
If instead, you want to set the focus to a control by its Tab Order, you can replace textBox1.Focus(); with something like this:
int someIndex = 5;
Control control = this.Controls.OfType<Control>()
.FirstOrDefault(c => c.TabIndex == someIndex);
if (control != null) control.Focus();
You'd just need to change the value of someIndex to the index of your choice and change this with the control's container (you can leave it if the container is the current form/UserControl).

Quick use of MASShortcut framework on Swift project

I am having trouble implementing MASShortcut (docs here) in a Swift OSX project to listen for global hotkeys. I have managed to import the framework via CocoaPods, and I have a working MASShortcutView instance:
#IBOutlet weak var testShortcutView:MASShortcutView!
I also figured out how to monitor and trigger something with the shortcut (please tell me if this is correct):
let shortcut = MASShortcut(keyCode: keycode, modifierFlags: modifierkeys)
MASShortcutMonitor.sharedMonitor().registerShortcut(shortcut, withAction: callback)
The question here is, how can I get the keyCode and modifierFlags from my MASShortcutView?
I really thank you in advance, I searched everywhere and I can't find an example on how to do this on swift. All I can find is is objective-c, and I can't figure it out.
Following code will register shortcut handler for Cmd+Shift+K key combination
let shortcut = MASShortcut.init(keyCode: UInt(kVK_ANSI_K), modifierFlags: UInt(NSEventModifierFlags.CommandKeyMask.rawValue + NSEventModifierFlags.ShiftKeyMask.rawValue))
MASShortcutMonitor.sharedMonitor().registerShortcut(shortcut, withAction: {
print("Hello world")
})
Cmd and Shift - modifing keys. You should set them in the modifierFlags parameters. Full list of possible values is available in NSEventModifierFlags enum.
For your convenience I have placed sample project on github:
https://github.com/melifaro-/ShortCutSwiftSample
That handles shortcuts changes:
shortcutView.shortcutValueChange = { (sender) in
let callback: (() -> Void)!
if self.shortcutView.shortcutValue.keyCodeStringForKeyEquivalent == "k" {
callback = {
print("K shortcut handler")
}
} else {
callback = {
print("Default handler")
}
}
MASShortcutMonitor.sharedMonitor().registerShortcut(self.shortcutView.shortcutValue, withAction: callback)
}
I have pushed changes into the repo. I would recommend to try following scenario:
Using the shortcut view:
Set Cmd+Shift+K shortcut
Set Cmd+Shift+J shortcut
Try this shortcuts - different callbacks should be performed
Hope it helps.
In Swift 5
let shortcut = MASShortcut(keyCode: kVK_ANSI_K, modifierFlags: [.command, .shift])
MASShortcutMonitor.shared()?.register(shortcut, withAction: {
print("hello")
})

Manage multiple windows in App Titanium

At the moment,my app have many window with correspond ID..Each I want to go to other page,I create a window and add view corresspond and open it.
I want to manage windows by stack array.
Each create a new window and open it, I will push ID of that window to stack windows.Then operate test in stack array..If that ID existed,I will close window in front of with that ID.
The code is follow:
var stackWindows=[]; //global variable
//function test the exist of window
function testWindowExist(windows)
{
for(var i=0;i<windows.length;i++)
{
for(var j=i+1;j<windows.length;j++)
{
if(windows[i]==windows[j])
{
return windows[i];
//close windows with ID=windows[i];
}
else
{
//do nothing
return 0;
}
}
}
}
I think I can get ID of windows existed but I don't know the way to close that window.
Can you help me.(Sorry,I am not good at English)
Closing a window is really easy:
windows[i].close();
But you've got bigger issues than that, I believe. Your algorithm above is identical to this one:
if (windows.length < 2) return undefined;
if (windows[0] == windows[1] return windows[0];
return 0;

Resources