How To Create Window with CreateWindowEx ?

Archives Forums/Win32 Discussion/How To Create Window with CreateWindowEx ?

regaa(Posted 2005) [#1]
I fail badly when i try to create a window with this api-call.

here is the code: (i am sure there are lot of bugs or so, but the compiler does not complain)




SillyPutty(Posted 2005) [#2]
dont you need to create a WNDCLASSEX structure and call RegisterClassEx before calling the createwindow function ?


regaa(Posted 2005) [#3]
good question! is there anybody who have basic winapi knowledge with some bm examples?


SillyPutty(Posted 2005) [#4]
I just checked in the msdn, it says you need to register the class before makking a call to createwindow.


regaa(Posted 2005) [#5]
Ok, thank you very much. I will post the next error in a few minutes as i will make some errors^^.

1st problem:

msdn say:

he RegisterClassEx function registers a window class for subsequent use in calls to the CreateWindow or CreateWindowEx function.

Syntax

ATOM RegisterClassEx(

CONST WNDCLASSEX *lpwcx
);

Parameters

lpwcx
[in] Pointer to a WNDCLASSEX structure. You must fill the structure with the appropriate class attributes before passing it to the function.





WNDCLASSEX should look like this:

typedef struct {
UINT cbSize;
UINT style;
WNDPROC lpfnWndProc;
int cbClsExtra;
int cbWndExtra;
HINSTANCE hInstance;
HICON hIcon;
HCURSOR hCursor;
HBRUSH hbrBackground;
LPCTSTR lpszMenuName;
LPCTSTR lpszClassName;
HICON hIconSm;
} WNDCLASSEX, *PWNDCLASSEX;

How to do this in BM?


SillyPutty(Posted 2005) [#6]
lol yeah, that is where I fell over :)

I am sure someone here knows how :)


Kev(Posted 2005) [#7]
heres a c function from my max gui module thats still in development.


// The name of our window class.
TCHAR szClassName[] = TEXT("MicroMax_CLASS") ;

//
int CLASS_GOOD;

// Creates GUI Window.
int MicroMax_CreateWindow(LPCTSTR szWindowText,int x,int y,int width,int height,int group,int flags){
	
	HINSTANCE hThisInstance = GetModuleHandle(0);
	
	if(!CLASS_GOOD){
	
  		// Window class structure.
  		WNDCLASSEX wcx ;

  		// Now we must fill in the members of WNDCLASSEX.
  		wcx.hInstance     = hThisInstance;
  		wcx.lpszClassName = szClassName ;
  		wcx.lpfnWndProc   = (WNDPROC)MicoMaxWinProc;
  		wcx.style         = CS_DBLCLKS;
  		wcx.hIcon         = LoadIcon (NULL, IDI_APPLICATION);
  		wcx.hIconSm       = LoadIcon (NULL, IDI_APPLICATION);
  		wcx.hCursor       = LoadCursor (NULL, IDC_ARROW);
  		wcx.lpszMenuName  = NULL;
  		wcx.cbSize        = sizeof (WNDCLASSEX);
  		wcx.cbClsExtra    = 0;
  		wcx.cbWndExtra    = 0;
  		wcx.hbrBackground = GetSysColorBrush(COLOR_3DFACE) ;

  		// Register our window class with the operating system.
  		// If there is an error, exit program.
  		if ( !RegisterClassEx (&wcx) )
  		{
    		MessageBox( 0, TEXT("Failed to register window class!"),TEXT("Error!"), MB_OK|MB_ICONERROR ) ;
    		return 0;
  		}
		
		// class created.
		CLASS_GOOD = TRUE;
	}

	//	
	int child_window=1;

	if(!group){
		group = (int)HWND_DESKTOP;
		child_window=0;
	}else{
		child_window=1;
	}
	
	HWND hwnd = CreateWindowEx ( 0, szClassName, szWindowText, WS_OVERLAPPEDWINDOW|WS_VISIBLE, x, y, width, height,(HWND)group,  0, hThisInstance, 0 ); 
	
	if(child_window==1){
		SetParent(hwnd,(HWND)group);
	}
	
	if ( !IsWindow(hwnd) ) { 
		return 0;
	}
			
	return (int)hwnd;
	
}



kev


SillyPutty(Posted 2005) [#8]
here is my feeble attempt, maybe it might help :(

Global CreateWindowEx(window,Title$z,message$z, flags,x,y,w,h,Parent,guiid, hInstance,dunno);
Global RegisterClassEx(wndclassex:WNDCLASSEX);
Global GetModuleHandle(modname$);

Const WS_OVERLAPPED	= 0
Const WS_VISIBLE	= $10000000

user32 = LoadLibraryA ("user32.dll")
Kernel32 = LoadLibraryA ("Kernel32.dll")
If user32=Null
	Notify("Konnte user32.dll nicht laden.")
Else
	CreateWindowEx=GetProcAddress(user32,"CreateWindowExA")
	RegisterClassEx=GetProcAddress(user32,"RegisterClassExA")
	GetModuleHandle=GetProcAddress(Kernel32,"GetModuleHandleA")
EndIf

If user32=Null
	Notify("Konnte Kernel32.dll nicht laden.")
Else
	GetModuleHandle=GetProcAddress(Kernel32,"GetModuleHandleA")
EndIf




myInstance% = GetModuleHandle(Null)

Type WNDCLASSEX
	Field size%
	Field style%
	Field lpfnWndProc%
	Field extra%
	Field wndExtra%
	Field hInstance%
	Field hIcon%
	Field hCursor%
	Field bg%
	Field menuname$
	Field classname$
	Field hIconSm%
End Type

wnd:WNDCLASSEX = New WNDCLASSEX
wnd.size = SizeOf(WNDCLASSEX)
wnd.style = CS_HREDRAW
wnd.lpfnWndProc = Null
wnd.extra = DLGWINDOWEXTRA
wnd.wndExtra=0
wnd.hInstance = myInstance 
wnd.hIcon=0
wnd.hCursor=0
wnd.bg=COLOR_WINDOW
wnd.menuname=Null
wnd.classname="test"
wnd.hiconsm=Null


If Not RegisterClassEx(wnd) Then Notify("could not register class")


If Not CreateWindowEx(0,"test","test window",WS_OVERLAPPED | WS_VISIBLE,0,0,640,480,0,0,myInstance ,Null) Then Notify("could not create window") 



While Not KeyDown(KEY_ESCAPE)
Wend





Kev(Posted 2005) [#9]
without testing Deux example, wnd.lpfnWndProc needs to be an address of a function.

some thing like this, we need the address of the winproc.

Local WinProcADDR:Byte Ptr = WinProc
If WinProcADDR > Null Then
	Print "winproc addr obtained "
EndIf

Function WinProc(hWnd:Int,Msg:Int,wParam:Int,lParam:Int)

End Function 


kev


SillyPutty(Posted 2005) [#10]
yeah, I just rearranged code, never really tested it myself, sorry for not doing that.

I have been looking at the user32.bmx code, and I think that may be helpful for regaa, the constants and functions you need are in there I think.


Kev(Posted 2005) [#11]
here you go a working example using just blitzmax, this creates a window and waits for the close button.


Import "-luser32"
Extern 
	Function GetSysColorBrush:Int(nIndex:Int) = "GetSysColorBrush@4"
End Extern

Const COLOR_BTNFACE = 15

Local WinProcADDR:Byte Ptr = WinProc
If WinProcADDR > Null Then
	Print "winproc addr obtained "
EndIf

Local classname$ = "WindowCLASS"
Local CLASSNAME_ADRR:Byte Ptr = Byte Ptr classname$

Local class:WNDCLASS = New WNDCLASS
Local classADDR:Byte Ptr = Byte Ptr class 
class.hInstance = GetModuleHandleA(0)
class.lpfnWndProc = WinProcADDR
class.lpszClassName = CLASSNAME_ADRR
class.hbrBackground = GetSysColorBrush(COLOR_BTNFACE) 

If(RegisterClassA(classADDR) <> Null) Then
	Print "class reg ok"
EndIf

Local message:MSG = New MSG
Local messageADDR:Byte Ptr = Byte Ptr message

Local windowTitle$ = "Testing"
Local windowTitleADDR:Byte Ptr = Byte Ptr windowTitle$

Const WS_CAPTION = $C00000
Const WS_SYSMENU = $80000
Const WS_VISIBLE = $10000000
Const WS_MINIMIZEBOX = $20000
Const WS_MAXIMIZEBOX = $10000

Const WM_DESTROY = 2

Local lpParamADDR:Byte Ptr

Local window = CreateWindowExA( 0,CLASSNAME_ADRR,windowTitleADDR,WS_CAPTION | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU | WS_VISIBLE,100,100,200,200,0,0,GetModuleHandleA(0),lpParamADDR )

While Not KeyDown(KEY_ESCAPE) 
	GetMessageA(messageADDR,0,0,0)
	TranslateMessage(messageADDR)
	DispatchMessageA(messageADDR)
Wend 


'
'
'
Function WinProc(hWnd:Int,Msg:Int,wParam:Int,lParam:Int)
	
	Select Msg
		
		Case WM_DESTROY
			Notify "Bye!"
			End
			
	End Select
	
	Return DefWindowProcA(hWnd,Msg,wParam,lParam)
	
End Function 



needs cleaning up.

kev.


regaa(Posted 2005) [#12]
many thanks to that much examples. i will check'em out. god job dudes :P


Difference(Posted 2005) [#13]
Very cool kev. Thanks!


regaa(Posted 2005) [#14]
I tryed to extend some parts, but whenever i use SendMessage (declared in user32.bmx) i get this error:

undefined reference to `SendMessage@16

:(


Kev(Posted 2005) [#15]
regaa im not sure why you get the error, but this will work.

add the sendmessage to the extern ... end extern

 
	Function SendMessage:Int(hWnd:Int,MSG:Int,wParam:Int,lParam:Int) = "SendMessageA@16"



then to test use SendMessage window,WM_DESTROY,0,0 after creating the window.

kev


regaa(Posted 2005) [#16]
Thank you very much. I've learned some important BM basics :p .


SillyPutty(Posted 2005) [#17]
wow very cool, awsome kev !

Thanks


Difference(Posted 2005) [#18]
Here's one with some buttons and a keypress - you can press [ESC] to quit.




Kev(Posted 2005) [#19]
just to make a note, under WM_COMMAND the HIWORD(wParam) specifies the notification code if the message is from a control, this will be 0 if the message is from a menu, the ID of the menu is found in the LOWORD(wParam)

heres 2 functions to get the low and hi words.


Function LOWORD(value)
	Return value And $FFFF
End Function

Function HIWORD(value)
	Return (value Shr 16)
End Function



kev


Difference(Posted 2005) [#20]
I'm trying to add a font, but my CreateFont call makes Blitz quit:




Difference(Posted 2005) [#21]
I can add a font to ONE control using this code, adding the font to more than one control makes Blitz quit:




Kev(Posted 2005) [#22]
this is how i do it in winblitz3d. you shold be able to convert this easy.


Function OpenFont(fontname$,width=12,height=8,bold=0,italic=0,underline=0)
	
	font = apiCreateFont(width,height,0,0,bold,underline,0,0,0,0,0,0,0,GRAB_StringAddr(fontname$))
	Return font 

End Function

Function Usefont(gadget,font)

	hdc = apiGetWindowDC(gadget)
	hfontprev = apiSelectObject(hdc,font)
	
	apiSendMessage gadget,WM_SETFONT,apiSelectObject(hdc,font),1
		
End Function



kev


Difference(Posted 2005) [#23]
Thanks, kev. I see I've been doing it all wrong, I'll make those SelectObject() changes and try again.


Difference(Posted 2005) [#24]
I'm still having troubles: http://www.blitzbasic.com/Community/posts.php?topic=50237 :)


Difference(Posted 2005) [#25]
btw : LOWORD needs to be changed to: ("&" not "AND" )

Function LOWORD(value)
	Return value & $FFFF
End Function



ftbass(Posted 2006) [#26]
Hi,
I'm late...
Can anyone make this code by Kev work with the latest version of BlitzMax :

Import "-luser32"
Extern 
	Function GetSysColorBrush:Int(nIndex:Int) = "GetSysColorBrush@4"
End Extern

Const COLOR_BTNFACE = 15

Local WinProcADDR:Byte Ptr = WinProc
If WinProcADDR > Null Then
	Print "winproc addr obtained "
EndIf

Local classname$ = "WindowCLASS"
Local CLASSNAME_ADRR:Byte Ptr = Byte Ptr classname$

Local class:WNDCLASS = New WNDCLASS
Local classADDR:Byte Ptr = Byte Ptr class 
class.hInstance = GetModuleHandleA(0)
class.lpfnWndProc = WinProcADDR
class.lpszClassName = CLASSNAME_ADRR
class.hbrBackground = GetSysColorBrush(COLOR_BTNFACE) 

If(RegisterClassA(classADDR) <> Null) Then
	Print "class reg ok"
EndIf

Local message:MSG = New MSG
Local messageADDR:Byte Ptr = Byte Ptr message

Local windowTitle$ = "Testing"
Local windowTitleADDR:Byte Ptr = Byte Ptr windowTitle$

Const WS_CAPTION = $C00000
Const WS_SYSMENU = $80000
Const WS_VISIBLE = $10000000
Const WS_MINIMIZEBOX = $20000
Const WS_MAXIMIZEBOX = $10000

Const WM_DESTROY = 2

Local lpParamADDR:Byte Ptr

Local window = CreateWindowExA( 0,CLASSNAME_ADRR,windowTitleADDR,WS_CAPTION | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU | WS_VISIBLE,100,100,200,200,0,0,GetModuleHandleA(0),lpParamADDR )

While Not KeyDown(KEY_ESCAPE) 
	GetMessageA(messageADDR,0,0,0)
	TranslateMessage(messageADDR)
	DispatchMessageA(messageADDR)
Wend 


'
'
'
Function WinProc(hWnd:Int,Msg:Int,wParam:Int,lParam:Int)
	
	Select Msg
		
		Case WM_DESTROY
			Notify "Bye!"
			End
			
	End Select
	
	Return DefWindowProcA(hWnd,Msg,wParam,lParam)
	
End Function 


This would be great :)


klepto2(Posted 2006) [#27]
Just to clarify ;) you all know that these functions are already shipped with Blitzmax?
If not, then take a look to the pub.win32 module. this module already gives you everything you need (structs and functions) for these things.


ftbass(Posted 2006) [#28]
Thanks, I'll take a look :)


Jan_(Posted 2006) [#29]
hm, there is an Problem with the Maximize

Strict 

Framework PUB.Win32 
Import BRL.System 
Import BRL.EventQueue 
Import BRL.basic 

Extern "Win32" 
   Function UpdateWindow(hWnd) 
End Extern 


Global CLASS_NAME:Byte Ptr="bbW32 Window".ToCString() ' Wie heißt unsere Anwendung 
Global hinst=GetModuleHandleA(0) ' was ist uinsere instance 


Local hwnd%=CreateHWND(600,400,0,"Jan_'s Win32 Application".ToCString()) ' Fenster erstellen 
'showwindow(hwnd,sw_show) ' fenster Zeigen 
'showwindow(hwnd,sw_hide) ' fenster verstecken 
Local ende% 
Repeat 
   WaitEvent() ' warten, das was passiert, das wichtig ist --> 0% CPU last 
   ende=True 
Until (ende=True) 

DestroyWindow(hWnd) ' das Fenster wieder löschen 
End 

Function WndProc( hwnd,message,wp,lp ) "win32" 
   Local event:TEvent 

   Select message ' hier reagieren wir auf die aktionen die der nutzer auslöst 
   Case WM_CLOSE ' schließen 
      event=New TEvent 
      PostEvent(event) ' so, das sendet an Waitevent das es was machen soll (siehe oben) 
      postquitmessage(0) 
      DestroyWindow(hWnd) 
      End 
      Return 
   Case WM_DESTROY ' zerstören 
      event=New TEvent 
      PostEvent(event) ' so, das sendet an Waitevent das es was machen soll (siehe oben) 
      postquitmessage(0) 
      DestroyWindow(hWnd) 
      End 
      Return 
   Case WM_MOVE ' bewegen 
      'updatewindow(hwnd) 
      Return 
   Case WM_SIZE 
      'bbSystemEmitOSEvent hwnd,message,wp,lp,Null 
      'updatewindow(hwnd) 
      Return 
   Case WM_Paint 
      updatewindow(hwnd) 
      Return 
'   Case WM_MOUSEMOVE 
   'Default 
      'bbSystemEmitOSEvent hwnd,message,wp,lp,Null 
   End Select 
   Return DefWindowProcA( hwnd,message,wp,lp ) 
End Function 

Function CreateHWND(width,height,fullscreen,WINDOW_TITLE:Byte Ptr,PosX%=100,PosY%=100) ' Fenster erstellen 
    
   Local style,ex_style,hwnd 
   Local hinst=GetModuleHandleA(0) 
    
   Global wndClas 
    
   If Not wndClas 
      Local wc:WNDCLASS=New WNDCLASS 
      Local hinst=GetModuleHandleA(0) 
      'Local icon:Byte Ptr="IDI_INFORMATION".ToCString() 
      wc.style=CS_HREDRAW Or CS_VREDRAW ' Fensterstyle 
      wc.lpfnWndProc=WndProc 'Zeiger auf die Fensterprozedur 
      wc.cbClsExtra=0 
      wc.cbWndExtra=0 
      wc.hInstance=hinst ' Instanz des Programms 
      wc.hIcon=LoadIconA(Null, Null) 'Handle eines Icons das z.B. mit LoadIcon() geladen wurde 
      wc.hbrBackground = GetStockObject (LTGRAY_BRUSH) 
      wc.hCursor=LoadCursorA( Null,Byte Ptr IDC_ARROW ) 'Handle eines Cursors 
      wc.lpszClassName=CLASS_NAME ' Name der zu registrierenden Fensterklasse 
      wndClas=RegisterClassA( wc ) 
      If Not wndClas 
         Throw "Failed to register window class" 
      EndIf 
   EndIf 

   ex_style=WS_EX_TRANSPARENT 
   style=WS_VISIBLE|WS_SYSMENU|WS_CAPTION|WS_MAXIMIZEBOX|WS_MINIMIZEBOX|WS_SIZEBOX'|WS_SYSMENU 
    
   Local rect[]=[posx,posy,width+posx,height+posy] 

   hWnd=CreateWindowExA(.. 
      ex_style,.. 
      CLASS_NAME,.. 
      WINDOW_TITLE,.. 
      style,.. 
      posx,posy,width,height,.. 
      0,0,hinst,Null) 
   ShowWindow(hWnd,SW_SHOW); 

   MemFree WINDOW_TITLE 
   If Not hwnd Throw "Failed to create window" 
   Return hwnd 
End Function