SDL window with fixed aspect ratio

I have now been searching for hours unable to find one with a similar problem and a solution to it that fit my needs.

Fixed aspect ratio like e.g. some of the standard windows solitaire games(at least windows 7).

I?m using SDL 1.2.14(no OpenGL) on Window 7 with VS10.

I have used: http://www.gamedev.net/community/forums/topic.asp?topic_id=428022 to make screen update when the resize event happens. I?ve tried to implement the fixed aspect ratio in the eventFilter function to. It works, but with issues. The default window resize handler (or whatever it?s called) shows the resized window every time there is a SDL_VIDEORESIZE event, so the window switch between the normal resized form and the fixed aspect ratio form(which is showed when the SDL_SetVideoMode where called).
My code example have the problem that when I poll in the right side of the window, the resizing just change between the case: diff_w > and the case: diff_h<, because the default resize handler comes in between and overwrite the height I?ve set in the case: diff_w>. And then the diff_h obviously is bigger, and then it just switches between these cases.

I don?t know if it?s possible to disable the default handling though some windows functions, I guess there isn?t a SDL way to do it. Else maybe change some the default window resize handling ? if possible.

Hope someone can solve this problem… [Rolling Eyes]

Code example:

Code:

const int SCREEN_W_RATIO=5;
const int SCREEN_H_RATIO=4;

int MapEditor::eventFilter(const SDL_Event *e)
{
if( e->type == SDL_VIDEORESIZE )
{
int resize_h=e->resize.h, resize_w=e->resize.w, diff_w=resize_w-screen_w, diff_h=resize_h-screen_h;

	if(abs(diff_w)>abs(diff_h))
	{
		if(diff_w > SCREEN_W_RATIO/2)
		{
			int resizeFactor = diff_w/SCREEN_W_RATIO + ((diff_w%SCREEN_W_RATIO)>SCREEN_W_RATIO/2 ? 1 : 0);
			screen_w += SCREEN_W_RATIO*resizeFactor;
			screen_h += SCREEN_H_RATIO*resizeFactor;
			int b[4] = {screen_w, resize_w, screen_h, resize_h };
			Testing::printToLog(b,4,"Efter W>: SW, RW, SH, RH");
			SDL_SetVideoMode(screen_w,screen_h,SCREEN_BPP, SDL_SWSURFACE | SDL_RESIZABLE);
			calcZoom(resize_w);
			staticShow();
		}
		else if(diff_w < -SCREEN_W_RATIO/2)
		{
			int resizeFactor = (-diff_w)/SCREEN_W_RATIO + (((-diff_w)%SCREEN_W_RATIO)>SCREEN_W_RATIO/2 ? 1 : 0);
			screen_w -= SCREEN_W_RATIO*resizeFactor;
			screen_h -= SCREEN_H_RATIO*resizeFactor;
			int b[4] = {screen_w, resize_w, screen_h, resize_h };
			Testing::printToLog(b,4,"Efter W<: SW, RW, SH, RH");
			SDL_SetVideoMode(screen_w,screen_h,SCREEN_BPP, SDL_SWSURFACE | SDL_RESIZABLE);
			calcZoom(resize_w);
			staticShow();
		}
	}
	else
	{
		if(diff_h > SCREEN_H_RATIO/2)
		{
			int resizeFactor = diff_h/SCREEN_H_RATIO + ((diff_h%SCREEN_H_RATIO)>SCREEN_H_RATIO/2 ? 1 : 0);
			screen_w += SCREEN_W_RATIO*resizeFactor;
			screen_h += SCREEN_H_RATIO*resizeFactor;
			int b[4] = {screen_w, resize_w, screen_h, resize_h };
			Testing::printToLog(b,4,"Efter H>: SW, RW, SH, RH");
			SDL_SetVideoMode(screen_w,screen_h,SCREEN_BPP, SDL_SWSURFACE | SDL_RESIZABLE);
			calcZoom(resize_w);
			staticShow();
		}
		else if(diff_h < -SCREEN_H_RATIO/2)
		{
			int resizeFactor = (-diff_h)/SCREEN_H_RATIO + (((-diff_h)%SCREEN_H_RATIO)>SCREEN_H_RATIO/2 ? 1 : 0);
			screen_w -= SCREEN_W_RATIO*resizeFactor;
			screen_h -= SCREEN_H_RATIO*resizeFactor;
			int b[4] = {screen_w, resize_w, screen_h, resize_h };
			Testing::printToLog(b,4,"Efter H<: SW, RW, SH, RH");
			SDL_SetVideoMode(screen_w,screen_h,SCREEN_BPP, SDL_SWSURFACE | SDL_RESIZABLE);
			calcZoom(resize_w);
			staticShow();
		}
	}
}
return 1; 

}

I?ve now found the solution myself.
It only suits window but that?s my primarily need.
I?ve used the VM_RESIZING message.

It still needs full screen handling but that will come…

Code:

#include <Windows.h>

const int SCREEN_W_RATIO=5;
const int SCREEN_H_RATIO=4;

