Problem mit CreateWindow()
-
Hallo,
ich habe jetzt, nach einigen erstellten Dreiecken in DirectX/C++ die Fenstererstellung in eine Klasse gepackt. Das funktioniert aber nicht und ich habe ehrlich gesagt keinen blassen Schimmer warum....
Ich hoffe ihr könnt mir weiterhelfen, denn ich habe schon stundenlang nach einer Lösung gesucht aber keine gefunden.Hier sind der Header mit der Klasse:
//----------------------------------------------------------------------------------------------------------// // WINDOW.H //----------------------------------------------------------------------------------------------------------// #ifndef WINDOW_H #define WINDOW_H //----------------------------------------------------------------------------------------------------------// // Includes #include "core.h" //----------------------------------------------------------------------------------------------------------// // Klasse class BASIC_WINDOW { private: LPCWSTR m_caption; // Überschrift des Fensters int m_windowWidth; // Göße des FENSTERS int m_windowHeight; int m_clientWidth; // Größe der für uns wichtigen client area int m_clientHeight; bool m_fullscreen; // Vollbildmodus? bool m_minimized; // minimiert? bool m_maximized; // maximiert? bool m_resizing; // wird das Fenster im Moment vergrößert bzw. verkleinert? bool m_paused; HINSTANCE m_hInst; HWND m_hWnd; ID3D11Device* m_d3dDevice; ID3D11DeviceContext* m_d3dDeviceContext; IDXGISwapChain* m_swapChain; ID3D11RenderTargetView* m_renderTargetView; ID3D11DepthStencilView* m_depthStencilView; ID3D11Texture2D* m_depthStencilBuffer; D3D11_VIEWPORT m_viewport; bool m_enable4xMSAA; UINT m_4xMSAAQuality; public: BASIC_WINDOW(HINSTANCE hInst); // Konstruktor virtual ~BASIC_WINDOW(); // virtueller Destruktor HINSTANCE GetHInst()const; HWND GetHWND()const; virtual bool Init(); bool CreateDirectXWindow(); bool DestroyWindow(); virtual int Run(); virtual void Draw(){}; // = 0 für das Erzwingen der Überschreibung virtual void Update(){}; // s.o. virtual LRESULT WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); virtual void Resize(); }; #endif // WINDOW_H
Die Sourcecode Datei:
//----------------------------------------------------------------------------------------------------------// // WINDOW.CPP //----------------------------------------------------------------------------------------------------------// //----------------------------------------------------------------------------------------------------------// // Includes #include "window.h" #include "string.h" #include <sstream> #include <iostream> //----------------------------------------------------------------------------------------------------------// // Funktionen namespace { BASIC_WINDOW* window = 0; } LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { return window->WndProc(hWnd, msg, wParam, lParam); } BASIC_WINDOW::BASIC_WINDOW(HINSTANCE hInst) : m_hWnd(0), m_d3dDevice(0), m_d3dDeviceContext(0), m_swapChain(0), m_4xMSAAQuality(0) { m_caption = L"DirectX Fenster"; m_clientWidth = 1920; m_clientHeight = 1080; m_fullscreen = false; m_paused = false; m_hInst = hInst; m_enable4xMSAA = true; } BASIC_WINDOW::~BASIC_WINDOW() { ReleaseCOM(m_d3dDevice); ReleaseCOM(m_d3dDeviceContext); ReleaseCOM(m_swapChain); } bool BASIC_WINDOW::CreateDirectXWindow() { //WNDCLASS wndClass = {0}; // WindowClass WNDCLASS wndClass; // WindowClass wndClass.style = CS_HREDRAW | CS_VREDRAW; wndClass.lpfnWndProc = MainWndProc; wndClass.cbClsExtra = 0; wndClass.cbWndExtra = 0; wndClass.hInstance = m_hInst; wndClass.hIcon = LoadIcon(0, IDI_APPLICATION); wndClass.hCursor = LoadCursor(0, IDC_ARROW); wndClass.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH); wndClass.lpszMenuName = 0; wndClass.lpszClassName = L"D3DWndClassName"; if(!RegisterClass(&wndClass)) // Klasse Registrieren { MessageBox(NULL, L"Cannot create Window Class!", L"Error", MB_OK | MB_ICONERROR); // Falls es fehlschlägt return false; } RECT rc = {0, 0, m_clientWidth, m_clientHeight}; AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE); // die client bzw. window area berechnen m_windowWidth = rc.right - rc.left; m_windowHeight = rc.bottom - rc.top; //m_hWnd = CreateWindow(L"D3DWindowClass", m_caption, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, 0, 0, m_hInst, 0); // Fenster erstellen m_hWnd = CreateWindow(L"D3DWindowClass", L"D3D Window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 100, 100, 0, 0, m_hInst, 0); // Fenster erstellen DWORD x = GetLastError(); if(!m_hWnd) { MessageBox(NULL, L"Cannot create the Window!", L"Error", MB_OK | MB_ICONERROR); // falls es fehlschlägt return false; } ShowWindow(m_hWnd, 0); // Fenster zeigen // -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- UINT createDeviceFlags = 0; #if defined(DEBUG) || defined(_DEBUG) // Wenn in debug mode, dann die flag zum erstellen verwenden createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; #endif D3D_FEATURE_LEVEL featureLevel; HRESULT hr = D3D11CreateDevice(0, D3D_DRIVER_TYPE_HARDWARE, 0, createDeviceFlags, 0, 0, D3D11_SDK_VERSION, &m_d3dDevice, &featureLevel, &m_d3dDeviceContext); // d3dDevice erstellen if(FAILED(hr)) // fehlgeschlagen? { MessageBox(0, L"Creating the d3dDevice failed!", L"Error", MB_OK | MB_ICONERROR); return false; } if(featureLevel != D3D_FEATURE_LEVEL_11_0) // directx11 nicht unterstützt? { MessageBox(0, L"Direct3D Feature Level 11 unsupported.", L"Error", MB_OK | MB_ICONERROR); return false; } m_d3dDevice->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM, 4, &m_4xMSAAQuality); // Wie gut kann vierfaches MSAA unterstützt werden? // swap chain desc ausfüllen DXGI_SWAP_CHAIN_DESC sd; sd.BufferDesc.Width = m_clientWidth; sd.BufferDesc.Height = m_clientHeight; 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; if(m_enable4xMSAA) { sd.SampleDesc.Count = 4; sd.SampleDesc.Quality = m_4xMSAAQuality-1; } else { sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; } sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.BufferCount = 1; sd.OutputWindow = m_hWnd; sd.Windowed = true; sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; sd.Flags = 0; IDXGIDevice* dxgiDevice = 0; // ein bisschen code zum erstellen der swap chain m_d3dDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice); IDXGIAdapter* dxgiAdapter = 0; dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&dxgiAdapter); IDXGIFactory* dxgiFactory = 0; dxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&dxgiFactory); dxgiFactory->CreateSwapChain(m_d3dDevice, &sd, &m_swapChain); ReleaseCOM(dxgiDevice); // ungenutzte COM objekte löschen ReleaseCOM(dxgiAdapter); ReleaseCOM(dxgiFactory); Resize(); // Depth/Stencil Buffer und Viewport einstellen return true; // hat alles geklappt?!? } bool BASIC_WINDOW::DestroyWindow() { return true; } int BASIC_WINDOW::Run() { MSG msg = {0}; while(msg.message != WM_QUIT) { // If there are Window messages then process them. if(PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) { TranslateMessage( &msg ); DispatchMessage( &msg ); } // Otherwise, do animation/game stuff. else { if( !m_paused ) { } else { Sleep(100); } } } return (int)msg.wParam; } LRESULT BASIC_WINDOW::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) // Nachrichten, die für uns von Bedeutung sind dabei? { case WM_DESTROY: // Wenn Fenster geschlossen wird, PostQuitMessage(0); // die QuitMessage 0 senden return 0; case WM_ACTIVATE: // Wenn das Fenster if(LOWORD(wParam) == WA_INACTIVE)// inaktiv wird, pausieren { m_paused = true; } else // wieder aktiv wird, starten { m_paused = false; } return 0; case WM_SIZE: // diese NAchricht wird gesendet, wenn irgentetwas mit der GrÖße des Fensters passiert (z.B. Maximiert, Minimiert) m_clientWidth = LOWORD(lParam); // Setze die neue Größe des Fensters m_clientHeight = HIWORD(lParam); if(m_d3dDevice) // Wenn das Fenster schon existiert... { if(wParam == SIZE_MINIMIZED) // Wenn das Fenster Minimiert wird { m_paused = true; m_minimized = true; m_maximized = false; } else if(wParam == SIZE_MAXIMIZED) // Wenn das Fenster Maximiert wird { m_paused = false; m_minimized = false; m_maximized = true; Resize(); } else if(wParam == SIZE_RESTORED) // Wenn das Fenster vom maxi- oder minimierten Zustand zurück in den Fenstermodus gesetzt wird { if(m_minimized) // War es vorher Minimiert? { m_paused = false; m_minimized = false; Resize(); } else if(m_maximized) // War es vorher Maximiert? { m_paused = false; m_maximized = false; Resize(); } else if(m_resizing) // Wird das Fenster an den Seiten verstellt? { // Wenn das Fenster noch verstellt wird, macht es keinen Sinn etwas zu tun, weil man das Fenster sonst sehr of neu erstellen würde, was zu laggen führen würde } else // Ist sonst etwas? { Resize(); } } } return 0; case WM_ENTERSIZEMOVE: // Diese Nachricht wird gesendet, wenn jemand anfängt, das Fenster zu verstellen m_paused = true; m_resizing = true; return 0; case WM_EXITSIZEMOVE: // Diese Nachricht wird gesendet, wenn die verstell-Balken losgelassen werden m_paused = false; m_resizing = false; Resize(); return 0; case WM_MENUCHAR: // Wenn man einen Knopf drückt, der nichts bewirkt, mackt Windows automatisch einen Piep-Ton return MAKELRESULT(0, MNC_CLOSE); // Nicht piepen wenn man Alt+Enter drückt case WM_GETMINMAXINFO: // Das Fenster davon abhalten, zu klein zu werden ((MINMAXINFO*)lParam)->ptMinTrackSize.x = 200; ((MINMAXINFO*)lParam)->ptMinTrackSize.y = 200; return 0; default: return DefWindowProc(hWnd, msg, wParam, lParam); // Wenn nichts von bedeutung dabei, messages an die normale WndProc übergeben } } bool BASIC_WINDOW::Init() { return CreateDirectXWindow(); } void BASIC_WINDOW::Resize() { ReleaseCOM(m_renderTargetView); ReleaseCOM(m_depthStencilView); ReleaseCOM(m_depthStencilBuffer); // Setze den backBuffer der swap chain auf die (neuen) Maße m_swapChain->ResizeBuffers(1, m_clientWidth, m_clientHeight, DXGI_FORMAT_R8G8B8A8_UNORM, 0); ID3D11Texture2D* backBuffer; m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&backBuffer)); m_d3dDevice->CreateRenderTargetView(backBuffer, 0, &m_renderTargetView); ReleaseCOM(backBuffer); // Erstelle den depth/stencil buffer neu D3D11_TEXTURE2D_DESC depthStencilDesc; depthStencilDesc.Width = m_clientWidth; depthStencilDesc.Height = m_clientHeight; depthStencilDesc.MipLevels = 1; depthStencilDesc.ArraySize = 1; depthStencilDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; if( m_enable4xMSAA ) { depthStencilDesc.SampleDesc.Count = 4; depthStencilDesc.SampleDesc.Quality = m_4xMSAAQuality-1; } else { 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; m_d3dDevice->CreateTexture2D(&depthStencilDesc, 0, &m_depthStencilBuffer); m_d3dDevice->CreateDepthStencilView(m_depthStencilBuffer, 0, &m_depthStencilView); // Binde den neuen Depht/Stencil Buffer und das Render Target View an die Rendering Pipeline m_d3dDeviceContext->OMSetRenderTargets(1, &m_renderTargetView, m_depthStencilView); // Setze den Viewport m_viewport.TopLeftX = 0; m_viewport.TopLeftY = 0; m_viewport.Width = static_cast<float>(m_clientWidth); m_viewport.Height = static_cast<float>(m_clientHeight); m_viewport.MinDepth = 0.0f; m_viewport.MaxDepth = 1.0f; m_d3dDeviceContext->RSSetViewports(1, &m_viewport); }
Und natürlich die core datei mit den Includes:
//----------------------------------------------------------------------------------------------------------// // CORE.H //----------------------------------------------------------------------------------------------------------// #ifndef CORE_H #define CORE_H //----------------------------------------------------------------------------------------------------------// // Includes #include <DXGI.h> #include <D3D11.h> #include <D3DX11.h> #include <D3D10.h> #include <D3DX10.h> #include <DxErr.h> #include <Windows.h> #pragma comment (lib, "d3d11.lib") #pragma comment (lib, "d3dx11.lib") #pragma comment (lib, "dxgi.lib") #pragma comment (lib, "dxerr.lib") //----------------------------------------------------------------------------------------------------------// // Macros und sonstige Defines #define ReleaseCOM(x) (x->Release()) #endif // CORE_H
Jaja und die überschaubare main.cpp:
//----------------------------------------------------------------------------------------------------------// // MAIN.CPP //----------------------------------------------------------------------------------------------------------// //----------------------------------------------------------------------------------------------------------// // Includes #include "window.h" //----------------------------------------------------------------------------------------------------------// // main() int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, PSTR cmdLine, int cmdShow) { BASIC_WINDOW window(hInst); if(!window.Init()) { MessageBox(NULL, L"Could not Initialize the Window", L"Error", MB_ICONERROR); return -1; } window.Run(); return 0; }
Das ganze ist an den Code aus dem Buch "Introduction to 3D Game Programming with DirectX 11" angelehnt (oder besser gesagt zum grüßten Teil übernommen).
Jedoch schlägt bei mir immer die "CreateWindow(...)" Funktion fehl und somit ist m_hWnd nicht definiert.
Ich hoffe ihr könnt mir helfen (ich bin mir fast sicher, dass es wieder irgenteine Kleinigkeit ist )LG Sky
-
Schau dir mal, was du an RegisterClass übergibst, und dann schau dir deinen CreateWindow Aufruf an.
-
Ich weiß, ist ein bisschen OT, aber ein eigener Thread lohnt sich dafür nicht.
Skybuildhero schrieb:
ID3D11RenderTargetView* m_renderTargetView; ID3D11DepthStencilView* m_depthStencilView; ID3D11Texture2D* m_depthStencilBuffer;
Ist es notwendig, dass man selber eine ID3D11Texture2D Referenz auf den Depth-Stencil-Buffer hält? Oder reicht es, wenn man wie beim backBuffer, nur eine RenderTargetView Referenz hält.
@Skybuildhero: Wenn du dein Fenster erstellst, rufst du BASIC_WINDOW::Resize() auf. Und in der ersten Zeile gibst du ein paar COM Objekte frei, die zu diesem Zeitpunkt noch gar nicht existieren.
Ich würde zwischen erstellen und "resizen" unterscheiden (sprich 2 Funktionen). Das löst allerdings noch nicht aller Probleme, denn CreateWindow sendet auch eine WM_SIZE Nachricht die dann abgearbeitet wird
bevor du deine D3D11 Objekte erstellst ==> püfe (z.B. in BASIC_WINDOW::Resize ob dein Device schon erstellt ist, und resize nur dann.
Außerdem:[url] http://msdn.microsoft.com/en-us/library/windows/desktop/bb205075.aspx#Handling_Window_Resizing [/url]
-
Mechanics schrieb:
Schau dir mal, was du an RegisterClass übergibst, und dann schau dir deinen CreateWindow Aufruf an.
Was meinst du damit?
-
Dass der Class Name unterschiedlich ist.
-
@OT_FRAGE
Ich hab jetzt ind der resize() funktion eine Überprüfung drin aber es geht immer noch nicht.
Und in der msgProg ist war ja schon vorher ein Test, ob der device erstellt ist.
-
Ja das mist dem Klass Name war zwar ein Fehler aber nach dem fix siehts immer noch nicht besser aus.
Irgentwo ist da ganz arg der Wurm drin...WNDCLASS wndClass = {0}; // WindowClass wndClass.style = CS_HREDRAW | CS_VREDRAW; wndClass.lpfnWndProc = MainWndProc; wndClass.cbClsExtra = 0; wndClass.cbWndExtra = 0; wndClass.hInstance = m_hInst; wndClass.hIcon = LoadIcon(0, IDI_APPLICATION); wndClass.hCursor = LoadCursor(0, IDC_ARROW); wndClass.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH); wndClass.lpszMenuName = 0; wndClass.lpszClassName = L"D3DWndClassName"; if(!RegisterClass(&wndClass)) // Klasse Registrieren { MessageBox(NULL, L"Cannot create Window Class!", L"Error", MB_OK | MB_ICONERROR); // Falls es fehlschlägt return false; } RECT rc = {0, 0, m_clientWidth, m_clientHeight}; AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE); // die client bzw. window area berechnen m_windowWidth = rc.right - rc.left; m_windowHeight = rc.bottom - rc.top; //m_hWnd = CreateWindow(L"D3DWindowClass", m_caption, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, 0, 0, m_hInst, 0); // Fenster erstellen m_hWnd = CreateWindow(L"D3DWndClassName", L"D3D Window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 100, 100, 0, 0, m_hInst, 0); // Fenster erstellen DWORD x = GetLastError(); if(!m_hWnd) { MessageBox(NULL, L"Cannot create the Window!", L"Error", MB_OK | MB_ICONERROR); // falls es fehlschlägt return false; } ShowWindow(m_hWnd, 0); // Fenster zeigen
-
Wenn die Funktion fehlschlängt, ruf GetLastError auf und schau, was es zurückgibt.
-
Mechanics schrieb:
Wenn die Funktion fehlschlängt, ruf GetLastError auf und schau, was es zurückgibt.
Wie du siehst mache ich das auch direkt nach der Funktion, aber es gibt "0" zurück.
-
Nee, hab ich übersehen, weil ich nur nach if (!...) danach geschaut habe.
CreateWindow sollte eine WM_CREATE Nachricht schicken, du könntest schauen, ob die ankommt. Sonst könnten noch die Parameter falsch sein, wobei ich hier jetzt nichts besonderes sehe.
-
Es kommt keine WM_CREATE Nachicht an