C++ Callbacks - Unresolved external symbol - c++

I'm trying to write a error handling system in c++, which calls a callback function whenever an error rises. However, the linker always complains about an unresolved external symbol whenever I try to run the project.
GEWindow.h:
#include <Windows.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>
#include <functional>
#ifndef GE_WINDOW
#define GE_WINDOW
//class GEWindow;
//typedef void(*GE_ERROR_CALLBACK)(HWND, UINT, LPCWSTR);
#define GE_WINDOW_REGISTERATION_FAILED 1
#define GE_WINDOW_CREATION_FAILED 2
class GEWindow {
public:
typedef std::function<void(GEWindow *, UINT, LPCWSTR)> GE_ERROR_CALLBACK;
static int geCreateWindow(GEWindow *window);
static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
static inline void setErrorCallback(GE_ERROR_CALLBACK fun) { errCallback = fun; };
inline HWND getHWnd() { return hWnd; };
inline int getWidth() { return _width; };
inline int getHeight() { return _height; };
inline LPCWSTR getTitle() { return _title; };
inline void setWidth(int width) { _width = width; };
inline void setHeight(int height) { _height = height; };
inline void setTitle(LPCWSTR title) { _title = title; };
private:
static GE_ERROR_CALLBACK errCallback;
HWND hWnd;
int _width = 400, _height = 400;
LPCWSTR _title;
};
#endif
GEWindow.cpp:
#include "GEWindow.h"
int GEWindow::geCreateWindow(GEWindow *window) {
HINSTANCE hInstance = GetModuleHandle(NULL);
TCHAR szWindowClass[] = _T("GEWindow");
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = GEWindow::WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
if (!RegisterClassEx(&wcex))
{
//if (!errCallback)
// errCallback(window, GE_WINDOW_REGISTERATION_FAILED, _T("Failed to register the GE window"));
MessageBox(NULL, _T("Failed to register"), _T("Error"), NULL);
return NULL;
}
window->hWnd = CreateWindow(
szWindowClass,
window->_title,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
window->_width, window->_height,
NULL,
NULL,
hInstance,
NULL);
if (!window->hWnd) {
//if (!errCallback)
// errCallback(window, GE_WINDOW_CREATION_FAILED, _T("Failed to create the GE window"));
MessageBox(NULL, _T("Failed to create"), _T("Error"), NULL);
return NULL;
}
ShowWindow(window->hWnd, SW_SHOW);
UpdateWindow(window->hWnd);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 1;
}
LRESULT CALLBACK GEWindow::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message)
{
case WM_PAINT:
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
}
return 0;
}
main.cpp:
#include "GEWindow.h"
static void error_callback(GEWindow *window, UINT errorCode, LPCWSTR message) {
MessageBox(window->getHWnd(), message, _T("Error"), NULL);
}
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow) {
GEWindow window;
window.setWidth(500);
window.setHeight(500);
window.setTitle(_T("lala lulu"));
/*
error LNK2001: unresolved external symbol "private: static class std::function<void __cdecl(class GEWindow *, unsigned int, wchar_t const *)> GEWindow::errCallback" (?errCallback#GEWindow##0V?$function#$$A^AXPAVGEWindow##IPB_W#Z#std##A)
*/
window.setErrorCallback(error_callback);
GEWindow::geCreateWindow(&window);
}

When using static member variables, you only declare them in the class, you need to define them as well. That definition has to be done in a source file, like this:
GEWindow::GE_ERROR_CALLBACK GEWindow::errCallback;

static void GeWindows::error_callback() will fix this problem..I found it after days by days by the help of "Tony The Lion" (credit...)

Related

c++ winapi window process inside of a class not working