int eventFilter(const SDL_Event e)
{
if( e->type == SDL_SYSWMEVENT)
{
switch(e->syswm.msg->msg)
{
case WM_SIZING:
{
RECT windowRect;
RECT * lParamRectPtr = ((RECT
)e->syswm.msg->lParam);
GetWindowRect(e->syswm.msg->hwnd,&windowRect);
int diff_w=(lParamRectPtr->right-lParamRectPtr->left)-(windowRect.right-windowRect.left), diff_h=(lParamRectPtr->bottom-lParamRectPtr->top)-(windowRect.bottom-windowRect.top);

			if ((e->syswm.msg->wParam==WMSZ_BOTTOMLEFT) || (e->syswm.msg->wParam==WMSZ_BOTTOMRIGHT))			
				e->syswm.msg->wParam=WMSZ_BOTTOM;		
			else if ((e->syswm.msg->wParam==WMSZ_TOPLEFT) || (e->syswm.msg->wParam==WMSZ_TOPRIGHT))			
				e->syswm.msg->wParam=WMSZ_TOP;

			if(e->syswm.msg->wParam==WMSZ_RIGHT || e->syswm.msg->wParam==WMSZ_LEFT)
			{
				if(diff_w > SCREEN_W_RATIO/2)
				{
					int resizeFactor = diff_w/SCREEN_W_RATIO + ((diff_w%SCREEN_W_RATIO)>SCREEN_W_RATIO/2 ? 1 : 0);
					screen_w += SCREEN_W_RATIO*resizeFactor;
					screen_h += SCREEN_H_RATIO*resizeFactor;
					calcZoom(screen_w);

					(*lParamRectPtr) = windowRect;
					if(e->syswm.msg->wParam==WMSZ_RIGHT)
						lParamRectPtr->right += SCREEN_W_RATIO*resizeFactor;
					else
						lParamRectPtr->left += SCREEN_W_RATIO*resizeFactor;
					lParamRectPtr->bottom += SCREEN_H_RATIO*resizeFactor;

				}
				else if(diff_w < -SCREEN_W_RATIO/2)
				{
					int resizeFactor = (-diff_w)/SCREEN_W_RATIO + (((-diff_w)%SCREEN_W_RATIO)>SCREEN_W_RATIO/2 ? 1 : 0);
					screen_w -= SCREEN_W_RATIO*resizeFactor;
					screen_h -= SCREEN_H_RATIO*resizeFactor;
					calcZoom(screen_w);

					(*lParamRectPtr) = windowRect;
					if(e->syswm.msg->wParam==WMSZ_RIGHT)
						lParamRectPtr->right -= SCREEN_W_RATIO*resizeFactor;
					else
						lParamRectPtr->left -= SCREEN_W_RATIO*resizeFactor;
					lParamRectPtr->bottom -= SCREEN_H_RATIO*resizeFactor;
				}
				else
					(*lParamRectPtr) = windowRect;
			}
			else if(e->syswm.msg->wParam==WMSZ_BOTTOM || e->syswm.msg->wParam==WMSZ_TOP)
			{
				if(diff_h > SCREEN_H_RATIO/2)
				{
					int resizeFactor = diff_h/SCREEN_H_RATIO + ((diff_h%SCREEN_H_RATIO)>SCREEN_H_RATIO/2 ? 1 : 0);
					screen_w += SCREEN_W_RATIO*resizeFactor;
					screen_h += SCREEN_H_RATIO*resizeFactor;
					calcZoom(screen_w);

					(*lParamRectPtr) = windowRect;
					if(e->syswm.msg->wParam==WMSZ_BOTTOM)
						lParamRectPtr->bottom += SCREEN_W_RATIO*resizeFactor;
					else
						lParamRectPtr->top += SCREEN_W_RATIO*resizeFactor;
					lParamRectPtr->right += SCREEN_H_RATIO*resizeFactor;
				}
				else if(diff_h < -SCREEN_H_RATIO/2)
				{
					int resizeFactor = (-diff_h)/SCREEN_H_RATIO + (((-diff_h)%SCREEN_H_RATIO)>SCREEN_H_RATIO/2 ? 1 : 0);
					screen_w -= SCREEN_W_RATIO*resizeFactor;
					screen_h -= SCREEN_H_RATIO*resizeFactor;
					calcZoom(screen_w);

					(*lParamRectPtr) = windowRect;
					if(e->syswm.msg->wParam==WMSZ_BOTTOM)
						lParamRectPtr->bottom -= SCREEN_W_RATIO*resizeFactor;
					else
						lParamRectPtr->top -= SCREEN_W_RATIO*resizeFactor;
					lParamRectPtr->right -= SCREEN_H_RATIO*resizeFactor;
				}
				else
					(*lParamRectPtr) = windowRect;
			}
			
		break;
		}
	}
}

if( e->type == SDL_VIDEORESIZE )
{
	SDL_SetVideoMode(screen_w,screen_h,SCREEN_BPP, SDL_SWSURFACE | SDL_RESIZABLE);
	staticShow();
}
return 1;

}