Disable resizing window from top / NSWindowDelegate

I wonder if it’s possible (with declares) to prevent resizing a window from the top border. I know I can recreate the whole resizing mechanism with Xojo, but I’d prefer to use the native one.

I know of no easy way, such as a declarable property of resizableEdge, but building a custom NSWindowDelegate that catches the windowWillMove: event (or windowWillStartLiveResize:, or both) should do – just compare the old frame to the new and forbid a change if window.frame.y and window.frame.height differ. I am not sure which one (or in which order they) fire/s if the window is resized by dragging its top.

Thanks for the idea. That might be out of my knowledge at the moment. And I guess the top border would still change the cursor to resize arrows?

I did not want to mention it since you said you wanted a declare solution, but since that seems out, you could simply keep the value of Window.Top and if it changes without the event Moved has taken place, you reinstate the previous value. It would not disable resizing, but the window would snap back at its previous size afterward. It could be enough, though.

@Ulrich Bogun, do you know how to create NSWindowDelegate in Xojo? I now need NSWindowDelegateMBS.willPositionSheet as well to position a sheet window.

Hi Thomas,
I could have a look at it next week but if you use a MBSDelegate isn’t there such a function included in the plugin?

[quote=157562:@Ulrich Bogun]Hi Thomas,
I could have a look at it next week but if you use a MBSDelegate isn’t there such a function included in the plugin?[/quote]

Actually NSWindowDelegateMBS is a class in the MonkeyBread plugins. Maybe what Thomas wants is a free declare and not a paying solution …

That maybe, but if a free option isn’t available… A paid option may just be better than no option.

Here’s how to get those events…

If you need it for multiple windows you’ll also have to add a dispatcher from the Shared implementation to the instance.

[code]//Module
Structure NSSize
w As single
h As single
End Structure

//Window
Private Shared delegateClass As Ptr
Private Shared myWindowDelegate As Ptr

Sub Open()
const Cocoa = “Cocoa”
soft declare function NSClassFromString lib Cocoa (aClassName as CFStringRef) as Ptr
soft declare function alloc lib Cocoa selector “alloc” (classRef as Ptr) as Ptr
soft declare function init lib Cocoa selector “init” (classRef as Ptr) as Ptr
soft declare function NSSelectorFromString lib Cocoa (aSelectorName as CFStringRef) as Ptr
soft declare sub objc_registerClassPair lib Cocoa (cls as Ptr)
soft declare function objc_allocateClassPair lib Cocoa _
(superclass as Ptr, name as CString, extraBytes as Integer) as Ptr
soft declare function class_addMethod lib Cocoa _
(cls as Ptr, name as Ptr, imp as Ptr, types as CString) as Boolean
soft declare function objc_getProtocol lib Cocoa (name as CString) As Ptr
soft declare function class_addProtocol lib Cocoa (cls As Ptr, proto As Ptr) As Boolean
soft declare sub setDelegate lib Cocoa selector “setDelegate:” (id As Ptr, cvc As Ptr)

if delegateClass = nil then
delegateClass = objc_allocateClassPair(NSClassFromString(“NSObject”), “MyWillMoveHandler”, 0)
if delegateClass = nil then break
objc_registerClassPair(delegateClass)

dim delProtocol As Ptr = objc_getProtocol("NSWindowDelegate")  //get protocol type
if not class_addProtocol(delegateClass, delProtocol) then break //add protocol to class

if not class_addMethod(_
  delegateClass, _
  NSSelectorFromString("windowWillStartLiveResize:"), _
  AddressOf impl_StartLiveResize, _
  "v@:@"_
  ) then break
  
if not class_addMethod(_
  delegateClass, _
  NSSelectorFromString("windowWillResize:toSize:"), _
  AddressOf impl_WillResize, _
  "{NSSize=ff}@:@{NSSize=ff}"_
  ) then break

end //end creating delegate class

myWindowDelegate = init(alloc(delegateClass)) //create instance of Delegate Class

setDelegate(Ptr(self.Handle), myWindowDelegate) //link to window

End Sub

Sub Close()
declare sub release lib “Cocoa” selector “release” (c as Ptr)
if myWindowDelegate <> nil then release(myWindowDelegate)
End Sub

Private Shared Sub impl_StartLiveResize(id as Ptr, sel as Ptr, notification as Ptr)
System.DebugLog(“start resize”)
End Sub

Private Shared Function impl_WillResize(id as Ptr,s as Ptr,sndr as Ptr,newSize As NSSize) As NSSize
System.DebugLog("will resize to size " + Str(newSize.w) + ", " + Str(newSize.h))
return newSize
End Function[/code]

Exactly. I also think it is kind of rude to mention an MBS class and request a declare that has the same functionality. Like “I don’t want to afford that, can you hack it for me ?”…

But as you noted in another thread, it seems being honest and open does not pay as much :confused:

He could have had the decency to simply mention the Cocoa class, after a bit of homework in the Mac Developer Library.

Referring to MBS was a mistake on my part. I found the Cocoa function in the MBS documents first using Google, and copy-pasted it here without noticing the MBS-postfix. So I apologize for that.

Thanks Will for you help! I’ll try it out and let you know how it goes :slight_smile:

I tried the code, but unfortunately couldn’t quite get it to work. The window seems to be closing as soon as I resize it.

Hmm, maybe something got lost in the copy paste. Here’s the project that’s running for me http://home.comcast.net/~trochoid/WillResize.zip

This restricting of drag sides is something I’ve wanted to do too but I don’t see how these events will help. The WillResizeToSize event uses an NSSize, not an NSRect so you can’t tell which side is being dragged, just what it’s new width height is. Maybe measuring the cursor position is needed.

[quote=157907:@Will Shank]Hmm, maybe something got lost in the copy paste. Here’s the project that’s running for me http://home.comcast.net/~trochoid/WillResize.zip

This restricting of drag sides is something I’ve wanted to do too but I don’t see how these events will help. The WillResizeToSize event uses an NSSize, not an NSRect so you can’t tell which side is being dragged, just what it’s new width height is. Maybe measuring the cursor position is needed.[/quote]

This project works quite fine. I just read a workaround to render a window non resizeable that could be applied to the OP concerne here, sort of. If you set a window minHeight = maxHeight = Height then the window will not resize heightwise. Placing that in impl_handlewillResizeToSize if the newSize.h value is different than the current one would prevent resizing.

But the OP wants to specifically prevent resizing from the top, as I understand not from the bottom. So the trick would not work, as it would prevent resizing from bottom.

Resizing from the top actually changes the top value as well as it changes the height. Looking at System.MouseY, and comparing with mainWindow.Top, one can detect the “resize from top” and prevent it.