Get ITaskbarList3 data of specific window - winapi

ITaskbarList3 interface provides only setter methods. Is there a way to get the information (like HWND list of the tabs) for a specific taskbar entry?

No that's not possible through the taskbar API. The system has been designed with the intention that you'll only work on taskbar buttons that you own. In which case there's no need for getters since you can remember for yourself what value you last passed to a setter, should you need to.

Related

Make "Close All" (cmd+option+W) apply only to one type of document windows

I have an application that manages different types of NSDocument subclasses (along with matching NSWindow subclasses).
For instance, it's possible that the app has one window of type A open, and two windows of type B.
Now, if a window of type B is active, and the user chooses "Close All" or hits cmd+option+W, all my app's windows are sent the close message.
But I only want all of the active window type's windows closed instead, i.e. only the two type B, not the type A window. How do I accomplish this?
I currently have no explicit menu entry for "Close All". Instead, macOS provides that automagically. If there perhaps a way to intercept a "closeAll" message? Can't find one, though.
AppKit will add the Close All menu item if there isn't one. Add an alternate menu item item with key equivalent cmd+option+W below the Close menu and connect it to your own action method.
You might succeed with overriding your document's canClose(withDelegate:,shouldClose:,contextInfo:) to return whether a document should be closed.
If this doesn't behave the way you want, you can create a subclass of NSDocumentController (if you don't have one already). Details on how to do that vary, but usually you have main (menu) XIB or main Storyboard, which has a "Document Controller" object: set its class to your custom class.
Then override closeAllDocuments(withDelegate:,didCloseAllSelector:,contextInfo:) and implement your custom logic.
Note that you should detect whether your app is about to quit and then really do close all you documents (unless you really want to prevent the app quit, e.g. because a document is dirty).
After some digging I figured out where the auto-generated "Close All" menu item sends its action to: To the closeAll: selector of the application target:
Thus my solution is to subclass NSApplication and implement the handler there, which then simply closes all windows that are of the same type (this assumes that I use specific subclasses for my different types of windows):
- (IBAction)closeAll:(id)sender {
Class windowClass = self.keyWindow.class;
for (NSWindow *w in self.windows) {
if (windowClass == w.class) {
[w performClose:sender];
}
}
}
Caution: If you adopt this pattern be aware that:
The closeAll: selector is not documented nor mentioned in the header files, meaning that Apple might feel free to change in a future SDK, though I find that unlikely. It will probably not break anything if that happens, but instead your custom handler won't be called any more.
The code simply tells all windows to close, ignoring the fact that one might reject to be closed, e.g. by user interaction. In that case you may want to stop the loop instead of continuing to close more windows (though I know of no easy way to accomplish that).

How do I test if my custom callback is set as the current procedure for a given window?

We have a kiosk mode application for Windows Mobile 5 that was going strong for a year at least in production. It uses window subclassing through the SetWindowLong windows API function to override the behavior of the taskbar to prevent users from ever leaving our application or other explicitly allowed applications.
My callback overrides the handling of a few window messages and calls the default handler for other messages. This is done by storing the previous function pointer returned by SetWindowLong, and using it inside of the new function by calling CallWindowProc on it.
Then we had to update the application to be compatible with Windows Mobile 6.5.3, and started having a bunch of problems. I followed this article to disable the bottom menu buttons which are new on 6.5. On a single application, it works fine and the menu respects my callback. As soon as the user opens up another application through ours, that window seems to be recreated, and I had to devise a mechanism to detect foreground window changes and then "resubclass" the window again.
In my code, I don't have control of when exactly this window is recreated, so my first attempt was to use the GetWindowLong function to obtain the current callback address and test it against my own function address. I learned the hard way that I can't just compare the values like that, since it does not always return the function pointer.
Because I'm not able to test if my method is the current handler that way, I end up sometimes setting my method as the handler, and the previous handler is also my own method (in this case, the window was not recreated and thus already had my method set). This results in an infinite loop, since my callback ends up calling itself indefinitely.
How can I know if my custom function is the one being used by a certain window, so that I can avoid this infinite recursion?
Don't use SetWindowLong(GWL_WNDPROC) to subclass a window. Use SetWindowSubClass() instead (like Raymond Chen said):
Subclassing Controls
Safer subclassing
Amongst providing safer subclassing semantics (such as allowing multiple subclasses at a time), it also allows you to associate user-defined data with each subclass. So you could use GetWindowSubclass() to check if you have already subclassed the window or not.
Or, you could simply keep track of whether or not you have already subclassed the window. A simple boolean variable will suffice. Once your subclass is in place, you MUST remove the subclass before the window is fully destroyed. So, for instance, when the subclass receives the WM_NCDESTROY message, you can remove the subclass and clear your boolean at the same time, and then the next time you see the window again your boolean will tell you that you need to subclass the window.
Send the custom message to window. Handle this message in your custom function to return some value that will indicate that it was your custom handler.. and so on.
if(SendMessage(hwnd, mymsg, 0, 0) != myvalue)
;// It's not your handler