I am creating a window wrapper class in c++ but I cannot seem to fix this bug.
it seems that when my window process callback gets called it is not retrieving the this pointer I inputted for the extra information when creating the window. I did a little bit of debugging to find out that when I reinterpret it to a Window* it is NULL and every variable is uninitialized.
here is Window.h
#pragma once
#include <Windows.h>
#include <string>
class Window
{
private:
class WindowClass
{
private:
static WindowClass wndClass;
WindowClass();
HINSTANCE hInst;
const char* className = "Sadie Game Engine";
WindowClass(WindowClass&) = delete;
WindowClass operator=(WindowClass&) = delete;
~WindowClass();
public:
static WindowClass& getInstance();
HINSTANCE getHInstance();
const char* getClassName();
};
private:
const char* windowTitle;
int width, height;
int windowX, windowY;
HWND windowHandle;
public:
bool keyStates[256];
Window(int width, int height, int x, int y, const char* title);
void setWindowTitle(std::string str);
static LRESULT CALLBACK handleMsgCallBack(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
LRESULT handleMsg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
~Window();
};
and here is Window.cpp
#include "Window.h"
///
/// WindowClass
///
Window::WindowClass Window::WindowClass::wndClass;
Window::WindowClass::WindowClass()
{
hInst = GetModuleHandleA(nullptr);
WNDCLASSEXA wc = { 0 };
wc.cbSize = sizeof(wc);
wc.style = CS_OWNDC;
wc.lpfnWndProc = handleMsgCallBack;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.lpszClassName = className;
wc.hIcon = nullptr;
wc.hIconSm = nullptr;
wc.hCursor = nullptr;
wc.hbrBackground = nullptr;
wc.lpszMenuName = nullptr;
RegisterClassExA(&wc);
}
Window::WindowClass::~WindowClass()
{
UnregisterClassA(className, hInst);
}
Window::WindowClass& Window::WindowClass::getInstance()
{
return wndClass;
}
HINSTANCE Window::WindowClass::getHInstance()
{
return hInst;
}
const char* Window::WindowClass::getClassName()
{
return className;
}
///
/// Window
///
Window::Window(int _width, int _height, int x, int y, const char* title)
{
width = _width;
height = _height;
windowX = x;
windowY = y;
windowTitle = title;
RECT wr;
wr.left = 100;
wr.right = width + wr.left;
wr.top = 100;
wr.bottom = height + wr.top;
AdjustWindowRect(&wr, WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU, FALSE);
windowHandle = CreateWindowExA(0l, WindowClass::getInstance().getClassName(),
windowTitle, WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
windowX, windowY, width, height, nullptr, nullptr, WindowClass::getInstance().getHInstance(), this);
ShowWindow(windowHandle, SW_SHOW);
}
void Window::setWindowTitle(std::string str)
{
SetWindowTextA(windowHandle, str.c_str());
}
LRESULT Window::handleMsgCallBack(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
Window* const windowPtr = reinterpret_cast<Window*>(GetWindowLongPtrA(hWnd, GWLP_USERDATA));
return windowPtr->handleMsg(hWnd, msg, wParam, lParam);
}
LRESULT Window::handleMsg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_SYSKEYDOWN:
case WM_KEYDOWN:
keyStates[wParam] = true;
break;
case WM_SYSKEYUP:
case WM_KEYUP:
keyStates[wParam] = false;
break;
case WM_CHAR:
break;
case WM_CLOSE:
PostQuitMessage(0);
return 0;
}
return DefWindowProcA(hWnd, msg, wParam, lParam);
}
Window::~Window()
{
DestroyWindow(windowHandle);
}
Any help would be appreciated.
As RbMm said, You did not call the SetWindowLongPtr function
Just add the following code:
case WM_NCCREATE:
{
LPCREATESTRUCT pcs = (LPCREATESTRUCT)lParam;
Window* w = (Window*)pcs->lpCreateParams;
::SetWindowLongPtr(hWnd,GWLP_USERDATA,reinterpret_cast<LONG_PTR>(w));
break;
}

Constructor string parameter not setting window title

