🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Win32 Window Creation

Started by
19 comments, last by Buckeye 9 years, 8 months ago

I'm creating an Win32 Window to serve as the primary surface to make DirectX and OpenGL calls. The problem is that is more intuitive to create the window first, initialize the API and load graphics resources (Shaders, Textures, Vertex Streams), and after that start with the simulation loop, but I don't know that if there is some internal problem - maybe with the Windows platform - in this create-load-show interval. Another thing is that I'm using the main thread to bufferize keyboard events. Eg.:


/*
* Initialize and Win32 Window to be showed later.
*/

BOOL CWindow::Init(const std::wstring& _sTitle, unsigned int _ui32Width, unsigned int _ui32Height, bool /*_bFullscreen*/) {
	WNDCLASSEX wcex;
	wcex.cbSize = sizeof(WNDCLASSEX);
	wcex.style = CS_OWNDC;
	wcex.lpfnWndProc = CWindow::WndProc;
	wcex.cbClsExtra = 0;
	wcex.cbWndExtra = 0;
	wcex.hInstance = ::GetModuleHandle(NULL);
	wcex.hIcon = NULL;
	wcex.hCursor = ::LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW + 1);
	wcex.lpszMenuName = NULL;
	wcex.lpszClassName = _sTitle.c_str();
	wcex.hIconSm = ::LoadIcon(NULL, IDI_APPLICATION);

	if ( !::RegisterClassEx(&wcex) ) { return false; }

	m_hWnd = ::CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, wcex.lpszClassName, wcex.lpszClassName,
		WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 
		CW_USEDEFAULT, CW_USEDEFAULT, _ui32Width, _ui32Height, 
		NULL, NULL, wcex.hInstance, reinterpret_cast<LPVOID>(this) );

	return m_hWnd ? true : false;
}

Looks more intuitive than the create-show-load approach, but I don't know if I'm going to lose window events in the interval of the above implementation so after the initialization I can call:


int CWindow::Run() {
::SetThreadPriority(::GetCurrentThread(), THREAD_PRIORITY_HIGHEST);


MSG msg = { 0 };
while (m_bIsOpen) {
::WaitMessage();
while (::PeekMessage(&msg, m_hWnd, 0, 0, PM_REMOVE)) {
::DispatchMessage(&msg);
}
}
return static_cast<int>(msg.wParam);
}

At the highest level:


m_wWindow.Init(...);
CGraphics::InitApi( m_wWindow.Hwnd() );
m_wWindow.Show(...);
m_wWindow.Run();
Advertisement
FWIW there is literally no good reason I can think of to use raw Win32 rather than something like SDL2. It'll save you a lot of pain, also let you be more portable, and is used increasingly frequently in the AAA space. Some of the framework libraries are GL-only but SDL2 can easily be used with D3D for sure (as come some of the others).

Sean Middleditch – Game Systems Engineer – Join my team!

FWIW there is literally no good reason I can think of to use raw Win32 rather than something like SDL2. It'll save you a lot of pain, also let you be more portable, and is used increasingly frequently in the AAA space. Some of the framework libraries are GL-only but SDL2 can easily be used with D3D for sure (as come some of the others).

The reason that I don't use these kind of libraries is that I want to have full control of what I am doing at the lower level possible for me. I've posted this specific problem but everything else is working fine - OpenGL and DirectX support, etc. From what I've read from the Microsoft Win32 Documentation, it says nothing related the problem I am having.

To be honest. I don't know, but what I do recommend is rather choosing a different way of doing this. I recommend trying out and consider using the Delphi Programming Languages which is the best language to create Windows applications out there.

To be honest. I don't know, but what I do recommend is rather choosing a different way of doing this. I recommend trying out and consider using the Delphi Programming Languages which is the best language to create Windows applications out there.

I disagree. What you have said is totally off-topic. The standard language - not the obrigatory one - to create applications - in my case an Game Engine - that use OpenGL or DirectX as the main Graphics Library API is the C++ Language if the platform you're targeting is Windows.

I'm not sure if you're saying there is a problem, or if you're asking if there might be a problem.

It sounds like you are worried that you could possibly be lose some events between "m_wWindow.Init(...);" and "m_wWindow.Run();".

Aren't the events buffered up and stored for you until you process them? How long does 'InitApi()' take to run? Are you doing alot of heavy resource loading, or are you delaying your resource loading until after Run() begins?

I'm not sure if you're saying there is a problem, or if you're asking if there might be a problem.

It sounds like you are worried that you could possibly be lose some events between "m_wWindow.Init(...);" and "m_wWindow.Run();".

Aren't the events buffered up and stored for you until you process them? How long does 'InitApi()' take to run? Are you doing alot of heavy resource loading, or are you delaying your resource loading until after Run() begins?

Yeah, Mouse and Keyboard events for instance just get added to the Win32 Queue if I have an window that is currently on focus. Since I'm not showing the window in this interval this is not a problem. The same applies to WM_PAINT messages because I'm rendering from an different thread and just after the window is created and showed that I make an draw call.

I am using this approach and I have no problem, but I know that the internal Win32 Message Queue is a mystery unrevealed. Also I'm not having any syncronization issues with DirectX and OpenGL. I know that the correct way of doing this is to initialize the Graphics Library API after the WM_CREATE message, but for the sake of clarity Is better use what I've posted. Another reason is that sometimes there is an delay between the created window and the image to be displayed, so the window gets displayed while loading API resources. In my current setup immediatly my objects gets displayed on the screen without having an delay! smile.png

Each application has its own event queue. Events are not removed from it unless you remove them yourself (Yes, I'm intentionally ignoring the dusty corners of the API and hooks that change this).

They'll be waiting in your queue while you do whatever it is you need to to setup.

However, please note that not pumping your message queue for a length of time will cause Windows to assume you've frozen and grey the window out, put "not responding" in the title, and may ask the user if they want to terminate. So you should probably be processing your messages while you do whatever lengthy task you're doing on startup.

Each application has its own event queue. Events are not removed from it unless you remove them yourself (Yes, I'm intentionally ignoring the dusty corners of the API and hooks that change this).

They'll be waiting in your queue while you do whatever it is you need to to setup.

However, please note that not pumping your message queue for a length of time will cause Windows to assume you've frozen and grey the window out, put "not responding" in the title, and may ask the user if they want to terminate. So you should probably be processing your messages while you do whatever lengthy task you're doing on startup.

I know. I've spend quite a lot of time with the Win32 API, but I don't know every possible type of WM_X message. The Win32 Window Initialization and the Win32 Message Pump are single threaded. Now I'm going to assume the following pseudo-code:

The standard way:

CreateWindow() ->

ShowWindow() ->

InitializeGraphicsAPI() ->

LoadGraphicsResources() /*The window will be showed while I'm loading the resources. */ ->

StartSimulationLoop()

What I really need:

CreateWindow() ->

InitializeGraphicsAPI() ->

LoadGraphicsResources() ->

ShowWindow() /*Alright, I can see my rendered image immediately after the window gets showed.*/ ->

StartGameSimulation()


What I really need:

CreateWindow() ->
InitializeGraphicsAPI() ->
LoadGraphicsResources() ->
ShowWindow() /*Alright, I can see my rendered image immediately after the window gets showed.*/ ->
StartGameSimulation()

I'm not sure if this answers your concern:

In CreateWindow(), after the window is created, call:

ShowWindow( hWnd, SW_HIDE );

Your ShowWindow() is then:

ShowWindow( hWnd, SW_SHOW );

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

This topic is closed to new replies.

Advertisement