What difference between control's window handle and controlID

I'm learning Win32 assembly. Have some question I search but not suitable result.
Anyone can explain for me What difference between control's window handle and controlID.
They have nothing in common. Every window has a handle, returned by CreateWindowEx(). Such a window can have a few extra properties attached, like a menu handle. The hMenu argument in CreateWindowEx(). If the window doesn't have a menu, a child window won't have one, then you can use that argument to pass an arbitrary other bit of data. It will be assigned to the GWLP_ID property (see GetWindowLongPtr). Also note the GWLP_USERDATA, an extra property that's entirely yours to use as you see fit.
Dialogs take advantage of this, a dialog template that you create in the resource editor gives you a way to number the child controls. With a helper function like GetDlgItem() to get the handle back for a control with a specific number. Which is pretty necessary for dialogs since it is Windows that create the child controls from the dialog template so you don't know the window handles for them yourself.

block ALL keyboard access, mouse access and keyboard shortcut events

In order to block ALL keyboard access, mouse access and keyboard shortcut events in one of my projects, I:
Created a full screen transparent borderless window, in front of other windows, but invisible.
Handle all keyboard and mouse events with simple return; the window itself.
Make the window modal [NSApp runModalForWindow:myWindow] in order to block keyboard shortcuts.
Release window from touchpad's gesture events only.
But this guy made it look simple in a tiny app -MACIFIER:
How did he do it?
not really sure if this would be usable, but you could use the program hotkeynet (generally used for gaming, but I have had success using other methods) and map every single key/mouse action to do nothing. I did something similar by blocking access to a specific program with it in about 20-30 minutes.
not sure if it will help; but it might be the solution you need?
I believe you can use Quartz Event Services. In particular, have a look at CGEventTapCreate, and note the 4th parameter, which allows you to specify what kinds of events you'd like to intercept. The available kinds of events are listed in the CGEventType enum.
If you set your tap to be an active filter, returning NULL from the callback will delete the event.

What's a good way to bind from a shared utility window and the frontmost document window?

I have an application which allows for multiple NSDocuments to be open. In this application is a single utility window that contains some functionality that I want to apply to the frontmost document.
I am trying to use bindings here, so the trick is how to cleanly bind the user interface of the utility window to the frontmost document. The goal is that then switching the frontmost document window will update the view in the utility window; controls that are bound to properties of the frontmost document's model would be updated appropriately when state changes in the document's model, etc.
For sending actions from such a window, it's easy to just use first responder; the document object can intercept actions via the responder chain. But I want more than this, and of course you can't bind to the first responder.
A few ideas that I have:
put an object controller in my nib for the shared window. When a document window changes frontmost status, change the content of that binding. A disadvantage of this is that if I were to have another kind of utility window, I'd have to remember to hook up the bindings from the document window to that utility window too!
Make an accessor in the application delegate that gets the frontmost document window by traversing the window list. My utility window would just bind through the application delegate's method. A disadvantage here is that it's not KVO compliant
Have a getter and setter in the application delegate to determine (and perhaps set to be KVO-compliant? would that make sense?) the frontmost document. Perhaps use window notifications set an ivar to the appropriate value when a window loses main status. Update: I'm using this for now, and it actually seems pretty clean. I set the value from the windowDidBecomeMain notification of my doc window and clear it (if it's the current value) in windowWillClose. Unless there is any major objection, this is probably the approach I'll use.
One idea was to bind to mainWindow.windowController.document ... this comes close, except that when my shared window becomes main, then this binding goes away. So really I need to find the frontmost document window's controller (and of the right class).
None of these seem quite right. Is there a better way to do this that I'm missing?
I’ve always bound through Shared Application, mainWindow.document, which works fine. if you have windows w/o documents, you may want to add a mainYourKindOfWindow key that is implemented by watching mainWindow and updating the value based on some filter criteria.
Leopard's TextEdit does this for its inspector. Check it out in file:///Developer/Examples/AppKit/TextEdit.
put an object controller in my nib for the shared window. When a document window changes frontmost status, change the content of that binding.
That makes the most sense to me. You'd change the content to the document instance ([NSDocumentController currentDocument]).
A disadvantage of this is that if I were to have another kind of utility window, I'd have to remember to hook up the bindings from the document window to that utility window too!
Huh? I don't understand this.
Leopard's TextEdit does this for its inspector. Check it out in >file:///Developer/Examples/AppKit/TextEdit.
In TextEdit, inspector values are bound via an intermediate object controller. The controller content object is bound to the shared application mainWindow.
You may bind the content to mainWindow.firstResponder and uncheck "Raises for not applicable keys".
Use the key window, not the main window. KVO might not be supported for NSApplication's keyWindow property, but you can still use NSNotifications if it doesn't work. The reason for this is that NSDocumentController's currentDocument uses the keyWindow, so it better represents the built in functionality. Also, panels can be set to avoid becoming key window.

Resources