The window title in the title bar is not setting to the variable and string i assign it.
I have show my code below but the problem is app::Window * wnd = new app::Window(L"Window Title"); constructor does seem to be 'tstring mWindowName;' but this mhWnd = CreateWindowEx(NULL, className.c_str(), mWindowName.c_str(), WS_OVERLAPPEDWINDOW, 100, 200, mScreenWidth, mScreenHeight, nullptr, nullptr, mhInstance, this); is not setting the title.
Window.h
#ifndef _ST_Window_H_
#define _ST_Window_H_
// include files
//#include "s-window.h"
#include "s-platform.h"
#include "s-safe-delete-and-release.h"
#include "s-iostream.h"
#include "s-strings.h"
#ifndef _WINDOWS_
#include <windows.h>
#endif //_WINDOWS_
namespace app
{
class Window
{
protected:
HINSTANCE mhInstance;
HWND mhWnd;
tstring mWindowName;
bool mRunState;
long int mScreenWidth;
long int mScreenHeight;
public:
Window(void);
Window(tstring windowName);
~Window(void);
int Setup(long int width, long int height);
LRESULT MessageProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
static LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
int Run(void);
inline HINSTANCE GetInstance(void) { return mhInstance; }
inline HWND GetHwnd(void) { return mhWnd; }
inline long GetWidth(void) { return mScreenWidth; }
inline long GetHeight(void) { return mScreenHeight; }
inline tstring GetWindowName(void) { return mWindowName; }
inline bool GetRunState(void) { return mRunState; }
protected:
int Create(void);
};
}
#endif //!_ST_Window_H_
Window.cpp
// include files
#include "sit-window.h"
using namespace std;
namespace app
{
Window::Window(void) : mhInstance(GetModuleHandle(0)), mhWnd(nullptr), mWindowName(nullptr),
mRunState(true), mScreenWidth(0), mScreenHeight(0)
{
}
Window::Window(tstring windowName) : mhInstance(GetModuleHandle(0)), mhWnd(nullptr),
mWindowName(windowName), mRunState(true), mScreenWidth(0), mScreenHeight(0)
{
}
Window::~Window(void)
{
}
int Window::Setup(long int width, long int height)
{
mScreenWidth = width;
mScreenHeight = height;
return Create();
}
LRESULT Window::MessageProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
}
LRESULT CALLBACK Window::WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
Window * wnd;
if (msg == WM_NCCREATE)
{
CREATESTRUCT * pcs = (CREATESTRUCT*)lParam;
wnd = (Window*)pcs->lpCreateParams;
wnd->mhWnd = hwnd;
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pcs->lpCreateParams);
return TRUE;
}
else
{
wnd = (Window*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
}
if (wnd)
return wnd->MessageProc(hwnd, msg, wParam, lParam);
return DefWindowProc(hwnd, msg, wParam, lParam);
}
int Window::Run(void)
{
MSG msg = { 0 };
while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
};
int Window::Create(void) {
WNDCLASSEX wnd;
SecureZeroMemory(&wnd, sizeof(WNDCLASSEX));
wnd.cbClsExtra = NULL;
wnd.cbSize = sizeof(WNDCLASSEX);
wnd.cbWndExtra = NULL;
wnd.hbrBackground = (HBRUSH)(COLOR_WINDOW + 3);
wnd.hCursor = LoadCursor(NULL, IDC_ARROW);
wnd.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wnd.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wnd.hInstance = mhInstance;
wnd.lpfnWndProc = WindowProc;
tstring className = mWindowName;
className.append(L" - WndCls");
wnd.lpszClassName = className.c_str();
wnd.lpszMenuName = nullptr;
wnd.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
if (!RegisterClassEx(&wnd))
{
std::wcout << L"Window class not registered!" << std::endl;
mRunState = false;
return 0x0;
}
RECT rect = { 0, 0, mScreenWidth, mScreenHeight };
if (!AdjustWindowRectEx(&rect, WS_OVERLAPPEDWINDOW, false, NULL))
{
std::wcout << L"Failed to adjust window rect!" << std::endl;
mRunState = false;
return 0x0;
}
else
{
mScreenWidth = rect.right;
mScreenHeight = rect.bottom;
}
mhWnd = CreateWindowEx(NULL, className.c_str(), mWindowName.c_str(),
WS_OVERLAPPEDWINDOW, 100, 200, mScreenWidth, mScreenHeight,
nullptr, nullptr, mhInstance, this);
if (!mhWnd)
{
std::wcout << L"Window not created!" << std::endl;
mRunState = false;
return 0x0;
}
if (ShowWindow(mhWnd, SW_SHOW))
{
std::wcout << L"Failed to show window!" << std::endl;
mRunState = false;
return 0x0;
}
if (!UpdateWindow(mhWnd))
{
std::wcout << L"Failed to update window!" << std::endl;
mRunState = false;
return 0x0;
}
if (!SetForegroundWindow(mhWnd))
{
std::wcout << L"Failed to set to foreground!" << std::endl;
mRunState = false;
return 0x0;
}
return 0x0;
}
}
Main.cpp
// include files
//#include "s-safe-delete-and-release.h"
//#include "s-window.h"
#include "sit-window.h"
#include <iostream>
#include <string>
#include <windows.h>
#include <assert.h>
#pragma comment(lib, "serenity-core.lib")
// namespaces
using namespace std;
// statics
//long int srnty::Window::mScreenWidth = 1024;
//long int srnty::Window::mScreenHeight = 768;
// win main entry point
namespace win {
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{
wcout << L"WinMain() called..." << endl;
app::Window * wnd = new app::Window(L"Window Title");
wnd->Setup(1024, 768);
int result = wnd->Run();
SafeDelete(wnd);
return result;
}
}
// main entry point
int main(int argv, char argc[])
{
// detect memory leaks in the application
#if defined(DEBUG) | defined(_DEBUG)
HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
_CrtSetBreakAlloc(0);
int mlCount = _CrtDumpMemoryLeaks();
wcout << L"Number of memory Leaks: " << to_wstring(mlCount) << endl;
assert(mlCount == 0);
#endif
wcout << L"main() called..." << endl;
win::WinMain(GetModuleHandle(0), nullptr, nullptr, SW_SHOW);
wchar_t title[1024];
wchar_t titleBuffer[1024];
GetConsoleTitle(titleBuffer, 1024);
//wsprintf(title, L"%d", GetCurrentProcessId());
SetConsoleTitle(title);
Sleep(40);
HWND hwndFound = FindWindow(NULL, title);
SetForegroundWindow(hwndFound);
system("pause");
return 0x0;
}
I expect tstring mWindowName; to set the window Title in the title bar when used here mhWnd = CreateWindowEx(NULL, className.c_str(), mWindowName.c_str(), WS_OVERLAPPEDWINDOW, 100, 200, mScreenWidth, mScreenHeight, nullptr, nullptr, mhInstance, this);. The initialization of the tstring mWindowName; is through the constructor in Main.cpp app::Window * wnd = new app::Window(L"Window Title");
As Raymond Chen above clearly pointed out. This was an oversight on my behalf.
In the Window.cpp file LRESULT CALLBACK Window::WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) never returned control the DefWindowProc function there for the never sets the title.
The fucntion should look like this:
LRESULT CALLBACK Window::WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
Window * wnd;
if (msg == WM_NCCREATE)
{
CREATESTRUCT * pcs = (CREATESTRUCT*)lParam;
wnd = (Window*)pcs->lpCreateParams;
wnd->mhWnd = hwnd;
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pcs->lpCreateParams);
//return TRUE;
return DefWindowProc(hwnd, msg, wParam, lParam);
}
else
{
wnd = (Window*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
}
if (wnd)
return wnd->MessageProc(hwnd, msg, wParam, lParam);
return DefWindowProc(hwnd, msg, wParam, lParam);
}
Thank you i hope this helps someone else.

