Sign in to follow this  
Jemme

Directx 11 Wpf Message pump

Recommended Posts

Howdy

Ive got a WPF level editor  and a C++ Directx DLL.

Here are the main functions:

 public static class Engine
    {
        //DX dll
        //Init
        [DllImport("Win32Engine.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern void Initialize(IntPtr hwnd, int Width, int Height);

        //Messages / Input
        [DllImport("Win32Engine.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern void HandleMessage(IntPtr hwnd, int msg, int wParam, int lParam);

        //Load
        [DllImport("Win32Engine.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern void Load();

        //Update
        [DllImport("Win32Engine.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern void Update();

        //Draw
        [DllImport("Win32Engine.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern void Draw();

        //Shutdown
        [DllImport("Win32Engine.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern void ShutDown();

    }

Okay so what is the proper way to get the window hosted inside a control and the pump the engine?

At the moment i have it inside a (winfom) panel and use:
 

 protected override void OnSourceInitialized(EventArgs e)
        {
            base.OnSourceInitialized(e);

            HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
            source.AddHook(WndProc);
        }

        private static IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            Engine.HandleMessage(hwnd, msg, (int)wParam, (int)lParam);

            Engine.Update();
            Engine.Draw();

            return IntPtr.Zero;
        }

But there's just a few problems:

  • Messages come from everywhere not just the panel (due to using the main window)
  • The input doesn't actually work
  • It's super duper ugly code wise

In terms of c++ side the normal enigne (non-editor ) uses this pump:

	while (msg.message != WM_QUIT)
	{
		while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);


			//Input
			if (msg.message == WM_INPUT)
			{

				//Buffer size
				UINT size = 512;
				BYTE buffer[512];
				GetRawInputData((HRAWINPUT)msg.lParam, RID_INPUT, (LPVOID)buffer, &size, sizeof(RAWINPUTHEADER));

				RAWINPUT *raw = (RAWINPUT*)buffer;

				if (raw->header.dwType == RIM_TYPEKEYBOARD)
				{
					bool keyUp = raw->data.keyboard.Flags & RI_KEY_BREAK;
					USHORT keyCode = raw->data.keyboard.VKey;

					if (!keyUp)
					{
						Keyboard::SetKeyState(keyCode, true);
					}
					else
					{
						Keyboard::SetKeyState(keyCode, false);
					}
				}
			}
		}

		time->Update();
		engine->Update(time->DeltaTime());
		engine->Draw();
	}

Not the nicest loop but works for now for testing and things.

Now the Editor versions code is:
 

//Initalize enigne and all sub systems
extern "C"
{
	//Hwnd is a panel usually
	DLLExport void Initialize(int* hwnd, int Width, int Height)
	{
		engine = new Engine();
		time = new Timer();
		time->Update();

		if (engine->Initialize(Width, Height,(WINHANDLE)hwnd))
		{
			//WindowMessagePump();
		}
		else
		{
			//return a fail?
		}
	}
}

extern "C"
{
	DLLExport void HandleMessage(int* hwnd, int msg, int wParam, int lParam)
	{
			//Input
			if (msg == WM_INPUT)
			{

				//Buffer size
				UINT size = 512;
				BYTE buffer[512];
				GetRawInputData((HRAWINPUT)lParam, RID_INPUT, (LPVOID)buffer, &size, sizeof(RAWINPUTHEADER));

				RAWINPUT *raw = (RAWINPUT*)buffer;

				if (raw->header.dwType == RIM_TYPEKEYBOARD)
				{
					bool keyUp = raw->data.keyboard.Flags & RI_KEY_BREAK;
					USHORT keyCode = raw->data.keyboard.VKey;

					if (!keyUp)
					{
						Keyboard::SetKeyState(keyCode, true);
					}
					else
					{
						Keyboard::SetKeyState(keyCode, false);
					}
				}
		}
	}
}

//Load
extern "C"
{
	DLLExport void Load()
	{
		engine->Load();
	}
}

//Update
extern "C"
{
	DLLExport void Update()
	{
		time->Update();
		engine->Update(time->DeltaTime());
	}
}

//Draw
extern "C"
{
	DLLExport void Draw()
	{
		engine->Draw();
	}
}

//ShutDown Engine
extern "C"
{
	DLLExport void ShutDown()
	{
		engine->ShutDown();
		delete time;
		delete engine;
	}
}

 

Any advice of how to do this properly would be much apprcieated.

p.s in my opinion the loop should kind of stay the same? but allow the wpf to psuh the message through some how and the loop within c++ calls the update and draw still so :
 

//Gets message from C# somehow
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
  TranslateMessage(&msg);
  DispatchMessage(&msg);
  //Input
}

time->Update();
engine->Update(time->DeltaTime());
engine->Draw();
//returns back to c#

^ some how have that in c++ as the message pump called from wpf 

Thanks :D

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Forum Statistics

    • Total Topics
      628285
    • Total Posts
      2981836
  • Similar Content

    • By reders
      Hi, everyone!
      I "finished" building my first game. Obviously Pong.
      It's written in C++ on Visual Studio with SFML.
      Pong.cpp
      What do you think? What should I consider doing to improve the code?
      Thank you very much.
       
      EDIT: added some screenshot and .zip file of the playable game
       
      Pong.zip


    • By GreenGodDiary
      I'm attempting to implement some basic post-processing in my "engine" and the HLSL part of the Compute Shader and such I think I've understood, however I'm at a loss at how to actually get/use it's output for rendering to the screen.
      Assume I'm doing something to a UAV in my CS:
      RWTexture2D<float4> InputOutputMap : register(u0); I want that texture to essentially "be" the backbuffer.
       
      I'm pretty certain I'm doing something wrong when I create the views (what I think I'm doing is having the backbuffer be bound as render target aswell as UAV and then using it in my CS):
       
      DXGI_SWAP_CHAIN_DESC scd; ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC)); scd.BufferCount = 1; scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_UNORDERED_ACCESS; scd.OutputWindow = wndHandle; scd.SampleDesc.Count = 1; scd.Windowed = TRUE; HRESULT hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, NULL, NULL, NULL, D3D11_SDK_VERSION, &scd, &gSwapChain, &gDevice, NULL, &gDeviceContext); // get the address of the back buffer ID3D11Texture2D* pBackBuffer = nullptr; gSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer); // use the back buffer address to create the render target gDevice->CreateRenderTargetView(pBackBuffer, NULL, &gBackbufferRTV); // set the render target as the back buffer CreateDepthStencilBuffer(); gDeviceContext->OMSetRenderTargets(1, &gBackbufferRTV, depthStencilView); //UAV for compute shader D3D11_UNORDERED_ACCESS_VIEW_DESC uavd; ZeroMemory(&uavd, sizeof(uavd)); uavd.Format = DXGI_FORMAT_R8G8B8A8_UNORM; uavd.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D; uavd.Texture2D.MipSlice = 1; gDevice->CreateUnorderedAccessView(pBackBuffer, &uavd, &gUAV); pBackBuffer->Release();  
      After I render the scene, I dispatch like this:
      gDeviceContext->OMSetRenderTargets(0, NULL, NULL); m_vShaders["cs1"]->Bind(); gDeviceContext->CSSetUnorderedAccessViews(0, 1, &gUAV, 0); gDeviceContext->Dispatch(32, 24, 0); //hard coded ID3D11UnorderedAccessView* nullview = { nullptr }; gDeviceContext->CSSetUnorderedAccessViews(0, 1, &nullview, 0); gDeviceContext->OMSetRenderTargets(1, &gBackbufferRTV, depthStencilView); gSwapChain->Present(0, 0); Worth noting is the scene is rendered as usual, but I dont get any results from the CS (simple gaussian blur)
      I'm sure it's something fairly basic I'm doing wrong, perhaps my understanding of render targets / views / what have you is just completely wrong and my approach just makes no sense.

      If someone with more experience could point me in the right direction I would really appreciate it!

      On a side note, I'd really like to learn more about this kind of stuff. I can really see the potential of the CS aswell as rendering to textures and using them for whatever in the engine so I would love it if you know some good resources I can read about this!

      Thank you <3
       
      P.S I excluded the .hlsl since I cant imagine that being the issue, but if you think you need it to help me just ask

      P:P:S. As you can see this is my first post however I do have another account, but I can't log in with it because gamedev.net just keeps asking me to accept terms and then logs me out when I do over and over
    • By noodleBowl
      I was wondering if anyone could explain the depth buffer and the depth stencil state comparison function to me as I'm a little confused
      So I have set up a depth stencil state where the DepthFunc is set to D3D11_COMPARISON_LESS, but what am I actually comparing here? What is actually written to the buffer, the pixel that should show up in the front?
      I have these 2 quad faces, a Red Face and a Blue Face. The Blue Face is further away from the Viewer with a Z index value of -100.0f. Where the Red Face is close to the Viewer with a Z index value of 0.0f.
      When DepthFunc is set to D3D11_COMPARISON_LESS the Red Face shows up in front of the Blue Face like it should based on the Z index values. BUT if I change the DepthFunc to D3D11_COMPARISON_LESS_EQUAL the Blue Face shows in front of the Red Face. Which does not make sense to me, I would think that when the function is set to D3D11_COMPARISON_LESS_EQUAL the Red Face would still show up in front of the Blue Face as the Z index for the Red Face is still closer to the viewer
      Am I thinking of this comparison function all wrong?
      Vertex data just in case
      //Vertex date that make up the 2 faces Vertex verts[] = { //Red face Vertex(Vector4(0.0f, 0.0f, 0.0f), Color(1.0f, 0.0f, 0.0f)), Vertex(Vector4(100.0f, 100.0f, 0.0f), Color(1.0f, 0.0f, 0.0f)), Vertex(Vector4(100.0f, 0.0f, 0.0f), Color(1.0f, 0.0f, 0.0f)), Vertex(Vector4(0.0f, 0.0f, 0.0f), Color(1.0f, 0.0f, 0.0f)), Vertex(Vector4(0.0f, 100.0f, 0.0f), Color(1.0f, 0.0f, 0.0f)), Vertex(Vector4(100.0f, 100.0f, 0.0f), Color(1.0f, 0.0f, 0.0f)), //Blue face Vertex(Vector4(0.0f, 0.0f, -100.0f), Color(0.0f, 0.0f, 1.0f)), Vertex(Vector4(100.0f, 100.0f, -100.0f), Color(0.0f, 0.0f, 1.0f)), Vertex(Vector4(100.0f, 0.0f, -100.0f), Color(0.0f, 0.0f, 1.0f)), Vertex(Vector4(0.0f, 0.0f, -100.0f), Color(0.0f, 0.0f, 1.0f)), Vertex(Vector4(0.0f, 100.0f, -100.0f), Color(0.0f, 0.0f, 1.0f)), Vertex(Vector4(100.0f, 100.0f, -100.0f), Color(0.0f, 0.0f, 1.0f)), };  
    • By Eck
      I just saw their courses were knocked down to $10 each and figured I'd share the info here. They have stuff for Unity, Unreal, drawing, business, etc. I haven't used their stuff before, but the previews I looked at seemed pretty good and there is a user review system as well.
      https://www.udemy.com/courses/search/?q=Unity&src=ukw
      - Eck
       
  • Popular Now