View Full Version : Carbon window -- maintaining aspect ratio on resize
Hi all,
my game requires a fixed aspect ratio for layout reasons, but I would like the player to be able to resize the window using the normal resize dragging action. This resizing needs to restrict the window dimensions to the original aspect ratio.
Does anyone know how this can be done in Carbon? I believe it can be done in Cocoa, but that is not an option at present.
thanks for any help.
NCarter
2004.01.12, 07:35 PM
Register for your window to receive kEventWindowBoundsChanging and kEventWindowBoundsChanged events from the class kEventClassWindow. Then you can do something like this:
case kEventWindowBoundsChanging:
{
UInt32 attributes;
::GetEventParameter(inEvent, kEventParamAttributes, typeUInt32, NULL,
sizeof(UInt32), NULL, &attributes);
// Only respond if the window is being resized:
if(attributes & kWindowBoundsChangeSizeChanged)
{
Rect bounds;
::GetEventParameter(inEvent, kEventParamCurrentBounds,
typeQDRectangle, NULL, sizeof(Rect), NULL, &bounds);
UInt32 width = bounds.right - bounds.left;
UInt32 height = bounds.bottom - bounds.top;
// We work out whether the mouse is closer to the right or the
// bottom edge of the window and use that to control the window
// size, because it gives a better feeling of control. As
// GetMouse() returns port-local coordinates, I'm hoping that
// the port will always be set correctly when this handler gets
// called....
Point mouse_location = {0, 0};
::GetMouse(&mouse_location);
mouse_location.h = mouse_location.h * 3 / 4;
if(mouse_location.h < mouse_location.v)
bounds.right = bounds.left + (height * 4 / 3);
else
bounds.bottom = bounds.top + (width * 3 / 4);
(OSStatus)::SetEventParameter(inEvent, kEventParamCurrentBounds,
typeQDRectangle, sizeof(Rect), &bounds);
}
// Only bother redrawing the window if live window resizing is available.
// Otherwise, spurious redraws occur while resizing windows under MacOS 9.
if(UGestalt::WindowManagerAttributes() & gestaltWindowLiveResizeMask)
{
mView->UpdateFromPort();
mView->Render();
}
// The following is necessary to ensure that the default handler doesn't
// undo our adjustments:
status = noErr;
break;
}
case kEventWindowBoundsChanged:
{
mView->UpdateFromPort();
mView->Render();
status = noErr;
break;
}
This code comes from CDisplayWindow::Handler() from the Yoink source code, if you want to see it in context. Note that the aspect ratio is hardcoded to 4/3 - you might want to make that adjustable in some way.
Thanks very much for that! I've just gotten around to including it (I had to revamp my event handling from an old WNE based system first) and it works just fine.
Much appreciated.
skyhawk
2004.01.25, 03:00 AM
to anyone curious, here is the cocoa code I use:
- (NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)proposedFrameSize
{
proposedFrameSize.height = proposedFrameSize.width * 3/4;
return [NSWindow frameRectForContentRect:(NSRect){[self frame].origin,proposedFrameSize} styleMask:[sender styleMask]].size;
}
- (NSRect)windowWillUseStandardFrame:(NSWindow *)sender defaultFrame:(NSRect)df
{
int n=df.size.height*4/3;
if (n < df.size.width)
{
df.origin.x += (df.size.width-n)/2;
df.size.width = n;
} else {
df.size.height = df.size.width*3/4;
}
return df;
}
- (void)newsize:(NSNotification *)nsn
{
NSOpenGLContext *c = [self openGLContext];
[c clearDrawable];
[c setView:self];
}
vBulletin® v3.8.4, Copyright ©2000-2010, Jelsoft Enterprises Ltd.