How can i receive Notifications while a modal dialog is open - cocoa

I need to send messages to the GUI thread which should be processed the next time the GUI thread is idle. This message can come from the GUI thread or background threads.
I tried a combination of a MachPort/Notification. But when i do a
[[NSNotificationQueue defaultQueue] enqueueNotification: my_notify postingStyle: NSPostASAP];
This is not dispatched if there is a modal dialog, i have to close the dialog before it is processed so this is not useable for me.
It's okay to not handle messages during menu selection or live resize, but modal dialogs is a little bit too much delay.

Short answer: Don't use modal dialogs.
Long answer: Modal dialogs are handled by a special run loop mode called NSModalPanelRunLoopMode, see here.
To schedule a call, one way is to use performSelectorOnMainThread:withObject:waitUntilDone:modes: explained in that document; don't forget to specify the modal mode and the default mode there.
You can also use NSNotificationCenter and specify the run loop modes, see the discussion here. But it's tricky to use NSNotificationCenter from the threaded environment to start with as described here, so I don't recommend it.
On 10.6, you can also use dispatch_async.

Related

Is it possible to suppress single-click events during a double-click?

Our application supports single click and double-click events on a window which do different things. However we always get a single-click event during the double-click which causes undesired effects.
Our application is in Qt but really this is a question about underlying Windows/Mac APIs - is this a fundamental detail that the OS detects a single click as soon as you lift your finger since it can't possibly know you are going to click a second time, or can it be prevented?
If it can't be prevented, is their an accepted best practice how to handle it?
Start a timer when you get WM_LBUTTONDOWN (or Qt equivalent). If you get WM_LBUTTONDBLCLK (or Qt equivalent) before the timer expires, cancel the timer and execute your double-click action. Otherwise, when the timer expires, execute your single-click event.
On Windows, you can get the double-click time using GetDoubleClickTime().
That's about the best you can do - you can't prevent the single click message being generated in the first place on either platform.

Preventing WM_SETCURSOR and WM_NCHITTEST messages from being generated

