winapi destroyWindow() immediately exits my program - c++

Okay, i can understand if the function would return an error or throw an exception, but for some reason my call to DestroyWindow literally exits the program at that point. Like with the actual exit() function changing my program flow. The documentation mentions nothing like this and i have no means of figuring out what is going on since i get no error code. Has anyone ever encountered something like this?
I'm doing quite a bit more with this object than using winapi, so ignore the rest of it. What else could be wrong here?
SYNC_WinSystem.h
#ifndef SYNC_WINSYSTEM_H
#define SYNC_WINSYSTEM_H
#include "SYNC_ISystem.h"
#include <Windows.h>
#include <array>
#include "SYNC_Winput.h"
#include "SYNC_IRenderer.h"
#include "SYNC_D3D11Renderer.h"
#define FULL_SCREEN true
// SYNC_WinSystem
class SYNC_WinSystem : public SYNC_ISystem
{
public:
class WindowsContext;
SYNC_WinSystem();
virtual long Initialize(InitializeContext *);
virtual void Init_Loop();
virtual void Shutdown();
virtual long MakeDirectory(std::string);
virtual bool CreateSkin(std::string, std::string, SYNC::ISkin *&);
virtual ISound * CreateSound();
LRESULT CALLBACK MessageHandler(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
private:
virtual long InitializeWindows();
virtual bool Frame();
virtual void ShutdownWindows();
private:
SYNC_Winput m_Input;
private:
std::shared_ptr<SYNC_IRenderer> m_Graphics;
HINSTANCE m_hinstance;
HWND m_hwnd;
int m_screenWidth;
int m_screenHeight;
std::string m_WindowName;
};
// SYNC_WinSystem::WindowsContext
class SYNC_WinSystem::WindowsContext : public SYNC_ISystem::InitializeContext
{
public:
WindowsContext();
std::string Type();
HINSTANCE m_hinstance;
std::string m_WindowName;
private:
const static std::string m_Identifier;
};
#endif
SYNC_WinSystem.cpp
#include "SYNC_WinSystem.h"
// SYNC_WinSystem definitions
SYNC_WinSystem * g_windows;
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
SYNC_WinSystem::SYNC_WinSystem()
: m_Graphics(new SYNC_D3D11Renderer)
{
m_hinstance = nullptr;
m_hwnd = nullptr;
m_screenWidth = 0;
m_screenHeight = 0;
}
long SYNC_WinSystem::Initialize(InitializeContext * context)
{
long result = 0;
char errors[256];
WindowsContext * cContext;
if(context->Type() == "WindowsContext")
cContext = static_cast<WindowsContext *>(context);
else
return false;
m_hinstance = cContext->m_hinstance;
m_WindowName = cContext->m_WindowName;
g_windows = this;
result = InitializeWindows();
if(result)
{
sprintf_s(errors, "The Window could not initialize. Windows error code: %i", result);
MessageBox(NULL, errors, "Error!", MB_OK);
return result;
}
std::array<std::string, 3> folderNames=
{{
"Compiled_Models",
"Temp_Models",
"Materials"
}};
for(int i = 0; i < (int) folderNames.size(); i++)
{
result = MakeDirectory(folderNames[i]);
if( result && (result != ERROR_ALREADY_EXISTS))
{
sprintf_s(errors, "Error creating directory \" %s \" for system. Windows error code: %i", folderNames[i].c_str(), result);
MessageBox(NULL, errors, "Error!", MB_OK);
return result;
}
result = 0;
}
SYNC_D3D11Renderer::D3D11Context graphicsContext;
graphicsContext.fullscreen = true;
graphicsContext.hwnd = m_hwnd;
graphicsContext.screenDepth = 1000.0f;
graphicsContext.screenNear = 0.1f;
graphicsContext.screenWidth = m_screenWidth;
graphicsContext.screenHeight = m_screenHeight;
if(!m_Graphics->Initialize(&graphicsContext))
return false;
return result;
}
void SYNC_WinSystem::Init_Loop()
{
MSG msg;
bool done, result;
ZeroMemory(&msg, sizeof(MSG));
done = false;
while(!done)
{
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if(m_Input.IsKeyPressed(VK_ESCAPE))
{
done = true;
}
else
{
result = Frame();
if(!result)
{
done = true;
}
}
}
}
void SYNC_WinSystem::Shutdown()
{
ShutdownWindows();
}
long SYNC_WinSystem::MakeDirectory(std::string dirName)
{
DWORD result = 0;
long returnValue = 0;
dirName.insert(0, ".\\");
result = CreateDirectory(dirName.c_str(), NULL);
if(result == 0)
{
returnValue = GetLastError();
}
return returnValue;
}
bool SYNC_WinSystem::Frame()
{
if(!m_Graphics->Frame())
return false;
return true;
}
long SYNC_WinSystem::InitializeWindows()
{
DWORD result = 0;
WNDCLASSEX wc;
DEVMODE dmScreenSettings;
int posX, posY;
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = &WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = m_hinstance;
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wc.hIconSm = wc.hIcon;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = m_WindowName.c_str();
wc.cbSize = sizeof(WNDCLASSEX);
if(RegisterClassEx(&wc) == 0)
{
result = GetLastError();
return result;
}
m_screenWidth = GetSystemMetrics(SM_CXSCREEN);
m_screenHeight = GetSystemMetrics(SM_CYSCREEN);
if(FULL_SCREEN)
{
memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
dmScreenSettings.dmSize = sizeof(dmScreenSettings);
dmScreenSettings.dmPelsWidth = (unsigned long) m_screenWidth;
dmScreenSettings.dmPelsHeight = (unsigned long) m_screenHeight;
dmScreenSettings.dmBitsPerPel = 32;
dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN);
posX = posY = 0;
m_hwnd = CreateWindowEx(WS_EX_APPWINDOW,
m_WindowName.c_str(),
m_WindowName.c_str(),
WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_POPUP,
posX, posY, m_screenWidth, m_screenHeight,
NULL, NULL, m_hinstance, NULL);
}
else
{
m_screenWidth = 800;
m_screenHeight = 600;
posX = ((GetSystemMetrics(SM_CXSCREEN)/2) - (m_screenWidth/2));
posY = ((GetSystemMetrics(SM_CYSCREEN)/2) - (m_screenHeight/2));
m_hwnd = CreateWindowEx(WS_EX_APPWINDOW,
m_WindowName.c_str(),
m_WindowName.c_str(),
WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_POPUP,
posX, posY, m_screenWidth, m_screenHeight,
NULL, NULL, m_hinstance, NULL);
}
if(!m_hwnd)
{
result = GetLastError();
return result;
}
ShowWindow(m_hwnd, SW_SHOW);
SetForegroundWindow(m_hwnd);
SetFocus(m_hwnd);
return result;
}
void SYNC_WinSystem::ShutdownWindows()
{
ShowCursor(true);
if(FULL_SCREEN)
{
ChangeDisplaySettings(NULL, 0);
}
if(DestroyWindow(m_hwnd) == 0)
{
char meh[256];
sprintf(meh, "error: %i" , GetLastError());
MessageBox(NULL, meh, "error!", MB_OK);
}
m_hwnd = NULL;
UnregisterClass(m_WindowName.c_str(), m_hinstance);
m_hinstance = NULL;
g_windows = NULL;
return;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch(msg)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
case WM_CLOSE:
{
PostQuitMessage(0);
return 0;
}
default:
{
return g_windows->MessageHandler(hwnd, msg, wparam, lparam);
}
}
}
LRESULT CALLBACK SYNC_WinSystem::MessageHandler(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch(msg)
{
case WM_KEYDOWN:
{
m_Input.KeyDown((unsigned int) wparam);
return 0;
}
case WM_KEYUP:
{
m_Input.KeyDown((unsigned int) wparam);
return 0;
}
default:
{
return DefWindowProc(hwnd, msg, wparam, lparam);
}
}
}
ISound * SYNC_WinSystem::CreateSound()
{
return nullptr;
}
bool SYNC_WinSystem::CreateSkin(std::string filename, std::string shaderName, SYNC::ISkin *& skin)
{
if(!m_Graphics->CreateSkin(filename, shaderName, skin))
return false;
return true;
}
// SYNC_WinSystem::WindowsContext definitions
const std::string SYNC_WinSystem::WindowsContext::m_Identifier = "WindowsContext";
SYNC_WinSystem::WindowsContext::WindowsContext()
{
}
std::string SYNC_WinSystem::WindowsContext::Type()
{
return m_Identifier;
}
quick explanation of how i do this. window handle and hinstance have private members in the object, and during the Initialize() and InitializeWindows() functions, the window class and window itself is created. The windows procedure is defined below as a global function, because you can't use a member function as a windows procedure. I dodge around this by making a global pointer (gasp) at the top, and assigning it to the this pointer of the system, which allows the procedure to call a member function procedure. Still only allows one instance of the system, but that's all i need :. Anywho, during shutdown, ShutdownWindows() is called, which then calls DestroyWindow. It is during this call, that my program simply ends, no error, no exception. MSVC++ express tells me it returns error code 3, but as far as windows error codes, that's just an ERROR_PATH_NOT_FIND which makes no sense in this context. Anyone have a clue?
main.cpp
#include <memory>
#include <Windows.h>
#include "Syncopate.h"
#include "SYNC_WinSystem.h"
using namespace std;
#include "SYNC_Winput.h"
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR lpCmdLine, INT nCmdShow)
{
//create a new instance of the engine
std::shared_ptr<SYNC_WinSystem> system( new SYNC_WinSystem);
// create an init context for this specific derivative of SYNC_ISystem
SYNC_WinSystem::WindowsContext context;
context.m_hinstance = hInstance;
context.m_WindowName = "Syncopate";
// Initialize the system object. if something goes wrong, return ERROR
if(system->Initialize(&context))
return 1;
SYNC::ISkin * model;
if(!system->CreateSkin("data.txt", "ColorShader", model))
return 1;
system->Init_Loop();
system->Shutdown();
return 0;
}

