Dialog Window Style!

BlitzMax Forums/BlitzMax Module Tweaks/Dialog Window Style!

JoshK(Posted 2006) [#1]
Ever notice how most programs use option windows and dialogs that don't have any icon on the left side of the titlebar?


Now you too can have professional-looking application windows or custom requesters, with my amazing WINDOW_DIALOG tweak! Here's how:

First, open "mod\brl\maxgui.mod\gadget.bmx" and add this constant at line 60, then save the file:
Const WINDOW_DIALOG=512

Now open "mod\brl\win32maxgui.mod\win32gui\win32window.cpp". Find this section that starts at line 24:
	//1=title
	if( style&1 ){
		wstyle|=WS_CAPTION|WS_SYSMENU;
		if( style&2 ) wstyle|=WS_MINIMIZEBOX|WS_MAXIMIZEBOX;
	}else{
		wstyle|=WS_POPUP;
	}

And change it to this:
	//1=title
	if( style&1 ){
		wstyle|=WS_CAPTION|WS_SYSMENU;
		if( style&2 ) wstyle|=WS_MINIMIZEBOX|WS_MAXIMIZEBOX;
		if( style&512 ) xstyle|=WS_EX_DLGMODALFRAME;
	}else{
		wstyle|=WS_POPUP;
	}

Finally, open "mod\brl\win32maxgui.mod\win32gui\win32hwnd.cpp" and comment out line 184:
	// if (!icon) icon=LoadIcon( NULL,IDI_APPLICATION );


Recompile mods brl.maxgui and brl.win32maxgui. Then run this code in BlitzMax:
Strict

Local w=400
Local h=300
Local win:TGadget=CreateWindow("Dialog Window",(Desktop().ClientWidth()-w)/2,(Desktop().ClientHeight()-h)/2,w,h,Null,WINDOW_TITLEBAR+WINDOW_DIALOG)

While WaitEvent()<>EVENT_WINDOWCLOSE
Wend



JoshK(Posted 2006) [#2]
Part II

I noticed that using an icon in my main program window overides my icon-less window. To overcome this, you have to create a new window class. This can be done easily by just copying existing code.

Open "mod\brl\win32maxgui.mod\win32gui\win32hwnd.cpp" and find the Win32Hwnd::className() method. Copy the entire method and paste it again, then change the name to Win32Hwnd::classNameDialog(). Comment out the line where the icon is loaded, and the line where _wc.hicon is set. Also, change the class name to "BLITZMAX_DIALOG_CLASS". It should look like this:
const char *Win32Hwnd::classNameDialog(){

	static int done;
	
	static WNDCLASS _wc;

	static const char *name="BLITZMAX_DIALOG_CLASS";
	
	if( done ) return name;
	
	// HICON icon=LoadIcon(GetModuleHandle(0),(const char*)101);
	// if (!icon) icon=LoadIcon( NULL,IDI_APPLICATION );

	if( !_wc.lpfnWndProc ){
		_wc.style=CS_OWNDC|CS_HREDRAW|CS_VREDRAW;
		_wc.lpfnWndProc=classWndProc;
		_wc.hInstance=GetModuleHandle(0);
		//_wc.hIcon=icon;
		_wc.hCursor=LoadCursor( 0,MAKEINTRESOURCE( (DWORD)IDC_ARROW ) );
		_wc.hbrBackground=(HBRUSH)(COLOR_BTNFACE+1);
		_wc.lpszMenuName=0;
		_wc.lpszClassName=name;
		_wc.cbWndExtra=DLGWINDOWEXTRA;
		RegisterClass(&_wc);
	}
	SetWindowsHookEx( WH_GETMESSAGE,GetMessageProc,GetModuleHandle(0),GetCurrentThreadId() );
	SetWindowsHookEx( WH_KEYBOARD,KeyboardProc,GetModuleHandle(0),GetCurrentThreadId() );
	done=1;
	atexit(freehooks);
	return name;
}


Now open "mod\brl\win32maxgui.mod\win32gui\win32hwnd.h" and add a new function declaration at line 66:

	static const char *className();
	static const char *classNameDialog();


Finally, open "mod\brl\win32maxgui.mod\win32gui\win32window.cpp". Find this line:
	HWND hwnd=CreateWindowEx( xstyle,Win32Hwnd::className(),0,wstyle,0,0,0,0,parent,hmenu,GetModuleHandle(0),0 );

And replace it with this:
	HWND hwnd;
	if ( xstyle&WS_EX_DLGMODALFRAME ) {
		hwnd=CreateWindowEx( xstyle,Win32Hwnd::classNameDialog(),0,wstyle,0,0,0,0,parent,hmenu,GetModuleHandle(0),0 );
		}else{
		hwnd=CreateWindowEx( xstyle,Win32Hwnd::className(),0,wstyle,0,0,0,0,parent,hmenu,GetModuleHandle(0),0 );
		}


That's it! Recompile brl.win32maxgui and you can use icons in windows, and icon-less dialog windows.


JoshK(Posted 2007) [#3]
I just synced mods and followed my own instructions above. If you do exactly what it says, it will work with the latest MaxGUI 1.15.

Why not add this to the official module? I don't know if there is an equivalent in Mac and Linux, but it is an optional windows flag anyways, so I think that is acceptable.


klepto2(Posted 2007) [#4]
sorry, but this was discussed many times before. Only things which will work on all 3 plattforms and are prooved to be usefull will make it to the offical modules.
Believe me I have suggest some things and everytime it was the same explaination.

But your code is very usefull and I have already add it to my
MaxGui. Thx.


JoshK(Posted 2008) [#5]
With MaxGUI.win32maxguiex it is much easier to set this up, and it compiles about 20 times faster, since it is all BlitzMax code!

Open "win32maxguiex.bmx".

1. Add this function inside the TWindowsGUIDriver type. I am going to assume ClassAtom2 is a spare window class, because I could not find it being used anywhere:
	Function DialogClassName$()
		Global _name$
		Global _wc:WNDCLASSW
		'Global _icon
		
		If Not _name
			_name="BLITZMAX_DIALOG_CLASS"
			'_icon=LoadIconW(GetModuleHandleW(Null),Short Ptr(101))
			_wc=New WNDCLASSW
			_wc.style=CS_OWNDC|CS_HREDRAW|CS_VREDRAW
			_wc.lpfnWndProc=ClassWndProc
			_wc.hInstance=GetModuleHandleW(Null)
			'_wc.hIcon=_icon
			_wc.hCursor=LoadCursorW( 0,Short Ptr( IDC_ARROW ) )
			_wc.hbrBackground=COLOR_BTNSHADOW
			_wc.lpszMenuName=Null
			_wc.lpszClassName=_name.ToWString()
			_wc.cbWndExtra=DLGWINDOWEXTRA
			ClassAtom2=RegisterClassW(_wc)
		EndIf
		Return _name
	EndFunction


2. Replace the TWindowsWindow Create() method with this code:
	Method Create:TWindowsWindow(group:TGadget,style)	
		Local	hwnd,parent,client
		
		_style=style
		'_xstyle=|WS_EX_CONTROLPARENT
		_wstyle=WS_CLIPSIBLINGS|WS_VISIBLE|WS_CLIPCHILDREN
		If group Then parent = group.Query(QUERY_HWND)
		
		If style&WINDOW_TITLEBAR 
			_wstyle:|WS_OVERLAPPED|WS_SYSMENU
			If style&WINDOW_RESIZABLE _wstyle:|WS_MINIMIZEBOX|WS_MAXIMIZEBOX

			'=========================================================
			'=========================================================
			'Added this:
			If style&WINDOW_DIALOG _xstyle:|WS_EX_DLGMODALFRAME
			'=========================================================
			'=========================================================
			
		Else
			_wstyle:|WS_POPUP		
		EndIf
		If style&WINDOW_RESIZABLE 
			_wstyle:|WS_SIZEBOX	
		EndIf
		If style&WINDOW_MENU
			_hmenu=CreateMenu_()
			AppendMenuW( _hmenu,MF_STRING,Null,_wstrEmpty )
		EndIf
		If style&WINDOW_TOOL
			_xstyle:|WS_EX_TOOLWINDOW
		EndIf
		If style&WINDOW_HIDDEN
			_wstyle:&~WS_VISIBLE
		End If

		'=========================================================
		'=========================================================
		'Commented out -> hwnd=CreateWindowExW(_xstyle,TWindowsGUIDriver.ClassName(),"",_wstyle,0,0,0,0,parent,_hmenu,GetModuleHandleW(Null),Null)
		'Replaced with this:
		If (WS_EX_DLGMODALFRAME & _xstyle)
			hwnd=CreateWindowExW(_xstyle,TWindowsGUIDriver.DialogClassName(),"",_wstyle,0,0,0,0,parent,_hmenu,GetModuleHandleW(Null),Null)			
		Else
			hwnd=CreateWindowExW(_xstyle,TWindowsGUIDriver.ClassName(),"",_wstyle,0,0,0,0,parent,_hmenu,GetModuleHandleW(Null),Null)
		EndIf
		'=========================================================
		'=========================================================
				
		If style&WINDOW_STATUS
			_status=CreateWindowExW(0,"msctls_statusbar32","",WS_CHILD|WS_VISIBLE,0,0,0,0,hwnd,0,GetModuleHandleW(Null),Null)
			client=CreateWindowExW(0,TWindowsGUIDriver.ClassName(),"",WS_CHILD|WS_VISIBLE|WS_CLIPCHILDREN|WS_CLIPSIBLINGS,0,0,0,0,hwnd,0,GetModuleHandleW(Null),Null)
			SetWindowPos( _status, HWND_TOPMOST,0,0,0,0,SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOSIZE)
		EndIf
		Register GADGET_WINDOW,hwnd,client,False

		If style&WINDOW_ACCEPTFILES
			DragAcceptFiles _hwnd,True
		EndIf		
		Return Self
	EndMethod


3. Declare the constant WINDOW_DIALOG=512 somewhere in MaxGUI.MaxGUI or MaxGUI.Win32MaxGUIEx.

4. Recompile MaxGUI.Win32MaxGUIEx and MaxGUI.MaxGUI, if you added the constant in this module.


SebHoll(Posted 2008) [#6]
Hi Leadwerks,

Got back a day or so ago, so I've had time to look into this for.

I don't think that either Linux or Mac OS X have miniature window icons anyway and so a WINDOW_DIALOG flag would be somewhat obsolete if removing the icon was the only difference.

How about if we simply got MaxGUI to make all child windows (i.e. windows with a parent specified) iconless on Windows. All dialog boxes tend to be parented to a main window. I think that would certainly be more keeping with the apparent Windows GUI design guidelines.

Another approach, would be to think more in depth about about how a MaxGUI dialog window should be implemented on each platform. For example, on OS X dialog are usually presented in the form of a sheet.



These tend to be used for dialog boxes parented to a main window. Standard dialog boxes are pretty much normal windows.

Also, should a WINDOW_DIALOG window be sticky (i.e. always-on-top) for, similar to WINDOW_TOOL?

Finally, should it be modal, and if so how do we handle such modal behaviour using the current MaxGUI framework.

The FLTK framework is pretty basic, so a WINDOW_DIALOG window will probably have no effect on Linux.

Anyone any thoughts on any of the ideas above?


JoshK(Posted 2008) [#7]
I think making child windows icon-less is the best solution.


SebHoll(Posted 2008) [#8]
OK, please checkout the latest MaxGUI changes (rev. 83), build modules and let me know how you get on.

Anyone else have any strong views about this new behaviour?


grable(Posted 2008) [#9]
I liked it, it made MaxIDE-CE look better at least =)


JoshK(Posted 2008) [#10]
It works great.


Ked(Posted 2008) [#11]
This is great! Thanks, Seb.


SebHoll(Posted 2008) [#12]
Fantastic! I've just committed the tweak to the older MaxGUI.Win32MaxGUI module too, just in case anyone out there is still using it.


Grisu(Posted 2008) [#13]
Excellent!