Difference between WindowProc and CallWindowProc? - winapi

What is the difference between WindowProc and CallWindowProc ?
I can imagine when registering a new window class I can specify my own WindowProc for it.
This leaves the question: When and what for do I use CallWindowProc ?

When you subclass a window using SetWindowLong/Ptr(GWL_WNDPROC) to assign a new WindowProc() to the window, the replacement WindowProc() uses CallWindowProc() when it needs to call the window's original WindowProc():
Subclassing a window
The preferred way to subclass a window is to use SetWindowSubClass() instead:
Safer subclassing

See msdn. CallWindowProc is used for subclassing.

Related

what is the equivalent control we can use in Vb6 to get the window handle that the control is bound to

in c# we can use IntPtr hWnd = this.Handle to get the window handle that the control is bound to.
which control we can use in vb6 to gets the window handle that the control is bound to?
You can use the hWnd property of the Form object to get the window handle of the form or control.
Dim hWnd As Long
hWnd = Form1.hWnd
You can also use the hWnd property of other controls, such as buttons, labels, and text boxes, to get their window handles.

winapi - DeferWindowPos and InvalidateRect

I have a main window which allows to display a child modal dialog. That dialog window is created based on the resource file using DialogBox function. It contains a few controls and a horizontal splitter which are repositioned/resized when handling WM_SIZE and WM_MOUSEMOVE messages. I use BeginDeferWindowPos, DeferWindowPos and EndDeferWindowPos functions. It looks like that everything is repainted correctly. Should I also call InvalidateRect after EndDeferWindowPos ? Is there any scenario where it may be necessary ? I don't handle WM_PAINT message.
The documentation for the DeferWindowPos function would strongly suggest that, so long as you don't have the SWP_NOREDRAW bit set in the uFlags argument, you do not need to call InvalidateRect after you have called EndDeferWindowPos:
SWP_NOREDRAW 0x0008 Does not redraw changes. If this flag is set,
no repainting of any kind occurs. This applies to the client area, the
nonclient area (including the title bar and scroll bars), and any part
of the parent window uncovered as a result of the window being moved.
When this flag is set, the application must explicitly invalidate or
redraw any parts of the window and parent window that need redrawing.

Is it okay to call UIResponder.resignFirstResponder directly?

I just started to suspect that calling resignFirstResponder directly is not actually allowed. Unlike NSResponder, it's allowed to call becomeFirstResponder directly in UIKit. So far I was making assumption that calling resignFirstResponder would be okay too. But in fact, the manual says resignFirstResponder method is there to get notified, and mentions nothing about direct calling.
Notifies this object that it has been asked to relinquish its status
as first responder in its window.
If it's designed in same way of how NSResponder works, direct calling to resignFirstResponder wouldn't be allowed though there's no obvious way to figure out validity of the call in the manual...
If it's been designed not to be called directly, directly calling to the method would be harmful or make code harder to maintain.
Is it okay to call UIResponder.resignFirstResponder method directly?
It seems to be okay because on another part of the manual, it says
...
To dismiss the keyboard, you call the resignFirstResponder method of
the text-based view that is currently the first responder. When a text
view resigns its first responder status, it ends its current editing
session, notifies its delegate of that fact, and dismisses the
keyboard. In other words, if you have a variable called myTextField
that points to the UITextField object that is currently the first
responder, dismissing the keyboard is as simple as doing the
following:
[myTextField resignFirstResponder];
Everything from that point on is handled for you automatically by the text object.

When an NSWindow object has a delegate that is a NSWindow subclass, who is responsible to act on received events?