There's nothing in your message loop that will notice a WM_QUIT and abort. The "standard" practice for a message loop is to call GetMessage() until it fails, which indicates WM_QUIT, but you're calling PeekMessage() which has no handling for WM_QUIT at all. Your message loop only exits when done is true, which will only happen when escape is pressed or your Frame() call fails.
As you discovered, the solution was to redesign your loop to properly handle WM_QUIT messages and to not call DestroyWindow after the loop has already ended.

What seems to be going on is that you handle the WM_DESTROY message and explicitly call PostQuitMessage. I suspect somewhere that WM_QUIT message is being processed and causing an exit of some sort. I'll see if I can find any further information, but that's my understanding so far.
Rule of Thumb:
When you receive a WM_CLOSE message, call DestroyWindow. When you receive a WM_DESTROY message, call PostQuitMessage. Because you are using PeekMessage, you will get a message structure for a WM_QUIT message. When you find this message, you should end your loop.

IIRC exit code 3 is what you get by calling abort.
Anyway,
case WM_CLOSE:
{
PostQuitMessage(0);
return 0;
}
is very ungood (it terminates your message loop), and most likely the cause of your problems.
Just remove that.
Update: since the above recommendation didn't improve things, I suspect that you're calling DestroyWindow on an already destroyed window.
As a rule you should only call DestroyWindow in response to WM_CLOSE. For general windows that's the default handling. There is no indication in the presented code (as I'm writing this) of how your "shutdown" code is called, but due to the identical handling of WM_CLOSE and WM_DESTROY I suspect that it's a call placed after the message loop.
And in that case it is indeed likely that you're calling DestroyWindow on an already destroyed window.