I'm making an application that hooks itself in to a target application and, when activated by the user, prevents all keyboard and mouse window messages from reaching the target application's window proc. My application does this by translating the incoming input messages, such as WM_MOUSEMOVE, to WM_NULL, so that the window proc is unaware input happened.
The problem is that Windows also automatically sends WM_SETCURSOR and WM_NCHITTEST to the window proc (e.g. when the application calls PeekMessage) when mouse input occurs. These messages aren't posted to the window's message queue, so I can't change them to WM_NULL.
I initially worked around this by subclassing the window proc and simply ignoring WM_SETCURSOR and WM_NCHITTEST there, but subclassing seems to have compatibility issues with some of the applications I'm hooked in to.
My question is: How do I prevent WM_SETCURSOR and WM_NCHITTEST from being generated in the first place OR how do I prevent them from reaching the application's window proc.
Some Ideas to Try
I just finished implementing a global/system wide CallWndRetProc with a WH_CALLWNDPROCRET Windows Hook (like it describes in the past post of the link below).
http://help.lockergnome.com/windows2/Igor-SetCursor-SetWindowsHookEx--ftopict285504.html
Using that in combination with hiding all the system cursors using SetSystemCursor has effectively hidden the cursor for most applications.
If you wanted to continue hacking at this target application, you could try using API Monitor to diagnosis what is going on: http://www.rohitab.com/apimonitor
The guy at rohitab hints at releasing his source code eventually; his site seems to have some of the better forums about Hooking, Subclassing, Injecting, etc.
It sounds like you successfully used SetWindowLongPtr(), but there are a few different ways to get into the address space of the program you are working on...
Have you tried SetCapture()?
Other Links
Here are a few other links that may be useful:
http://support.microsoft.com/kb/31747
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646262(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/ms633569%28v=vs.85%29.aspx#winproc_subclassing
http://msdn.microsoft.com/en-us/library/windows/desktop/ms648395(v=vs.85).aspx
Hope that helps. Good luck.

WH_KEYBOARD_LL hook doesn't capture input in own process

I'm using a low-level keyboard hook (WH_KEYBOARD_LL) to disable certain input, such as Alt-Tab. I create the hook on a thread with a message pump, so I can properly handle the notifications.
The hook's callback function is able to process keyboard events whenever I'm not focused in the window that created the hook (i.e. my main window), but as soon as I activate that window, no events show up in the hook until I deactivate the window again and the input instead propagates to the window's WindowProc.
Does anybody have any clue what's going on here?
UPDATE: So, it turns out this behavior is caused by also registering for raw input in the same process. Apparently, using raw input causes my low-level keyboard hook to be disabled whenever my process’s window is focused. Does anybody know why and how to work around this?
Windows doesn't call low-level keyboard hooks if the most recently registered hook (aka the first hook to be executed) comes from a process that registered itself for raw keyboard events.
So a workaround is to create a second low-level keyboard hook in another process afterwards. Yes, this will cause both low-level keyboard hooks to be executed even when the focus is on a window from the first process.
Bad for performance, and who knows what Windows will bodge next - so I'm not really endorsing it - but it works.

How Do I Do Cool Dialog Stuff (MFC)

Whether I have to use a dialog box or a message doesn't really matter but I need to somehow do the following:
I've got a dialog-based MFC application. The main dialog calls a procedure that creates a thread. The call to the procedure is inside while loop. (Basically it's a file processing program - spawning off a thread for doing the file saving. So, a thread is spawned for each file that is being saved.)
I am suspending and resuming the main thread properly. However, I don't know how to get a message box/dialog box to display saying something like "please wait" and still have the main dialog update... 0.o
Basically, I want to lock the main dialog from user interaction (like keeping them from selecting anything or clicking any buttons), but I want the progress bar on the dialog to update...
Any ideas?
A bit old but does the work:
microsoft.com/msj/0297/wicked/wicked0297.aspx
Well, this is very old app.
You do not need to follow this sample; however you can follow the idea.
You have two choices:
Create progress bar in the main dialog, disable all dialog but progress. Start thread passing dialog’s handle. From the thread use this handle to send a custom message to allow dialog advancing progress.
Another message would notify dialog that thread is done and enable all controls.
Another choice would be to spawn modeless dialog, start the thread passing modeless dialog’s handle and process as described above.
Pass main dialog pointer to the modeless dialog to be used to disable and enable main dialog upon modeless start (OnInitDialog) and enable upon receiving thread complete message, before destroying modeless dialog window.

How do I create a custom modal NSWindow?

I want to create a custom NSWindow that acts as a modal dialog. By custom I mean it has normal user controls in the window, with a "OK" and "Cancel" buttons. The dialog will contain read only information, and have a few checkboxes, secure edit fields, etc.
The MainMenu.xib file will have the normal Window visible at launch, plus include the custom NSWindow (which is NOT visible at launch).
I am trying to find example code to launch the window in modal mode (after the app initializes and launches main window), and on "OK" run a process, and on success of that process hide the dialog. Or on failure, keep the dialog up, but show an error sheet on the dialog.
Any help is appreciated, thanks.
You want to look at NSApplication’s -runModalForWindow: and/or -runModalSession: methods. Note that using modal windows is generally a bad idea and if it’s at all possible to avoid doing so, you should; that said, sometimes needs must.
As far as launching a process, waiting for it to finish and so on, you can probably do what you need with NSTask, although you don’t provide sufficient detail to be certain. You’d probably want to observe NSTaskDidTerminateNotification to tell you when the task had finished.
See
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/OperatingSystem/OperatingSystem.html
for more on NSTask and
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/WinPanel/Concepts/UsingModalWindows.html%23//apple_ref/doc/uid/20000223-CJBEADBA
for more about modal NSWindow usage.
Have a look at NSApplication's -runModalForWindow: method, and "Using Application-Modal Dialogs."

Resources