_tfopen_s can function when passed a constant string, but cannot when passed a variable

Hi when I am openning a file in UNICODE environment, it works well with:
_tfopen_s(fp,TEXT("C://puttty.exe"),TEXT("rb"));
But in the following it doesn't work in a function:
#include "stdafx.h"
HINSTANCE hInst;
INT_PTR CALLBACK MainDlgProc(HWND, UINT, WPARAM, LPARAM);
struct _PE_INFO
{
TCHAR* szFileName;
};
class PEFile
{
public:
_PE_INFO pe_info;
public:
PEFile();
virtual ~PEFile();
public:
int ReadPEFile(_PE_INFO& pe);
VOID PEFile::OpenFile(LPOPENFILENAME lpOpenFileName, HWND hWndDlg);
};
PEFile::PEFile()
{
}
PEFile::~PEFile()
{
}
int PEFile::ReadPEFile(_PE_INFO& pe)
{
FILE* fp = NULL;
errno_t t = _tfopen_s(&fp, pe.szFileName, TEXT("rb"));
return t;
}
VOID PEFile::OpenFile(LPOPENFILENAME lpOpenFileName, HWND hWndDlg)
{
TCHAR szPeFileExt[100] = TEXT("*.exe;*.dll;*.scr;*.drv;*.sys");
TCHAR szFileName[256];
memset(szFileName, 0, 256);
memset(lpOpenFileName, 0, sizeof(*lpOpenFileName));
lpOpenFileName->lStructSize = sizeof(*lpOpenFileName);
lpOpenFileName->Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
lpOpenFileName->hwndOwner = hWndDlg;
lpOpenFileName->lpstrFilter = szPeFileExt;
lpOpenFileName->lpstrFile = szFileName;
lpOpenFileName->nMaxFile = MAX_PATH;
GetOpenFileName(lpOpenFileName);
}
INT_PTR CALLBACK MainDlgProc(HWND hDlg, UINT uMessage, WPARAM wParam, LPARAM lParam)
{
PEFile test;
OPENFILENAME stOpenFileName = { 0 };
int t = -1;
//int t = test.ReadPEFile(test.pe_info);
switch (uMessage)
{
case WM_CLOSE:
EndDialog(hDlg, 0);
break;
case WM_INITDIALOG:
test.OpenFile(&stOpenFileName,hDlg);
test.pe_info.szFileName = stOpenFileName.lpstrFile;
t = test.ReadPEFile(test.pe_info);
break;
default:
break;
}
return 0;
}
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
//test.pe_info.szFileName = TEXT("C:\\putty.exe");
DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG1), NULL, MainDlgProc);
getchar();
return 0;
}
And I followed the memory when debuging, I see the szFileName is changed in the process of _tfopen_s, and then shows that the file doesn't exist or system is busy.
I think maybe it's the problem from the class.. Thanks for help!