Related

Awesomium WebView doesn't display page

I've made two simple classes to use for displaying UIs with Awesomium. However creating the Awesomium WebView and setting the parent window to my Win32 window causes the program to hang and the page is never displayed. The classes are simple and creating a window is simple so there isn't much I can think of that could be going wrong. Perhaps there is something else required than what I've done to display a WebView?
To clarify: Creating the Win32 window without creating the WebView works fine, the window functions including the drag code etc... The hang only happens when you call set_parent_window.
UI.h
#pragma once
#include <Windows.h>
#include <windowsx.h>
#include <Awesomium/WebCore.h>
#include <Awesomium/STLHelpers.h>
using namespace Awesomium;
LRESULT CALLBACK LoginUICallback(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
class UI
{
public:
//Window Variables
HINSTANCE instance;
HWND window;
BOOL drag_window = false;
SHORT mouse_x, mouse_y, mouse_x_prev, mouse_y_prev;
//Awesomium Variables
WebCore* webcore = 0;
WebView* webview;
static HWND InitWindow(INT width, INT height, WNDPROC callback)
{
HWND hwnd;
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = callback;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = GetModuleHandle(0);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = "MyUI";
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if (!RegisterClassEx(&wc))
{
char msg[100];
sprintf(msg, "System Error: %i", GetLastError());
MessageBox(NULL, msg, "ERROR", MB_OK);
return NULL;
}
hwnd = CreateWindow("MyUI",
"",
WS_POPUP,
CW_USEDEFAULT,
CW_USEDEFAULT,
width,
height,
NULL,
NULL,
GetModuleHandle(0),
NULL);
if (!hwnd)
{
char msg[100];
sprintf(msg, "System Error: %i", GetLastError());
MessageBox(NULL, msg, "ERROR", MB_OK);
return NULL;
}
ShowWindow(hwnd, SW_SHOWNORMAL);
UpdateWindow(hwnd);
SetTimer(hwnd, 0, 15, NULL);
return hwnd;
}
};
class LoginUI : public UI
{
public:
INT width = 600;
INT height = 600;
INT RunUI()
{
this->window = UI::InitWindow(this->width, this->height, ::LoginUICallback);
if (!this->window)
return 0;
WebConfig config;
this->webcore = WebCore::Initialize(config);
this->webview = this->webcore->instance()->CreateWebView(this->width, this->height, 0, kWebViewType_Window);
this->webview->set_parent_window(this->window);
this->webview->LoadURL(WebURL(WSLit("http://www.google.com")));
MSG msg;
while(GetMessage(&msg, this->window, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
WebCore::Shutdown();
return 1;
}
}login_ui;
LRESULT CALLBACK LoginUICallback(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
case WM_TIMER:
break;
case WM_MOUSEMOVE:
{
if (login_ui.drag_window && (wParam & MK_LBUTTON))
{
// code executed when the dialog window is moved around on the screen
RECT win_rect;
GetWindowRect(hWnd, &win_rect);
int x_coord = GET_X_LPARAM(lParam);
int y_coord = GET_Y_LPARAM(lParam);
MoveWindow(hWnd,
win_rect.left + x_coord - login_ui.mouse_x_prev,
win_rect.top + y_coord - login_ui.mouse_y_prev,
win_rect.right - win_rect.left,
win_rect.bottom - win_rect.top,
false
);
}
break;
}
case WM_LBUTTONDOWN:
{
login_ui.mouse_x = GET_X_LPARAM(lParam);
login_ui.mouse_y = GET_Y_LPARAM(lParam);
if (login_ui.mouse_y < 41)
{
login_ui.mouse_x_prev = login_ui.mouse_x;
login_ui.mouse_y_prev = login_ui.mouse_y;
SetCapture(hWnd);
login_ui.drag_window = true;
}
break;
}
case WM_LBUTTONUP:
{
if (login_ui.drag_window)
{
login_ui.drag_window = false;
ReleaseCapture();
}
break;
}
case WM_SIZE:
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_QUIT:
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
Main.Cpp
#include "UI.h"
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE, char*, int nCmdShow)
{
login_ui.RunUI();
}
Have not used Awesomium but your GetMessage only pumps messages for the WebCore window. So instead you should pass NULL so your message pump dispatches messages for all windows created on that thread.

Windows C++ - Creating window in a class makes it look unusual

Ok, so i made a class which creates a HWND.
However, the window created shows some strange properties: it is not like other windows - it's non-transparent, the close-minimize-maximize buttons are located differently from normal windows.
But the style specified is default (WM_OVERLAPPEDWINDOW).
What's more, it can't be closed unless i move it a bit (seems like it is not generating WM_DESTROY or WM_CLOSE messages before moving).
This might be a problem with the implementation of main WinProc calling another message processer using pointers. However, i have no idea why the window is unusually looking.
My code:
//mywind.h
class Window
{
private:
HWND mHwnd;
const char* className="Window";
static LRESULT CALLBACK StartWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); //main WindowProc function
LRESULT ThisWindowProc(UINT msg, WPARAM wParam, LPARAM lParam); //Another, object-specific message processing function
bool isClassRegistered(HINSTANCE hinst);
public:
Window() : mHwnd( 0 ) { }
~Window();
int create(std::string title, int width, int height);
};
//mywind.cpp
Window::~Window()
{
if( mHwnd ) DestroyWindow( mHwnd );
}
int Window::create(std::string title, int width, int height)
{
WNDCLASS wincl;
HINSTANCE hInst = NULL;
hInst = GetModuleHandle(NULL);
if(hInst==NULL)
{
printf("Failed to load hInstance\n");
return -1;
}
if(!GetClassInfo(hInst, className, &wincl))
{
printf("Getting class info.\n");
wincl.style = 0;
wincl.hInstance = hInst;
wincl.lpszClassName = className;
wincl.lpfnWndProc = StartWindowProc;
wincl.cbClsExtra = 0;
wincl.cbWndExtra = 0;
wincl.hIcon = NULL;
wincl.hCursor = NULL;
wincl.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
wincl.lpszMenuName = NULL;
if(!isClassRegistered(hInst))
{
if (RegisterClass(&wincl) == 0)
{
printf("The class failed to register.\n");
return 0;
}
}
}
mHwnd = CreateWindow(className, title.c_str(), WS_VISIBLE | WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, width, height,
NULL, NULL, hInst, this);
if(mHwnd==NULL)
{
printf("Failed to create HWND.\n");
return -1;
}
MSG msg;
while(GetMessage(&msg, mHwnd, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
printf("Destroying window.\n");
if(mHwnd) DestroyWindow(mHwnd);
mHwnd=NULL;
printf("Returning.\n");
return msg.wParam;
}
bool Window::isClassRegistered(HINSTANCE hinst)
{
WNDCLASSEX clinf;
if(!GetClassInfoEx(hinst, className, &clinf)) return false;
return true;
}
LRESULT CALLBACK Window::StartWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
Window* winp = NULL;
if(msg == WM_CREATE)
{
CREATESTRUCT* cs = (CREATESTRUCT*) lParam;
winp = (Window*) cs->lpCreateParams;
SetLastError(0);
if(SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) winp) == 0)
{
if(GetLastError()!=0) return -1;
}
}
else
{
winp = (Window*) GetWindowLongPtr(hwnd, GWLP_USERDATA);
}
if(winp) return winp->ThisWindowProc(msg, wParam, lParam);
return DefWindowProc(hwnd, msg, wParam, lParam);
}
LRESULT Window::ThisWindowProc(UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_PAINT:
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_CLOSE:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(mHwnd, msg, wParam, lParam);
}
return 0;
}
//main.cpp
#include "mywind.h"
int main(int argc, char* argv[])
{
Window mwnd;
mwnd.create("Test", 200, 200);
return 0;
}
Notice that you don't set mHwnd until CreateWindowEx returns. This means that all the messages sent during window creation pass 0 to DefWindowProc instead of the actual window handle. This causes the window manager to think you are bypassing default handling and doing custom captions, which is why everything looks wrong.
TL;DR: Set mHwnd inside your WM_NCCREATE handler.
I am 90% sure that your problem is the missing manifest which enables WinXP/7 look. Now you are in compatibility mode and the window frame is for Windows 98/2000 style. For more details read this link (or many others for the same problem):
http://www.mctainsh.com/Articles/Csharp/XpControlsInCS.aspx