So I'm building a program that features the use of the IKImageBrowserView component as a subview in an NSWindow. As a side note, I have a controller object called ImageBrowserController which subclasses NSWindow and is set as the delegate of the NSWindow object of my app.
I have sent IKImageBrowserView the message setCanControlQuickLookPanel:YES to enable it to automatically use the QuickLook functionality to preview image files when the IKImageBrowserView is a first responder to receive key events. Then it took me a while to figure out how to make the IKImageBrowserView a first responder which I finally got working by overriding acceptsFirstResponder inside my ImageBrowserController.
Now I understand that as the delegate to the NSWindow, ImageBrowserController has a place in the responder chain after the event gets triggered on NSWindow. And I understand that as a subview of NSWindow, IKImageBrowserView is in line to be passed events for event handling. What I don't get is where the connection is between the ImageBrowserController being a first responder and the event somehow making it to the IKImageBrowserView. I didn't set NSWindow or IKImageBrowserView as first responders explicitly. So why isn't it necessary for me to implement event handling inside my ImageBrowserController?
EDIT: So after reading the accepted answer and going back to my code I tried removing the acceptsFirstResponder override in my ImageBrowserController and the QuickLook functionality still triggered just like the accepted answer said it would. Commenting out the setCanControlQuickLookPanel:YES made the app beep at me when I tried to invoke QuickLook functionality via the spacebar. I'm getting the feeling that my troubles were caused by user error of XCode in hitting the RUN button instead of the BUILD button after making changes to my code (sigh).
Some of what you are saying regarding the interactions between your objects does not make sense, and it is hard to address your stated question without some background.
As you say, your window delegate has a place at the end of the responder chain, after the window itself. The key point I think you are missing is that GUI elements, such as your IKImageBrowserView, will be at the beginning of the chain, and any one of them in a given window could be the current firstResponder.
When your application gets an event, it passes it off to the key window (which is just the window which currently accepts "key" (i.e., "keystroke") events). That window begins by asking its firstResponder to handle the event. If that object refuses, it passes the event to its own nextResponder, usually its superview, which either handles it or passes it on, until the event has either been handled or passed all the way up to the window object itself. Only then will the window (if it does not handle the event itself) ask its delegate to handle the event.
This means that the connection between the window delegate and the IKImageBrowserView is only through the Responder Chain, and its nature is simply that if the view declines to handle any given event, the delegate may eventually be asked to handle it, if no other object in between them handles it first.
Your window delegate does not need to be a firstResponder. Nor does overriding acceptsFirstResponder on the window delegate have any effect on one of the window's subviews.*
Your window delegate also does not need to (and, indeed should not) be a subclass of NSWindow. All it needs is to be a subclass of NSObject which implements whatever methods from the NSWindowDelegate Protocol you are interested in, and methods to handle any events you might want to catch if they are not handled by other objects.
So, the answer to your explicit question at the end is (and I do not mean this sarcastically): you only need to implement event handling in your window delegate if you want it to handle events itself.
*: IKImageBrowserView already responds YES to acceptsFirstResponder. If there are no other subviews in your window, it will automatically be the firstResponder when your application starts. You can set this initialFirstResponder explicitly in Interface Builder by connecting that outlet on the window to whatever object you want.

How to get notifications of NSView isHidden changes?

I am building a Cocoa desktop application. I want to know when a NSView's isHidden status has changed. So far using target/action doesn't help, and I can't find anything in NSNotification for this task. I would like to avoid overriding the setHidden method, because then I'll have to override all the NSView derived class that I am using.
UPDATE: I ended up using KVO. The path for "isHidden" is "hidden", probably because the setter is "setHidden".
You could use Key-Value Observing to observe the isHidden property of the NSView(s). When you receive a change notification from one of these views, you can check if it or one of its superviews is hidden with -isHiddenOrHasHiddenAncestor.
A word of warning: getting Key-Value Observing right is slightly tricky. I would highly recommend reading this post by Michael Ash, or using the -[NSObject gtm_addObserver:forKeyPath:selector:userInfo:options] method from the NSObject+KeyValueObserving category from the Google Toolbox for Mac.
More generally, one can override viewWillMoveToWindow: or the other related methods in NSView to tell when a view will actually be showing (i.e. it's window is in the window display list AND the view is not hidden). Thus the dependency on KVO for the 'hidden' key used above is removed, which only works if setIsHidden has been called on that view. In the override, 'window' (or [self window]) will indicate whether the view is being put into a visible view hierarchy (window is non-nil) or being taken out of it (window is nil).
I use it for example to start/stop a timer to update a control from online data periodically - when I only want to update while the control is visible.
Could you override the setter method for the hidden property so that it will trigger some custom notification within your application?

Resources