Getting these 2 errors in C++ (DirectX)

I´m currently working on D3D Renderer and i´m getting these errors:
1.)FIRST ERROR
2.)SECOND ERROR
FOR ANY ADVISE I´LL BE VERY THANKFUL :) + ERRORS ARE MARKED IN CODE AS //1. ERROR --> and //2.ERROR -->//
DXApp.cpp
#include "DXApp.h"
#include <d3dcommon.h>
namespace
{
//USED TO FORWARD MSGS TO USER DEFINED PROC FUNCTION //
DXApp* g_pApp = nullptr;
}
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (g_pApp) return g_pApp->MsgProc(hwnd, msg, wParam, lParam);
else return DefWindowProc(hwnd, msg, wParam, lParam);
}
DXApp::DXApp(HINSTANCE hInstance)
{
m_hAppInstance = hInstance;
m_hAppWnd = NULL;
m_ClientHeight = 800;
m_ClientWidth = 600;
m_AppTitle = "DX11 APP";
m_WndStyle = WS_OVERLAPPEDWINDOW;
m_pDevice = nullptr;
m_pImmediateContext = nullptr;
m_pRenderTargetView = nullptr;
m_pSwapChain = nullptr;
}
DXApp::~DXApp()
{
}
int DXApp::Run()
{
//MAIN MESSAGE LOOP//
MSG msg = { 0 };
while (WM_QUIT != msg.message)
{
if (PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
//UPDATE..//
Update(0.0f);
//RENDER//
Render(0.0f);
}
}
return static_cast<int>(msg.wParam);
}
bool DXApp::Init()
{
if (!InitWindow())
return false;
return true;
}
bool DXApp::InitWindow()
{
//WNDCLASSGENDER
WNDCLASSEX wcex;
ZeroMemory(&wcex, sizeof(WNDCLASSEX));
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_VREDRAW | CS_HREDRAW;
wcex.hInstance = m_hAppInstance;
wcex.lpfnWndProc = MainWndProc;
wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = "DXAPPWNDCLASS";
wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if (!RegisterClassEx(&wcex))
{
OutputDebugString("\nFAILED TO CREATE WINDOW CLASS !\n");
return false;
}
RECT r = { 0, 0, m_ClientWidth, m_ClientHeight };
AdjustWindowRect(&r, m_WndStyle, FALSE);
UINT width = r.right - r.left;
UINT height = r.bottom - r.top;
UINT x = GetSystemMetrics(SM_CXSCREEN) / 2 - width / 2;
UINT y = GetSystemMetrics(SM_CYSCREEN) / 2 - height / 2;
m_hAppWnd = CreateWindow("DXAPPWNDCLASS", m_AppTitle.c_str(), m_WndStyle,
x, y, width, height, NULL, NULL, m_hAppInstance, NULL);
if (!m_hAppWnd)
{
OutputDebugString("\nFAILED TO CREATE WINDOW CLASS !\n");
return false;
}
ShowWindow(m_hAppWnd, SW_SHOW);
return true;
}
bool DXApp::InitDirect3D()
{
UINT createDeviceFlags = 0;
#ifdef _DEBUG
createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif // _DEBUG
D3D_DRIVER_TYPE driverTypes[] =
{
D3D_DRIVER_TYPE_HARDWARE,
D3D_DRIVER_TYPE_WARP,
D3D_DRIVER_TYPE_REFERENCE
};
UINT numDriverTypes = ARRAYSIZE(driverTypes);
D3D_FEATURE_LEVEL featureLevels[] =
{
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_9_3,
};
UINT numFeatureLevels = ARRAYSIZE(featureLevels);
DXGI_SWAP_CHAIN_DESC swapDesc;
ZeroMemory(&swapDesc, sizeof(DXGI_SWAP_CHAIN_DESC));
swapDesc.BufferCount = 1; //Double buffer 0 = 1, 1 = 2
swapDesc.BufferDesc.Width = m_ClientWidth;
swapDesc.BufferDesc.Height = m_ClientHeight;
swapDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapDesc.BufferDesc.RefreshRate.Numerator = 60;
swapDesc.BufferDesc.RefreshRate.Denominator = 1;
swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapDesc.OutputWindow = m_hAppWnd;
swapDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
swapDesc.Windowed = true;
swapDesc.SampleDesc.Count = 1;
swapDesc.SampleDesc.Quality = 0;
swapDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; //FULLSCREEN CEZ ALT-ENTER
HRESULT result;
for (int i = 0; i < numDriverTypes; ++i)
{
D3D11CreateDeviceAndSwapChain(NULL, driverTypes[i], NULL, createDeviceFlags,
featureLevels, numFeatureLevels, D3D11_SDK_VERSION, &swapDesc, &m_pSwapChain, &m_pDevice,
//1.ERROR-->// &featureLevels, &m_pImmediateContext);
if (SUCCEEDED(result))
{
//2.ERROR-->// m_DriverType = driverTypes[i];
break;
}
}
}
LRESULT DXApp::MsgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
}
DXApp.h
#pragma once
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <string>
#include "DXUtil.h"
class DXApp
{
public:
DXApp(HINSTANCE hInstance);
virtual ~DXApp(void);
//MAIN APP LOOP//
int Run();
//FRAMEWORK//
virtual bool Init();
virtual void Update(float dt) = 0;
virtual void Render(float dt) = 0;
virtual LRESULT MsgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
protected:
//WIN 32 ATTRIBUTES//
HWND m_hAppWnd;
HINSTANCE m_hAppInstance;
UINT m_ClientWidth;
UINT m_ClientHeight;
std::string m_AppTitle;
DWORD m_WndStyle;
//DirectX ATTRIBUTES//
ID3D11Device* m_pDevice;
ID3D11DeviceContext* m_pImmediateContext;
IDXGISwapChain* m_pSwapChain;
ID3D11RenderTargetView* m_pRenderTargetView;
D3D_DRIVER_TYPE* m_DriverType;
D3D_FEATURE_LEVEL* m_FeatureLevel;
D3D11_VIEWPORT* m_Viewport;
protected:
//INIT WIN32 WINDOW//
bool InitWindow();
//INIT DirectX
bool InitDirect3D();
};
DXUtil.h
#pragma once
#include <d3d11.h>
#pragma comment(lib, "d3d11.lib")
namespace Memory
{
template <class T> void SafeDelete(T& t)
{
if (t)
{
delete t;
t = nullptr;
}
}
template <class T> void SafeDeleteArr(T& t)
{
if (t)
{
delete[];
t = nullptr;
}
}
template <class T> void SafeRelease(T& t)
{
if (t)
{
t->Release();
t = nullptr;
}
}
}
winmain.cpp
#include "DXApp.h"
class TestApp : public DXApp
{
public:
TestApp(HINSTANCE hInstance);
~TestApp();
bool Init() override;
void Update(float dt) override;
void Render(float dt) override;
};
TestApp::TestApp(HINSTANCE hInstance) : DXApp(hInstance)
{
}
TestApp::~TestApp()
{
}
bool TestApp::Init()
{
if (!DXApp::Init())
return false;
return true;
}
void TestApp::Update(float dt)
{
}
void TestApp::Render(float dt)
{
}
int WINAPI WinMain(__in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in LPSTR lpCmdLine, __in int nShowCmd)
{
TestApp tApp(hInstance);
if (!tApp.Init()) return 1;
return tApp.Run();
}
I suggest you start with some basic tutorials on C/C++ on how to use pointers, pass values by value, and pass values by reference/pointer. These issues have nothing in particular to do with DirectX.
D3D_DRIVER_TYPE* m_DriverType;
D3D_FEATURE_LEVEL* m_FeatureLevel;
D3D11_VIEWPORT* m_Viewport;
These variable declarations should be values, not pointers:
D3D_DRIVER_TYPE m_DriverType;
D3D_FEATURE_LEVEL m_FeatureLevel;
D3D11_VIEWPORT m_Viewport;
and the code should be:
HRESULT result;
for (int i = 0; i < numDriverTypes; ++i)
{
result = D3D11CreateDeviceAndSwapChain(NULL, driverTypes[i], NULL, createDeviceFlags,
featureLevels, numFeatureLevels, D3D11_SDK_VERSION, &swapDesc, &m_pSwapChain,
&m_pDevice, &m_FeatureLevel, &m_pImmediateContext);
if (SUCCEEDED(result))
{
m_DriverType = driverTypes[i];
break;
}
}
It looks to me like you are using a somewhat dated tutorial. You should take a look at the DirectX Tool Kit tutorials.