VS 2013 errorC3861 PeekMessage etc and errorC2065 WNDCLASSEX

I am attempting a new user graphics tutorial but I am very stuck. I am a very new programmer...I was under the impression that most of these definitions would be included in I included. My message handler is missing an identifier 'DefWindowProcess', WINDCLASSEX is also not being identified, GetModuleHandle function, PeekMessage/TranslateMessage etc. The Microsoft dev center says that all these definitions should be in windows.h.
#ifndef _SYSTEMCLASS_H_
#define _SYSTEMCLASS_H_
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "inputclass.h"
#include "graphicsclass.h"
class SystemClass
{
public:
SystemClass();
SystemClass(const SystemClass&);
~SystemClass();
bool Initialize();
void Shutdown();
void Run();
LRESULT CALLBACK MessageHandler(HWND, UINT, WPARAM, LPARAM);
private:
bool Frame();
void InitializeWindows(int&, int&);
void ShutdownWindows();
private:
LPCWSTR m_applicationName;
HINSTANCE m_hinstance;
HWND m_hwnd;
InputClass* m_Input;
GraphicsClass* m_Graphics;
};
static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
static SystemClass* ApplicationHandle = 0;
#endif
my systemclass.cpp is as follows
#include "pch.h"
#include "systemclass.h"
SystemClass::SystemClass()
{
m_Input = 0;
m_Graphics = 0;
}
bool SystemClass::Initialize()
{
int screenWidth, screenHeight;
bool result;
screenWidth = 0;
screenHeight = 0;
// Initialize the windows api.
InitializeWindows(screenWidth, screenHeight);
m_Input = new InputClass;
if (!m_Input)
{
return false;
}
// Initialize the input object.
m_Input->Initialize();
// Create the graphics object. This object will handle rendering all the graphics for this application.
m_Graphics = new GraphicsClass;
if (!m_Graphics)
{
return false;
}
// Initialize the graphics object.
result = m_Graphics->Initialize(screenWidth, screenHeight, m_hwnd);
if (!result)
{
return false;
}
return true;
}
void SystemClass::Shutdown()
{
// Release the graphics object.
if (m_Graphics)
{
m_Graphics->Shutdown();
delete m_Graphics;
m_Graphics = 0;
}
// Release the input object.
if (m_Input)
{
delete m_Input;
m_Input = 0;
}
// Shutdown the window.
ShutdownWindows();
return;
}
void SystemClass::Run()
{
MSG msg;
bool done, result;
// Initialize the message structure.
ZeroMemory(&msg, sizeof(MSG));
// Loop until there is a quit message from the window or the user.
done = false;
while (!done)
{
// Handle the windows messages.
if ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// If windows signals to end the application then exit out.
if (msg.message == WM_QUIT)
{
done = true;
}
else
{
// Otherwise do the frame processing.
result = Frame();
if (!result)
{
done = true;
}
}
}
return;
}
bool SystemClass::Frame()
{
bool result;
// Check if the user pressed escape and wants to exit the application.
if (m_Input->IsKeyDown(VK_ESCAPE))
{
return false;
}
// Do the frame processing for the graphics object.
result = m_Graphics->Frame();
if (!result)
{
return false;
}
return true;
}
LRESULT CALLBACK SystemClass::MessageHandler(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lparam)
{
switch (umsg)
{
// Check if a key has been pressed on the keyboard.
case WM_KEYDOWN:
{
m_Input->KeyDown((unsigned int)wparam);
return 0;
}
// Check if a key has been released on the keyboard.
case WM_KEYUP:
{
m_Input->KeyUp((unsigned int)wparam);
return 0;
}
default:
{
return DefWindowProc(hwnd, umsg, wparam, lparam);
}
}
}
void SystemClass::InitializeWindows(int& screenWidth, int& screenHeight)
{
WNDCLASSEX wc; //THIS IS THE PROBLEM
DEVMODE dmScreenSettings;
int posX, posY;
// Get an external pointer to this object.
ApplicationHandle = this;
// Get the instance of this application.
m_hinstance = GetModuleHandle(NULL);
// Give the application a name.
m_applicationName = L"Engine";
// Setup the windows class with default settings.
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = m_hinstance;
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wc.hIconSm = wc.hIcon;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = m_applicationName;
wc.cbSize = sizeof(WNDCLASSEX);
// Register the window class.
RegisterClassEx(&wc);
// Determine the resolution of the clients desktop screen.
screenWidth = GetSystemMetrics(SM_CXSCREEN);
screenHeight = GetSystemMetrics(SM_CYSCREEN);
if (FULL_SCREEN)
{
memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
dmScreenSettings.dmSize = sizeof(dmScreenSettings);
dmScreenSettings.dmPelsWidth = (unsigned long)screenWidth;
dmScreenSettings.dmPelsHeight = (unsigned long)screenHeight;
dmScreenSettings.dmBitsPerPel = 32;
dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
// Change the display settings to full screen.
ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN);
// Set the position of the window to the top left corner.
posX = posY = 0;
}
else
{
// If windowed then set it to 800x600 resolution.
screenWidth = 800;
screenHeight = 600;
// Place the window in the middle of the screen.
posX = (GetSystemMetrics(SM_CXSCREEN) - screenWidth) / 2;
posY = (GetSystemMetrics(SM_CYSCREEN) - screenHeight) / 2;
}
// Create the window with the screen settings and get the handle to it.
m_hwnd = CreateWindowEx(WS_EX_APPWINDOW, m_applicationName, m_applicationName,
WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_POPUP,
posX, posY, screenWidth, screenHeight, NULL, NULL, m_hinstance, NULL);
// Bring the window up on the screen and set it as main focus.
ShowWindow(m_hwnd, SW_SHOW);
SetForegroundWindow(m_hwnd);
SetFocus(m_hwnd);
// Hide the mouse cursor.
ShowCursor(false);
return;
}
void SystemClass::ShutdownWindows()
{
// Show the mouse cursor.
ShowCursor(true);
// Fix the display settings if leaving full screen mode.
if (FULL_SCREEN)
{
ChangeDisplaySettings(NULL, 0);
}
// Remove the window.
DestroyWindow(m_hwnd);
m_hwnd = NULL;
// Remove the application instance.
UnregisterClass(m_applicationName, m_hinstance);
m_hinstance = NULL;
// Release the pointer to this class.
ApplicationHandle = NULL;
return;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT umessage, WPARAM wparam, LPARAM lparam)
{
switch (umessage)
{
// Check if the window is being destroyed.
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
// Check if the window is being closed.
case WM_CLOSE:
{
PostQuitMessage(0);
return 0;
}
// All other messages pass to the message handler in the system class.
default:
{
return ApplicationHandle->MessageHandler(hwnd, umessage, wparam, lparam);
}
}
}
Figured it out, directx projects don't recognize window API, I needed a win32 project, apply #stdafx headers on all my cpp files to get precompiled headers to work an also add #pragma once to all header files to avoid pch errors. VS is a bit quirky it turns out. Also for all the other noobs, make sure you set up file paths for directx and that you add files through project ->add->newfile->appropriate file type. it will save you headaches from VS knowing correct file locations.

