Related
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.
I am creating a simple window but when I see the window being created and closes it, not WM_QUIT message is ever gotten. Here's some code:
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR cmdLine, int cmdShow)
{
cWindowApplication app(hInstance);
const long width = 1024L;
const long height = 768L;
if (app.CreateWindowApplication(width, height) == false)
{
MessageBox(NULL, "Unable to create OpenGL Window", "An error occurred", MB_ICONERROR | MB_OK);
app.DestroyWindowApplication();
return 1;
}
return app.MainLoop();
}
Here's the CreateWindowApplication(int, int) function:
bool cWindowApplication::CreateWindowApplication(long width, long height, bool full_screen /*= false*/)
{
DWORD dwExStyle; // Window Extended Style
DWORD dwStyle; // Window Style
mWindowRect.left = 0L; // Set Left Value To 0
mWindowRect.right = width; // Set Right Value To Requested Width
mWindowRect.top = 0L; // Set Top Value To 0
mWindowRect.bottom = height; // Set Bottom Value To Requested Height
mFullScreen = full_screen;
// fill out the window class structure
const char* class_name = "MyClass";
mWindowClass.cbSize = sizeof(WNDCLASSEX);
mWindowClass.style = CS_HREDRAW | CS_VREDRAW;
mWindowClass.lpfnWndProc = cWindowApplication::StaticWindowsProcessCallback;
mWindowClass.cbClsExtra = 0;
mWindowClass.cbWndExtra = 0;
mWindowClass.hInstance = mhInstance;
mWindowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); // default icon
mWindowClass.hCursor = LoadCursor(NULL, IDC_ARROW); // default arrow
mWindowClass.hbrBackground = NULL; // don't need background
mWindowClass.lpszMenuName = NULL; // no menu
mWindowClass.lpszClassName = class_name;
mWindowClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO); // windows logo small icon
// register the windows class
if (!RegisterClassEx(&mWindowClass))
{
return false;
}
if (mFullScreen == true) //If we are Full Screen, we need to change the display mode
{
DEVMODE dmScreenSettings; // device mode
memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
dmScreenSettings.dmSize = sizeof(dmScreenSettings);
dmScreenSettings.dmPelsWidth = width; // screen width
dmScreenSettings.dmPelsHeight = height; // screen height
dmScreenSettings.dmBitsPerPel = BITS_PER_PIXEL; // bits per pixel
dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
{
// setting display mode failed, switch to windowed
MessageBox(NULL, "Display mode failed", NULL, MB_OK);
mFullScreen = false;
}
}
if (mFullScreen == true) // Are We Still In Full Screen Mode?
{
dwExStyle = WS_EX_APPWINDOW; // Window Extended Style
dwStyle = WS_POPUP; // Windows Style
//ShowCursor(false); // Hide Mouse Pointer
}
else
{
dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Window Extended Style
dwStyle = WS_OVERLAPPEDWINDOW; // Windows Style
}
AdjustWindowRectEx(&mWindowRect, dwStyle, false, dwExStyle); // Adjust Window To True Requested Size
// class registered, and create our window
mHWND = CreateWindowEx(NULL, // extended style
class_name, // class name
"My Windows", // application name
dwStyle | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
0, 0, // x,y coordinate
mWindowRect.right - mWindowRect.left,
mWindowRect.bottom - mWindowRect.top, // width, height
NULL, // handle to parent
NULL, // handle to menu
mhInstance, // application instance
this); // this pointer to call member functions
// check if window creation failed (hwnd would equal NULL)
if (mHWND == false)
{
return false;
}
mHDC = GetDC(mHWND);
ShowWindow(mHWND, SW_SHOW); // display the window
UpdateWindow(mHWND); // update the window
return true;
}
Basically after this function call, the CreateWindowEx() function will call StaticWindowProcessCallback() that looks like this:
LRESULT cWindowApplication::StaticWindowsProcessCallback(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
cWindowApplication* win_app = NULL;
if (msg == WM_CREATE)
{
//Creation event
//Get the pointer we pass during CreateWindowApplication() call
win_app = (cWindowApplication*)((LPCREATESTRUCT)lParam)->lpCreateParams;
//Associate window pointer with the hwnd for the other events to access
SetWindowLongPtr(wnd, GWLP_USERDATA, (LONG_PTR)win_app);
}
else
{
//Non-creation event
win_app = (cWindowApplication*)GetWindowLongPtr(wnd, GWLP_USERDATA);
if (win_app != NULL)
{
return DefWindowProc(wnd, msg, wParam, lParam);
}
}
//call member
return win_app->WindowsProcessCallback(wnd, msg, wParam, lParam);
}
Finally, the last line of this function calls the member function WindowProcessCallback() that looks like this:
LRESULT cWindowApplication::WindowsProcessCallback(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CREATE:
{
mHDC = GetDC(wnd);
SetupPixelFormat();
//Set the version that we want, in this case 3.0
int attribs[] = { WGL_CONTEXT_MAJOR_VERSION_ARB, 3, WGL_CONTEXT_MINOR_VERSION_ARB, 0, 0 }; //zero indicates the end of the array
//Create temporary context so we can get a pointer to the function
HGLRC tmp_context = wglCreateContext(mHDC);
//Make it current
wglMakeCurrent(mHDC, tmp_context);
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL;
wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB");
if (wglCreateContextAttribsARB == NULL)
{
//No OpenGL 3.0, back to 2.0
mHGLRC = tmp_context;
}
else
{
//Create OpenGL 3.0
mHGLRC = wglCreateContextAttribsARB(mHDC, 0, attribs);
//Delete the temp context
wglDeleteContext(tmp_context);
}
//Make OpenGL 3.0
wglMakeCurrent(mHDC, mHGLRC);
mIsRunning = true;
}
break;
case WM_QUIT:
case WM_DESTROY:
case WM_CLOSE:
wglMakeCurrent(mHDC, NULL);
wglDeleteContext(mHGLRC);
mIsRunning = false;
PostQuitMessage(0); //Send a WM_QUIT message
return 0;
default:
break;
}
return DefWindowProc(wnd, msg, wParam, lParam);
}
As you can see, there are some message processing code there ... but other than the WM_CREATE, no other cases are being hit. After the WM_CREATE message being sent, the function MainLoop() is being called that looks like this:
int cWindowApplication::MainLoop()
{
while (mIsRunning == true)
{
ProcessWindowsMessages();
}
DestroyWindowApplication();
return 0;
}
Basically the ProcessWindowsMessages() function does not get any message after the window closes ... I have to press stop VS from running in order to kill the process. The ProcessWindowsMessages() function looks like this:
void cWindowApplication::ProcessWindowsMessages()
{
MSG msg;
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
This logic in StaticWindowsProcessCallback looks backwards:
if (win_app != NULL)
{
return DefWindowProc(wnd, msg, wParam, lParam);
}
If you don't have a pointer to the window wrapper object, you'll need to call DefWindowProc. So that should happen if (win_app == NULL). This is to handle a handful of messages that are sent before WM_CREATE. As a result of this, your code has undefined behavior on messages processed before WM_CREATE, and discards (by applying default processing) all messages after WM_CREATE.
It would be even better to use WM_NCCREATE for setting up the link, though. As well, win_app is not a very good name for this, maybe win_obj or something.
You also shouldn't handle WM_QUIT in your window procedure, since it isn't sent to a window. And the default behavior of WM_CLOSE should be fine, it will call DestroyWindow which will trigger WM_DESTROY.
But the first, failure to forward any messages after WM_CREATE to your window procedure, likely explains your lack of WM_QUIT in the main message loop.
Can anyone tell me how to enable and disable USB port using C/C++.
I have already searched one way to do this..using windows registry but there are some problems with it.
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\USBSTOR
change the value of start value to 3----for unblock
4----block
It does not show correct behavior on windows 7. eg-
when I change the value of start value to 4 it disable the usb ports but again for enabling we need to restart the system and one more thing after disabling all the ports are disabled but still we are able to use already plugged device.
Any other way to do it?
I have found out one more solution for this using devcon utility.
It provides various commands to enable and disable usb devices.
http://msdn.microsoft.com/en-us/library/windows/hardware/ff544746(v=vs.85).aspx#ddk_example_31_disable_devices_by_device_instance_id_tools
But it needs administrative privileges for running commands and I don't have source code for this.
So I want ask you all one thing..
I have heard about libusb-win32 library for writing prog for USB devices.
So does anybody have idea about it..
Any help will be highly appreciated..
Thank you all..
This is really answering comments on the question r.e. device detection.
Create a hidden window in your console application.
This example assumes you have a class called DevNotifier, with an HWND hidden_wnd_; member variable:
static TCHAR const s_window_class[] = _T("Device notification window");
static TCHAR const* const s_window_title = s_window_class;
LRESULT CALLBACK
DevNotifierWndProc(
HWND hWnd,
UINT message,
WPARAM wParam,
LPARAM lParam
) {
DevNotifier* dn = (DevNotifier*) ::GetWindowLongPtr(hWnd, GWLP_USERDATA);
switch (message)
{
case WM_DEVICECHANGE:
dn->onWM_DEVICECHANGE(
wParam,
lParam
);
break;
default:
return ::DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
void
DevNotifier::createHiddenWindow()
{
HINSTANCE hinstance = ::GetModuleHandle(NULL);
if ((hinstance == 0) || (hinstance == INVALID_HANDLE_VALUE))
{
throw Exception("Failed to get application instance handle.");
}
// register window class
WNDCLASSEX wcex;
::memset(&wcex, 0, sizeof(wcex));
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = 0;
wcex.lpfnWndProc = &DevNotifierWndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hinstance;
wcex.hIcon = 0;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = 0;
wcex.lpszMenuName = 0;
wcex.lpszClassName = s_window_class;
wcex.hIconSm = 0;
(void) ::RegisterClassEx(&wcex);
// Create the window
hidden_wnd_ = ::CreateWindow(
s_window_class,
s_window_title,
WS_POPUP,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hinstance,
NULL
);
if (!hidden_wnd_) {
throw Exception("Failed to create device notification window");
}
#ifdef _WIN64
::SetWindowLongPtr(static_cast<HWND>(hidden_wnd_), GWLP_USERDATA, (LONG_PTR)this);
#else
::SetWindowLongPtr(static_cast<HWND>(hidden_wnd_), GWLP_USERDATA, (LONG)this);
#endif
::ShowWindow(static_cast<HWND>(hidden_wnd_), SW_HIDE);
}
You can register for notifications on hidden_wnd_.
e.g.
DEV_BROADCAST_DEVICEINTERFACE filter;
ZeroMemory(&filter, sizeof(filter));
filter.dbcc_size = sizeof(filter);
filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
filter.dbcc_classguid = /* SOME INTERFACE GUID */;
HDEVNOTIFY hdn = ::RegisterDeviceNotification(
hidden_wnd_,
&filter,
DEVICE_NOTIFY_WINDOW_HANDLE
);
You'll need to implement the function to deal with the WM_DEVICE_CHANGE messages:
bool
DevNotifier::onWM_DEVICECHANGE(WPARAM wparam, LPARAM lparam)
{
DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*)lparam;
// Note dbh will NOT always be valid, depending upon the value of wparam.
if (wparam == DBT_DEVNODES_CHANGED) {
// Do some stuff here
return true;
}
else if (wparam == DBT_DEVICEARRIVAL) {
DEV_BROADCAST_HDR* hdr = (DEV_BROADCAST_HDR*)lparam;
if (hdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
DEV_BROADCAST_DEVICEINTERFACE* devinterface =
(DEV_BROADCAST_DEVICEINTERFACE*)hdr;
// Do some stuff here
}
}
else if (wparam == DBT_DEVICEREMOVEPENDING) {
}
else if (wparam == DBT_DEVICEREMOVECOMPLETE) {
HANDLE h = INVALID_HANDLE_VALUE;
DEV_BROADCAST_HDR* phdr = (DEV_BROADCAST_HDR*) lparam;
if (phdr->dbch_devicetype == DBT_DEVTYP_HANDLE) {
DEV_BROADCAST_HANDLE* pdbh = (DEV_BROADCAST_HANDLE*) lparam;
h = pdbh->dbch_handle;
}
else if (phdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
DEV_BROADCAST_DEVICEINTERFACE* devinterface =
(DEV_BROADCAST_DEVICEINTERFACE*)phdr;
// Do some stuff here
}
// Maybe do some stuff here too.
}
return false;
}
In your console application you are going to have to run a message pump to get windows messages to work. If you have got other stuff to do while the application is waiting for messages then you'll need to also handle that here.
while (GetMessage(&message, NULL, 0, 0) > 0) {
TranslateMessage(&message);
DispatchMessage(&message);
}
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.
Why do simple old programs like this that I've had lying around for years sometimes set off my anti-virus? It picked up the compiled exe for this one and said it might be a gen/dropper or something like that.
Here's the code:
#include "c:\\dxsdk\\include\\d3d9.h"
#include "c:\\dxsdk\\include\\d3dx9.h"
#include <time.h>
#include <sstream>
using namespace std;
#define APPTITLE "DirectX Practice"
LRESULT CALLBACK WinProc(HWND,UINT,WPARAM,LPARAM);
int Initialize(HWND);
void OnCleanup(HWND);
void OnInterval(HWND);
BOOL KEY_DOWN(UINT);
BOOL KEY_UP(UINT);
LPDIRECT3D9 d3d = NULL;
LPDIRECT3DDEVICE9 d3ddev = NULL;
LPDIRECT3DSURFACE9 backBuffer = NULL;
LPDIRECT3DSURFACE9 surface = NULL;
UINT Screen_Width = 0;
UINT Screen_Height = 0;
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
//
MSG msg;
////////////
Screen_Width = 1280;//GetSystemMetrics(SM_CXFULLSCREEN);
Screen_Height= 800;//GetSystemMetrics(SM_CYFULLSCREEN);
// can't use the real rez if it isn't standard
if( Screen_Width==0 || Screen_Height==0 ){
MessageBox(
NULL,
"Could not detect native screen resolution. Using Default.",
"Error",
MB_ICONERROR|MB_SYSTEMMODAL);
Screen_Width = 800;
Screen_Height = 600;
}
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW|CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WinProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetSysColorBrush(COLOR_BTNFACE);
wc.lpszMenuName = NULL;
wc.lpszClassName = APPTITLE;
wc.hIconSm = NULL;
if(!RegisterClassEx(&wc))
return FALSE;
HWND hwnd;
hwnd = CreateWindow(
APPTITLE,
APPTITLE,
WS_EX_TOPMOST|WS_VISIBLE|WS_POPUP,
CW_USEDEFAULT,
CW_USEDEFAULT,
Screen_Width,
Screen_Height,
NULL,
NULL,
hInstance,
NULL);
if(!hwnd)
return FALSE;
ShowWindow(hwnd,SW_SHOW/*nCmdShow*/);
UpdateWindow(hwnd);
if(!Initialize(hwnd))
return FALSE;
int done = 0;
while( !done )
{
if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
if(msg.message==WM_QUIT)
{
MessageBox(hwnd,"Exiting","Notice",MB_OK|MB_SYSTEMMODAL);
done = 1;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}else{
OnInterval(hwnd);
}
}
return msg.wParam;
}
LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_DESTROY:
OnCleanup(hwnd);
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hwnd,msg,wParam,lParam);
}
return 0;
}
int Initialize(HWND hwnd)
{
d3d = Direct3DCreate9(D3D_SDK_VERSION);
if(d3d == NULL){
MessageBox(hwnd,"Could not initialize Direct3D 9","Error",MB_ICONERROR|MB_SYSTEMMODAL);
return 0;
}
D3DPRESENT_PARAMETERS dp;
ZeroMemory(&dp,sizeof(dp));
dp.Windowed = FALSE;
dp.SwapEffect = D3DSWAPEFFECT_DISCARD;
dp.BackBufferFormat = D3DFMT_X8R8G8B8;
dp.BackBufferCount = 1;
dp.BackBufferWidth = Screen_Width;
dp.BackBufferHeight = Screen_Height;
dp.hDeviceWindow = hwnd;
d3d->CreateDevice(
D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hwnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&dp,
&d3ddev);
if(d3ddev == NULL){
MessageBox(hwnd,"Could not create Direct3D 9 device","Error",MB_ICONERROR|MB_SYSTEMMODAL);
return 0;
}
srand(time(NULL));
d3ddev->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,0),1.0f,0);
d3ddev->GetBackBuffer(0,0,D3DBACKBUFFER_TYPE_MONO,&backBuffer);
if(d3ddev->CreateOffscreenPlainSurface(
1294,614,
D3DFMT_X8R8G8B8,
D3DPOOL_DEFAULT,
&surface,
NULL) != D3D_OK )
{
MessageBox(hwnd,"Could not create off-screen data surface","Error",MB_ICONERROR|MB_SYSTEMMODAL);
return 0;
}
if(D3DXLoadSurfaceFromFile(
surface,
NULL,
NULL,
"green.jpg",
NULL,
D3DX_DEFAULT,
0,
NULL) != D3D_OK )
{
MessageBox(hwnd,"Could not load image","Error",0);
return 0;
}
return 1;
}
void OnCleanup(HWND hwnd)
{
MessageBox(hwnd,"exiting","bye",MB_ICONERROR|MB_SYSTEMMODAL);
if( surface!=NULL )
{
surface->Release();
}
if(d3ddev!=NULL)
{
d3ddev->Release();
}
if(d3d!=NULL)
{
d3d->Release();
}
}
void OnInterval(HWND hwnd)
{
/*RECT rect;
int r;
int g;
int b;
*/
if( KEY_DOWN(VK_ESCAPE) )
PostMessage(hwnd,WM_QUIT,0,0);
if(d3ddev == NULL)
return;
d3ddev->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,0),1.0f,0);
if(d3ddev->BeginScene())
{
/*r = rand()%255;
g = rand()%255;
b = rand()%255;
d3ddev->ColorFill(surface,NULL,D3DCOLOR_XRGB(r,g,b));
rect.left = rand()%Screen_Width/2;
rect.top = rand()%Screen_Height/2;
rect.right = rect.left + rand()%Screen_Width/2;
rect.bottom = rect.top + rand()%Screen_Height/2;
*/
// blit surface's contents to the screen into the
// target rect area
d3ddev->StretchRect(surface,NULL,backBuffer,&rect,D3DTEXF_NONE);
d3ddev->EndScene();
}
d3ddev->Present(NULL,NULL,NULL,NULL);
}
BOOL KEY_DOWN(UINT key)
{
return (BOOL)(GetAsyncKeyState(key) & 0x8000);
}
BOOL KEY_UP(UINT key)
{
return !((BOOL)(GetAsyncKeyState(key) & 0x8000));
}
What is setting off the virus scanner, and more precisely, what can I do to avoid that?
Check what happens when you recompile. If it the problem does not persist then it might be that some other process is tampering with your executable. Check why the virri scanner matches what pattern in your file and if your compiler really created that code (by dumping intermediate assembler of the compiler)
Hope that helps
I think it's a trend. There are only so much viruses an antivirus software can detect. So they started detecting a lot of false positives to remind the user how good the antivirus is and how lucky he is his computer was protected.
I also encounter this problem very often. Some users start complaining about false positives with an antivirus, I submit a report, an update is issued fixing the false positive and in a month the false positive is back.
The best solution is a digital signature. A digitally signed file comes with a guarantee that it's from a trusted source, so most antivirus applications don't report it as a problem. The downside is that you have to buy a code signing certificate.