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.
Related
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;
}
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.
In a short sample I generate a HwndRenderTarget, a Brush, a PathGeometry in this two lines are drawn both starting at the same Point. But in the rendered Frame they don't start at the same point but clearly intersect each other ( they are extended beyond the starting point)
Main.cpp
#include<Windows.h>
#include "Graphics.h"
Graphics* graphics;
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
//case WM_PAINT:
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE prevInstance, LPWSTR cmd, int nCMDShow)
{
WNDCLASSEX windowclass;
ZeroMemory(&windowclass, sizeof(WNDCLASSEX));
windowclass.cbSize = sizeof(WNDCLASSEX);
windowclass.hbrBackground = (HBRUSH)COLOR_WINDOW;
windowclass.hInstance = hInstance;
windowclass.lpfnWndProc = WindowProc;
windowclass.lpszClassName = "MainWindow";
windowclass.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&windowclass);
RECT rect = { 0,0,564,564 };
AdjustWindowRectEx(&rect, WS_OVERLAPPEDWINDOW, false, WS_EX_OVERLAPPEDWINDOW);
HWND windowhandle = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,"MainWindow", "Intersection Test", WS_OVERLAPPEDWINDOW, 100, 100,
rect.right - rect.left, rect.bottom- rect.top, NULL, NULL, hInstance, 0);
if (!windowhandle) return -1;
graphics = new Graphics();
if (!graphics->Init(windowhandle))
{
delete graphics;
return -1;
}
ShowWindow(windowhandle, nCMDShow);
graphics->PrepareSpirale();
MSG msg;
msg
.message = WM_NULL;
while (msg.message != WM_QUIT) //
{
if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
DispatchMessage(&msg);
}
else
{
graphics->BeginDraw();
graphics->ClearScreen(1, 1, 1);
graphics->DrawGraphics();
graphics->EndDraw();
}
}
delete graphics;
return 0;
}
Graphics.h
#pragma once
#include <Windows.h>
#include<d2d1.h>
#include <math.h>
class Graphics
{
ID2D1Factory* factory;
ID2D1HwndRenderTarget* renderTarget;
ID2D1PathGeometry * BorderCCW;
ID2D1GeometrySink * pSink;
ID2D1SolidColorBrush *RedBrush;
public:
Graphics();
~Graphics();
bool Init(HWND windowHandle);
void BeginDraw() { renderTarget->BeginDraw(); }
void EndDraw() { renderTarget->EndDraw(); }
void PrepareSpirale();
void DrawGraphics();
void ClearScreen(float r, float g, float b );
};
Graphics.cpp
#include"Graphics.h"
Graphics::Graphics()
{
factory = NULL;
renderTarget = NULL;
pSink = NULL;
BorderCCW = NULL;
RedBrush = NULL;
}
Graphics::~Graphics()
{
if (factory) factory->Release();
if (renderTarget) renderTarget->Release();
}
bool Graphics::Init(HWND windowHandle)
{
HRESULT res = 0;
// Create renderTarget
if (SUCCEEDED(res))
{
res = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &factory);
RECT rect;
GetClientRect(windowHandle, &rect);
D2D1_SIZE_U size = D2D1::SizeU(
rect.right - rect.left,
rect.bottom - rect.top
);
if (SUCCEEDED(res))
res = factory->CreateHwndRenderTarget(
D2D1::RenderTargetProperties(),
D2D1::HwndRenderTargetProperties(windowHandle, size),
&renderTarget);
FLOAT dpiX, dpiY;
factory->GetDesktopDpi(&dpiX, &dpiY);
// Create Other Resurces
if (SUCCEEDED(res))
{
// Brushes
res = renderTarget->CreateSolidColorBrush(
D2D1::ColorF(1.0f, 0.13f, 0.13f, 1.0f),
&RedBrush);
}
return true;
}
return false;
}
void Graphics::PrepareSpirale()
{
HRESULT res = 0;
if (SUCCEEDED(res))
{
res = factory->CreatePathGeometry(&BorderCCW);
if (SUCCEEDED(res))
{
res = BorderCCW->Open(&pSink);
D2D1_POINT_2F currentLocation = { 281.5f, 281.5f };
pSink->BeginFigure(currentLocation, D2D1_FIGURE_BEGIN_HOLLOW);
pSink->AddLine(D2D1::Point2F(132.5, 432.5));
pSink->EndFigure(D2D1_FIGURE_END_CLOSED);
pSink->BeginFigure(currentLocation, D2D1_FIGURE_BEGIN_HOLLOW);
pSink->AddLine(D2D1::Point2F(132+ 282.5f, 432.5));
pSink->EndFigure(D2D1_FIGURE_END_CLOSED);
}
//}
res = pSink->Close();
pSink->Release();
pSink = NULL;
}
}
void Graphics::DrawGraphics()
{
//renderTarget->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
renderTarget->DrawGeometry(BorderCCW, RedBrush, 2.f);
}
void Graphics::ClearScreen(float r, float g, float b )
{
renderTarget->Clear(D2D1::ColorF(r, g, b));
}
Rendered Lines
As this is my first adventure into C++ any style comments are also most welcome, but them main question is to find an explaination for this strange phenomenon.
First thing first, I am not that good in programming yet, so forgive me if I cant solve trivial problems. I want to display a basic screen in a window, so I made a framework for it from 3 diferrent sources, cause I wanted to write it from step to step to fully understand it. But still, I am getting this 3 errors and I dont know how to solve them. Thanking you in advance of you help.
The first code:
#ifndef WINAPPFRAME_H
#define WINAPPFRAME_H
#include <windows.h>
#include <windowsx.h>
#include <d3d11.h>
#include <d3dx11.h>
#include <d3dx10.h>
#include <string>
#pragma comment (lib, "d3d11.lib")
#pragma comment (lib, "d3dx11.lib")
#pragma comment (lib, "d3dx10.lib")
#define Release(x) { if(x){ x->Release(); x = 0; } }
#ifndef HR
#define HR(x) (x)
#endif
class D3Dwap
{
public:
D3Dwap(HINSTANCE hInstance);
~D3Dwap();
HINSTANCE AppInst()const;
HWND MainWnd()const;
bool Initialize();
int Run();
void Draw();
static LRESULT CALLBACK MsgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
protected:
bool InitMainWindow();
bool InitDirect3D();
protected:
HINSTANCE hD3DwapInst;
HWND hMainWnd;
ID3D11Device* D3Dwap_device;
ID3D11DeviceContext* D3Dwap_dev_context;
IDXGISwapChain* D3Dwap_SwapChain;
ID3D11Texture2D* D3Dwap_DepthStencilBuffer;
ID3D11RenderTargetView* D3Dwap_RenderTargetView;
ID3D11DepthStencilView* D3Dwap_DepthStencilView;
D3D11_VIEWPORT D3Dwap_ScreenViewport;
ID3D11Texture2D* backBuffer;
std::wstring MainWndCaption;
D3D_DRIVER_TYPE d3dDriverType;
int ScreenWidth;
int ScreenHeight;
};
D3Dwap* d3dwapl = 0;
#endif
The second part:
#include "WinAppFrame.h"
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
return d3dwapl->MsgProc(hwnd, msg, wParam, lParam);
}
D3Dwap::D3Dwap(HINSTANCE hInstance):
hD3DwapInst(hInstance),
MainWndCaption(L"Engine 2.0"),
d3dDriverType(D3D_DRIVER_TYPE_HARDWARE),
ScreenWidth(800),
ScreenHeight(600),
hMainWnd(0),
D3Dwap_device(0),
D3Dwap_dev_context(0),
D3Dwap_SwapChain(0) {}
D3Dwap::~D3Dwap()
{
Release(D3Dwap_SwapChain);
if( D3Dwap_dev_context )
D3Dwap_dev_context->ClearState(); //Ha még aktív az ezköz tartalma, törli azt
Release(D3Dwap_dev_context);
Release(D3Dwap_device);
}
HINSTANCE D3Dwap::AppInst()const
{
return hD3DwapInst;
}
HWND D3Dwap::MainWnd()const
{
return hMainWnd;
}
int D3Dwap::Run()
{
MSG msg;
while(msg.message != WM_QUIT)
{
if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
Draw();
}
return msg.wParam;
}
bool D3Dwap::Initialize()
{
if(!InitMainWindow())
return false;
if(!InitDirect3D())
return false;
return true;
}
LRESULT D3Dwap::MsgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
bool D3Dwap::InitMainWindow()
{
WNDCLASSEX wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hD3DwapInst;
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
wc.lpszClassName = L"D3Dwap_test";
if( !RegisterClassEx(&wc) )
{
MessageBox(0, L"Az ablakot nem sikerült regisztrálni", 0, 0);
return false;
}
RECT Rect = { 0, 0, ScreenWidth, ScreenHeight };
AdjustWindowRect(&Rect, WS_OVERLAPPEDWINDOW, false);
int width = Rect.right - Rect.left;
int height = Rect.bottom - Rect.top;
hMainWnd = CreateWindow (L"D3Dwap_test",
MainWndCaption.c_str(),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
width,
height,
0,
0,
hD3DwapInst,
0);
if( !hMainWnd )
{
MessageBox(0, L"Az ablakot nem sikerült létrehozni!", 0, 0);
return false;
}
ShowWindow(hMainWnd, SW_SHOW);
UpdateWindow(hMainWnd);
return true;
}
bool D3Dwap::InitDirect3D()
{
UINT create_D3Dwap_device_flags = 0;
D3D_FEATURE_LEVEL featurelevel;
HRESULT hr = D3D11CreateDevice(0,
d3dDriverType,
0,
create_D3Dwap_device_flags = 0,
0,
0,
D3D11_SDK_VERSION,
&D3Dwap_device,
&featurelevel,
&D3Dwap_dev_context);
if( FAILED(hr) )
{
MessageBox(0, L"A D3D11 eszközt nem sikerült létrehozni!", 0, 0);
return false;
}
if( featurelevel != D3D_FEATURE_LEVEL_11_0 )
{
MessageBox(0, L"A DirectX 11.0 a hardware által nem támogatott!", 0, 0);
return false;
}
DXGI_SWAP_CHAIN_DESC sd;
sd.BufferDesc.Width = ScreenWidth;
sd.BufferDesc.Height = ScreenHeight;
sd.BufferDesc.RefreshRate.Numerator = 60;
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
sd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.BufferCount = 1;
sd.OutputWindow = hMainWnd;
sd.Windowed = true;
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
sd.Flags = 0;
IDXGIDevice* dxgiDevice = 0;
if(FAILED(HR(D3Dwap_device->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice))))
{
return false;
}
IDXGIAdapter* dxgiAdapter = 0;
if(FAILED(HR(dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&dxgiAdapter))))
{
return false;
}
IDXGIFactory* dxgiFactory = 0;
if(FAILED(HR(dxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&dxgiFactory))))
{
return false;
}
HR(dxgiFactory->CreateSwapChain(D3Dwap_device, &sd, &D3Dwap_SwapChain));
ID3D11Texture2D* backBuffer;
if(FAILED(HR(D3Dwap_SwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&backBuffer)))))
{
return false;
}
if(FAILED(HR(D3Dwap_device->CreateRenderTargetView(backBuffer, 0, &D3Dwap_RenderTargetView))))
{
return false;
}
Release(backBuffer);
D3D11_TEXTURE2D_DESC depthStencilDesc;
depthStencilDesc.Width = ScreenWidth;
depthStencilDesc.Height = ScreenHeight;
depthStencilDesc.MipLevels = 1;
depthStencilDesc.ArraySize = 1;
depthStencilDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
depthStencilDesc.SampleDesc.Count = 1;
depthStencilDesc.SampleDesc.Quality = 0;
depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
depthStencilDesc.CPUAccessFlags = 0;
depthStencilDesc.MiscFlags = 0;
if(FAILED(HR(D3Dwap_device->CreateTexture2D(&depthStencilDesc, 0, &D3Dwap_DepthStencilBuffer))))
{
return false;
}
if(FAILED(HR(D3Dwap_device->CreateDepthStencilView(D3Dwap_DepthStencilBuffer, 0, &D3Dwap_DepthStencilView))))
{
return false;
}
D3Dwap_dev_context->OMSetRenderTargets(1, &D3Dwap_RenderTargetView, D3Dwap_DepthStencilView);
D3Dwap_ScreenViewport.TopLeftX = 0;
D3Dwap_ScreenViewport.TopLeftY = 0;
D3Dwap_ScreenViewport.Width = static_cast<float>(ScreenWidth);
D3Dwap_ScreenViewport.Height = static_cast<float>(ScreenHeight);
D3Dwap_ScreenViewport.MinDepth = 0.0f;
D3Dwap_ScreenViewport.MaxDepth = 1.0f;
D3Dwap_dev_context->RSSetViewports(1, &D3Dwap_ScreenViewport);
Release(dxgiDevice);
Release(dxgiAdapter);
Release(dxgiFactory);
return true;
}
and the third code:
#include "WinAppFrame.h"
class InitDirect3Dwap : public D3Dwap
{
public:
InitDirect3Dwap(HINSTANCE hInstance);
~InitDirect3Dwap();
bool Initialize();
void UpdateScene(float dt);
void Draw();
};
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance,
PSTR cmdLine, int showCmd)
{
// Enable run-time memory check for debug builds.
#if defined(DEBUG) | defined(_DEBUG)
_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif
InitDirect3Dwap theApp(hInstance);
if( !theApp.Initialize() )
return 0;
return theApp.Run();
}
InitDirect3Dwap::InitDirect3Dwap(HINSTANCE hInstance)
: D3Dwap(hInstance)
{
}
InitDirect3Dwap::~InitDirect3Dwap()
{
}
bool InitDirect3Dwap::Initialize()
{
if(!D3Dwap::Initialize())
return false;
return true;
}
void InitDirect3Dwap::UpdateScene(float dt)
{
}
void InitDirect3Dwap::Draw()
{
D3Dwap_dev_context->ClearRenderTargetView(D3Dwap_RenderTargetView, D3DXCOLOR(0.0f, 0.2f, 0.4f, 1.0f));
D3Dwap_dev_context->ClearDepthStencilView(D3Dwap_DepthStencilView, D3D11_CLEAR_DEPTH|D3D11_CLEAR_STENCIL, 1.0f, 0);
HR(D3Dwap_SwapChain->Present(0, 0));
}
1st: Error 29 error LNK2005: "class D3Dwap * d3dwapl" (?d3dwapl##3PAVD3Dwap##A) already defined in main.obj C:\Users\Seraph\documents\visual studio 2012\Projects\Engine_2.0\Engine_2.0\WinAppFrame.obj Engine_2.0
2nd: Error 30 error LNK2019: unresolved external symbol "public: void __thiscall D3Dwap::Draw(void)" (?Draw#D3Dwap##QAEXXZ) referenced in function "public: int __thiscall D3Dwap::Run(void)" (?Run#D3Dwap##QAEHXZ) C:\Users\Seraph\documents\visual studio 2012\Projects\Engine_2.0\Engine_2.0\WinAppFrame.obj Engine_2.0
3rd: Error 31 error LNK1120: 1 unresolved externals C:\Users\Seraph\documents\visual studio 2012\Projects\Engine_2.0\Debug\Engine_2.0.exe 1 1 Engine_2.0
You include "WinAppFrame.h" twice which makes a class defined there to duplicate. A common solution to this issue is to put
#pragma once
at the beginning of you WinAppFrame.h file.
Then, you declare a method Draw in class D3Dwap but there's no definition in a corresponding .cpp file.
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...)