infine windows message loop - c++

I tried to create this window class which creates and shows a window. When I run this class, GetMessage keep on sending WM_PAINT message, and task manager shows me about 50% CPU usage just from my process.
main.cpp:
#include "Window.h"
int WINAPI WinMain(
HINSTANCE /* hInstance */,
HINSTANCE /* hPrevInstance */,
LPSTR /* lpCmdLine */,
int /* nCmdShow */
)
{
Window::GlobalInitialize();
Window window(L"abcd", 500, 500);
if (SUCCEEDED(window.Initialize()))
window.RunMessageLoop();
Window::GlobalTerminate();
return 0;
}
Window.h:
#ifndef WINDOW_HEADER
#define WINDOW_HEADER
#include <Windows.h>
#include <functional>
#pragma comment(lib, "d2d1.lib")
class Window;
typedef std::function<void(Window *window, UINT id, LPCWSTR message)> ErrorCallback;
class Window {
public:
#define ERROR_FAILED_HINSTANCE 1
#define ERROR_FAILED_HINSTANCE_STR L"Failed to retrieve hInstance"
#define ERROR_FAILED_REGISTER 2
#define ERROR_FAILED_REGISTER_STR L"Failed to register window class"
#define ERROR_FAILED_CREATION 3
#define ERROR_FAILED_CREATION_STR L"Failed to create window"
typedef std::function<HRESULT(Window *window)> WEOnCreate;
typedef std::function<HRESULT(Window *window)> WEOnDestroy;
typedef std::function<HRESULT(Window *window)> WEOnRender;
typedef std::function<HRESULT(Window *window, UINT width, UINT height)> WEOnResize;
typedef std::function<HRESULT(Window *window, UINT horizontalResolution, UINT verticalResolution)> WEOnScreenResolutionChange;
Window(LPCWSTR title, UINT width, UINT height);
~Window();
HRESULT SetSize(UINT width, UINT height);
HRESULT SetTitle(LPCWSTR title);
inline UINT GetWidth() { return _width; }
inline UINT GetHeight() { return _height; }
inline LPCWSTR GetTitle() { return _title; }
inline HWND GetHandle() { return hWnd; }
inline void SetOnCreateCallback(WEOnCreate fun) { _onCreate = fun; }
inline void SetOnDestroyCallback(WEOnDestroy fun) { _onDestroy = fun; }
inline void SetOnRenderCallback(WEOnRender fun) { _onRender = fun; }
inline void SetOnResizeCallback(WEOnResize fun) { _onResize = fun; }
inline void SetOnScreenResolutionChangeCallback(WEOnScreenResolutionChange fun) { _onResChange = fun; }
inline void SetExtraAllocatedSpace(void *ptr) { extra = ptr; }
inline void *GetExtraAllocatedSpace() { return extra; }
inline void Terminate() { if (hWnd) DestroyWindow(hWnd); }
static inline void SetErrorCallback(ErrorCallback fun) { _errorCallback = fun; }
HRESULT Initialize();
void RunMessageLoop();
static HRESULT GlobalInitialize();
static HRESULT GlobalTerminate();
private:
static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
static inline void throwError(Window *window, UINT id, LPCWSTR message) {
if (_errorCallback)
_errorCallback(window, id, message);
}
WEOnCreate _onCreate;
WEOnDestroy _onDestroy;
WEOnRender _onRender;
WEOnResize _onResize;
WEOnScreenResolutionChange _onResChange;
static ErrorCallback _errorCallback;
static LPCWSTR szClassName;
static HINSTANCE hInstance;
HWND hWnd;
int _width, _height;
LPCWSTR _title;
void *extra;
};
#endif
Window.cpp:
#include "Window.h"
//Initialize static variables
ErrorCallback Window::_errorCallback = nullptr;
LPCWSTR Window::szClassName = L"WindowClass";
HINSTANCE Window::hInstance;
Window::Window(LPCWSTR title = L"Window", UINT width = 640, UINT height = 480) :
_onCreate(nullptr),
_onDestroy(nullptr),
_onRender(nullptr),
_onResize(nullptr),
hWnd(NULL),
extra(NULL),
_width(width),
_height(height),
_title(title) {}
Window::~Window() {
if (hWnd) {
DestroyWindow(hWnd);
hWnd = NULL;
}
}
HRESULT Window::GlobalInitialize() {
// Retreive hInstance
hInstance = GetModuleHandle(NULL);
if (!hInstance) {
throwError(NULL, ERROR_FAILED_HINSTANCE, ERROR_FAILED_HINSTANCE_STR);
return E_FAIL;
}
// Create window class
WNDCLASSEX wcex = {};
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = Window::WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = sizeof(LONG_PTR);
wcex.hInstance = hInstance;
wcex.hbrBackground = NULL;
wcex.lpszMenuName = NULL;
wcex.hCursor = LoadCursor(NULL, IDI_APPLICATION);
wcex.lpszClassName = szClassName;
if (!RegisterClassEx(&wcex)) {
throwError(NULL, ERROR_FAILED_REGISTER, ERROR_FAILED_REGISTER_STR);
return E_FAIL;
}
return S_OK;
}
HRESULT Window::GlobalTerminate() {
if (UnregisterClass(szClassName, hInstance))
return S_OK;
else
return E_FAIL;
}
void Window::RunMessageLoop() {
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
HRESULT Window::Initialize() {
// Create the window
hWnd = CreateWindow(
szClassName,
_title,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
_width,
_height,
NULL,
NULL,
hInstance,
this
);
if (!hWnd) {
throwError(this, ERROR_FAILED_CREATION, ERROR_FAILED_CREATION_STR);
return E_FAIL;
}
// Show and render the window
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
return S_OK;
}
LRESULT CALLBACK Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
if (message == WM_CREATE) {
LPCREATESTRUCT pcs = (LPCREATESTRUCT)lParam;
Window *window = (Window *)pcs->lpCreateParams;
::SetWindowLongPtr(hWnd, GWLP_USERDATA, PtrToUlong(window));
if (window->_onCreate != nullptr)
window->_onCreate(window);
}
Window *pWnd = reinterpret_cast<Window *>(static_cast<LONG_PTR>(GetWindowLongPtr(hWnd, GWLP_USERDATA)));
HRESULT hr = S_OK;
if (!pWnd) {
return DefWindowProc(hWnd, message, wParam, lParam);
}
switch (message) {
case WM_PAINT:
{
if (pWnd->_onRender)
hr = pWnd->_onRender(pWnd);
else
hr = S_OK;
}
break;
case WM_SIZE:
{
if (pWnd->_onResize)
hr = pWnd->_onResize(pWnd, LOWORD(lParam), HIWORD(lParam));
else
hr = S_OK;
}
break;
case WM_DISPLAYCHANGE:
{
if (pWnd->_onResChange)
hr = pWnd->_onResChange(pWnd, LOWORD(lParam), HIWORD(lParam));
else
hr = S_OK;
}
break;
case WM_DESTROY:
{
if (pWnd->_onDestroy && FAILED(pWnd->_onDestroy(pWnd)))
break;
}
PostQuitMessage(0);
hWnd = NULL;
break;
default:
hr = DefWindowProc(hWnd, message, wParam, lParam);
}
return hr;
}
HRESULT Window::SetSize(UINT width, UINT height) {
if (hWnd)
if (!::SetWindowPos(hWnd, 0, 0, 0, width, height, SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER))
return E_FAIL;
_width = width;
_height = height;
return S_OK;
}
HRESULT Window::SetTitle(LPCWSTR title) {
if (hWnd)
if (!::SetWindowText(hWnd, title))
return E_FAIL;
_title = title;
return S_OK;
}
I hope someone can help me since everything looks OK(the window even runs fine).
Firstly, you seem to be treating the window procedure as if it was a COM method, but window procedures do not return an HRESULT - they return an LRESULT whose meaning is different for each message.
In the case of WM_PAINT it's not possible to return a value that indicates "I don't need to paint this time". The system will send WM_PAINT messages as long as a portion of your window is marked as dirty, and the way you mark the dirty area as "painted" is by calling BeginPaint and EndPaint. If you don't do this, the system will continue to consider your window as dirty and continue to send WM_PAINT messages.
You haven't shown the source code for your _onRender function but the very fact that you have made WM_PAINT handling optional (i.e. if nothing calls SetOnRenderCallback then no callback will be registered) means that you are probably not processing WM_PAINT correctly. At the very least, if you don't do the painting yourself, you should pass the message through to DefWindowProc to allow the default processing to take place.

