Chronial gave the best answer. I will give what I think is a useful refinement.
Chronial's concept was to allow use of cpp throw mechanism inside your window procedure, but dont let it propogate outside of the window procedure; which is called in a C library and leads to undefined behaviour on 64 bit windows, namely 64 bits win 7 or windows 8. Instead catch the exception within the window procedure, and save it in a global variable, which you rethrow in your cpp main function and make use of. See Chronial's answer for code example.
The concept is simple, but requires a bit of detail to get 100% right.
One pitfall to avoid is not destroying the window you throwed from. Your code will clean up all objects declared in the try block, but the window object you create will still be alive and handling messages. Even though you are no longer dispatching messages. If you use pointers in the window procedure, these pointers may be invalid when your code is in your catch block, while windows is still pumping messages to your window which you didn't destroy.
Every window procedure needs to have this try catch, save exception technique. It won't work if only your top level window is prepared, but exceptions are thrown in it's child window's procedure.
If the first two were super obvious, this one is slightly non-obvious. For your top level window's procedure; in addition to try catch the entire switch statement, you should also try catch the WM_CREATE message, and return -1 if you caught an exception. This will prevent the window and its children from being created; and save you from having to destroy the window once you rethrow the exception.
Lastly once again in your WM_CREATE message of your top level window, after running the code that created child windows, check if those child windows set the global windowProcException variable. Creation of child windows will run their own windowProcedure, and exceptions caught in those window procedures will not automatically propogate to your top level window's procedure. If exceptions happened in the child's window procedure, returning -1 from the top level window will cancel creation of all windows. Unless, you decide that a particular child window was not super important.
void createChildWindows();
windowProcedure(hwnd,msg,wparam,lparam)
{
try
{
try
{
if(msg == WM_CREATE)
{
createChildWindows();
return windowProcException ? -1 : 0;
}
}
catch(...)
{
windowProcException = std::current_exception();
return -1;
}
return DefWindowProc(hwnd,msg,wparam,lparam);
}
catch(...)
{
windowProcException = std::current_exception();
//MingGw won't complain if you don't return a value;
//MSVC might
//As far as I am concerned, we are throwing,
//so any value returned is undefined
//We must however be careful with WM_CREATE as that return code
//dictates whether or not window creation continues
}
}
GetLastError
and the like appropriately. Propagate results if calling from a function called withinWindowProc
. – Libau