Is it possible to simulate mouse move and mouse clicks at hidden window?

So is there a way to make my Win32 application "think" that the mouse is moving over its window and making some clicks when the actual window is hidden (i mean ShowWindow(hWnd, SW_HIDE);)?
I tried to simulate mouse moving with PostMessage and SendMessage but no luck so far.
int x = 0;
int y = 0;
while (true)
{
SendMessage(hwnd, WM_MOUSEMOVE, 0, MAKELPARAM(x, y));
x += 10;
y += 10;
Sleep(100);
}
Is this even possible?
Yes it's possible. This is a test hidden window:
#define UNICODE
#include <Windows.h>
#include <Strsafe.h>
#include <Windowsx.h>
LRESULT CALLBACK WndProc(HWND Hwnd, UINT Msg, WPARAM WParam, LPARAM LParam);
INT CALLBACK
WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
INT nCmdShow)
{
WNDCLASSEX WndClass;
ZeroMemory(&WndClass, sizeof(WNDCLASSEX));
WndClass.cbSize = sizeof(WNDCLASSEX);
WndClass.lpfnWndProc = WndProc;
WndClass.hInstance = hInstance;
WndClass.lpszClassName = L"HiddenWinClass";
if(RegisterClassEx(&WndClass))
{
HWND Hwnd;
MSG Msg;
Hwnd = CreateWindowEx(0, L"HiddenWinClass", L"Nan",
0, 0, 0, 0, 0, NULL, NULL, hInstance, NULL);
if(Hwnd)
{
UpdateWindow(Hwnd);
ShowWindow(Hwnd, SW_HIDE);
while(GetMessage(&Msg, 0, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
}
}
return 0;
}
LRESULT CALLBACK
WndProc(HWND Hwnd,
UINT Msg,
WPARAM WParam,
LPARAM LParam)
{
TCHAR Message[255];
switch(Msg)
{
case WM_MOUSEMOVE:
StringCbPrintf(Message, sizeof(Message), L"(%d, %d)",
GET_X_LPARAM(LParam), GET_Y_LPARAM(LParam));
MessageBox(NULL, Message, L"WM_MOUSEMOVE", MB_OK);
break;
default:
return DefWindowProc(Hwnd, Msg, WParam, LParam);
}
return 0;
}
and this is your code:
#define UNICODE
#include <Windows.h>
int
main(int argc, char **argv)
{
HWND Hwnd;
if((Hwnd = FindWindow(L"HiddenWinClass", L"Nan")))
{
int x, y;
for(x = y = 0 ; ; x += 10, y += 10)
{
SendMessage(Hwnd, WM_MOUSEMOVE, 0, MAKELPARAM(x, y));
Sleep(100);
}
}
return 0;
}
It works nicely.