Windows has triggered a breakpoint in my Thread

In my application I'm loading (for example) Device_Manager.dll and this Device_Manager depend on the selected model start to load the correct Devices.dll.
In my Device_Manager.dll, I created a window to use its handle later on my Devices because Devices uses this handle when they want to send messages to the application.
So, I made the new thread in my Device_Manager.dll to get these message when ever they arrive!
(I'm also using QT for create/load .dlls.)
After I created a thread, I received this error:
Windows has triggered a breakpoint in sepanta.agent.exe.
This may be due to a corruption of the heap, which indicates a bug in sepanta.agent.exe or any of the DLLs it has loaded.
This may also be due to the user pressing F12 while sepanta.agent.exe has focus.
The output window may have more diagnostic information.
I use these two methods to initialize and start my device manager:
(These methods are called in the main application after I successfully load the .dll.)
bool DeviceManagerPlugin::initializeDeviceManager()
{
EventManager pEventManager = new EventManager();
bool init_result = pEventManager->initilize_window();
...
if(initilize_status == S_OK)
{
return true;
}
else
{
return false;
}
}
void DeviceManagerPlugin::startDeviceManager()
{
handle_of_thread = 0;
int data_of_thread = 1;
handle_of_thread = CreateThread(NULL, 0,listenToIncomingWFSMessages2, &data_of_thread, 0, NULL);
my_thread_handle = handle_of_thread;
}
This is my EventManager class, which created windows:
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
...
default:
return DefWindowProc(hWnd, msg, wParam, lParam );
}
}
bool EventManager::initialize_window()
{
WNDCLASS Wclass;
HWND gHwnd = NULL;
HINSTANCE gHinstance = NULL;
ZeroMemory(&Wclass, sizeof(WNDCLASS));
Wclass.hInstance = gHinstance;
Wclass.cbClsExtra = 0;
Wclass.cbWndExtra = 0;
Wclass.lpszClassName = TEXT("Device_Manager_Class_Name");
Wclass.lpszMenuName = NULL;
Wclass.lpfnWndProc = WndProc;
Wclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
Wclass.hCursor = LoadIcon(NULL, IDC_ARROW);
Wclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
Wclass.style = CS_OWNDC;
if(!RegisterClass(&Wclass))
{
cout<<"Unable to Register Class";
return false;
}
ULONG Window_Width;
ULONG Window_Height;
DWORD style;
bool full_screen = false;
if(full_screen)
{
Window_Width = GetSystemMetrics(SM_CXSCREEN);
Window_Height = GetSystemMetrics(SM_CYSCREEN);
style = WS_POPUP;
}
else
{
Window_Width = SCREEN_WIDTH;
Window_Height = SCREEN_HEIGHT;
style = WS_OVERLAPPED|WS_SYSMENU;
}
gHwnd = CreateWindow(TEXT("Device_Manager_Class_Name")
, TEXT("Device_Manager_Class_Title")
, style
, 0
, 0
, Window_Width
, Window_Height
, GetDesktopWindow()
, NULL
, gHinstance
, NULL);
if(!gHwnd)
{
cout<<"Unable to create the main window";
return false;
}
//ShowWindow(gHwnd, SW_SHOW);
//UpdateWindow(gHwnd);
//SetFocus(gHwnd);
return true;
}
DWORD WINAPI listenToIncomingWFSMessages2(LPVOID lpParam)
{
MSG msg;
SecureZeroMemory(&msg, sizeof(MSG));
BOOL bRet;
HWND windows_handle;
SecureZeroMemory(&windows_handle, sizeof(HWND));
windows_handle = FindWindow(TEXT("Device_Manager_Class_Name"), 0);
while( (bRet = GetMessage( &msg, windows_handle, 0, 0 )) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return 0;
}
What am I doing wrong here? What did I miss? If you have a better solution for what I'm about to do, please feel free to share it with me.