Вот пример, который использует vb.net и C ++ dll в visual studio 2017
Особенности:
- Универсальный проект Windows (UWP) в VB, использующий элемент управления XAML
SwapChainPanel.
- Вызывает стандартную Win32 DLL. DLL инициализирует
DirectX, создает поток и отображает SwapChainPanel из библиотеки DLL
код написан на C ++.
- Скомпилировано в Visual Studio 2017
В Visual Basic добавьте SwapChainPanel в MainPage.xaml
<SwapChainPanel x:Name="swapChainPanel1">
<TextBlock x:Name="txt1" Text="Hello from XAML!"
HorizontalAlignment="Right"
VerticalAlignment="Top"
FontSize="30" />
<Button Content="Button" HorizontalAlignment="Left" Height="30" Margin="812,484,0,0" VerticalAlignment="Top" Width="97" Click="Button_Click"/>
<Button Content="Button" HorizontalAlignment="Left" Height="79" Margin="851,561,0,0" VerticalAlignment="Top" Width="126" Click="Button_Click_1"/>
</SwapChainPanel>
В MainPage.xaml.vb
Imports System.Runtime.InteropServices ' Required for dll calling. Our C dll is "dhv.dll"
<DllImport("dhv.dll", CallingConvention:=CallingConvention.StdCall)>
Private Shared Function D3DInit(ByVal swapChainNative As IntPtr) As UInteger
End Function
<DllImport("dhv.dll", CallingConvention:=CallingConvention.StdCall)>
Private Shared Function D3DRender() As UInteger
End Function
Dim SwapChainNative As IntPtr
Private Sub Tst(ByRef s As SwapChainPanel) ' this is the Vb implementation of QueryInterface on SwapChainPanel cast as IUnknown. See the DirectX documentation
Dim inspectableIface As IntPtr
Dim uuid As New Guid("F92F19D2-3ADE-45A6-A20C-F6F1EA90554B") ' GUID of ISwapChainPanelNative decalred in <windows.ui.xaml.media.dxinterop.h>
inspectableIface = System.Runtime.InteropServices.Marshal.GetIUnknownForObject(s)
System.Runtime.InteropServices.Marshal.QueryInterface(inspectableIface, uuid, SwapChainNative)
End Sub
Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
Dim r As UInt32
Tst(Me.swapChainPanel1)
r = D3DInit(SwapChainNative)
Me.txt1.Text = r
End Sub
Private Sub Button_Click_1(sender As Object, e As RoutedEventArgs)
D3DRender()
End Sub
Создание стабильного проекта Win32 Dll. Это будет экспортировать две функции. Я использую файл .def для определения экспорта. Это очень хорошо работает с VB. Нет необходимости в других директивах, таких как extern "C" __declspec (dllexport) BOOL __stdcall D3DInit (). Убедитесь, что он вызывается компоновщиком i.e /DEF:".\dhv.def"
LIBRARY dhv
EXPORTS
D3DInit=D3DInit
D3DRender=D3DRender
Заголовочный файл Game.h (Этот код основан на http://www.directxtutorial.com. Код Microsoft раздут!
#pragma once
using namespace Microsoft::WRL;
using namespace DirectX;
class CGame
{
public:
ComPtr<ID3D11Device1> dev; // the device interface
ComPtr<ID3D11DeviceContext1> devcon; // the device context interface
ComPtr<IDXGISwapChain1> swapchain; // the swap chain interface
ComPtr<ID3D11RenderTargetView> rendertarget;
ComPtr<ID3D11Texture2D> Backbuffer;
UINT32 Initialize();
void Update();
UINT32 Render();
void InitGraphics();
private:
float ScreenColour;
UINT ScreenColourI;
UINT Width, Height;
UINT32 * TextureData;
};
и файл Game.cpp
#include "stdafx.h"
#include <wrl/client.h>
#include <d3d11_1.h>
#include <DirectXMath.h>
#include <windows.ui.xaml.media.dxinterop.h>
#include "Game.h"
DWORD WINAPI renderThread(LPVOID lpParameter);
CGame* pGame;
ComPtr<ISwapChainPanelNative> pSwapChainNative;
UINT32 __stdcall D3DInit(PULONG ptrSwapChainNative)
{
UINT r;
pGame = new CGame;
pSwapChainNative = reinterpret_cast<ISwapChainPanelNative*> (ptrSwapChainNative);
r = pGame->Initialize();
return r;
}
UINT32 __stdcall D3DRender(void)
{
CreateThread(NULL, NULL, renderThread, NULL, 0, NULL);
return 0;
}
DWORD WINAPI renderThread(LPVOID lpParameter)
{
for (int i = 0; i < 500; i++)
{
//pGame->Update();
pGame->Render();
}
return 1;
}
// this function initializes and prepares Direct3D for use
UINT32 CGame::Initialize()
{
HRESULT hr;
// Define temporary pointers to a device and a device context
ComPtr<ID3D11Device> dev11;
ComPtr<ID3D11DeviceContext> devcon11;
// Create the device and device context objects
D3D11CreateDevice(
nullptr,
D3D_DRIVER_TYPE_HARDWARE,
nullptr,
0,
nullptr,
0,
D3D11_SDK_VERSION,
&dev11,
nullptr,
&devcon11);
// Convert the pointers from the DirectX 11 versions to the DirectX 11.1 versions
dev11.As(&dev);
devcon11.As(&devcon);
// First, convert our ID3D11Device1 into an IDXGIDevice1
ComPtr<IDXGIDevice1> dxgiDevice;
dev.As(&dxgiDevice);
// Second, use the IDXGIDevice1 interface to get access to the adapter
ComPtr<IDXGIAdapter> dxgiAdapter;
dxgiDevice->GetAdapter(&dxgiAdapter);
// Third, use the IDXGIAdapter interface to get access to the factory
ComPtr<IDXGIFactory2> dxgiFactory;
dxgiAdapter->GetParent(__uuidof(IDXGIFactory2), &dxgiFactory);
/*
// set up the swap chain description
DXGI_SWAP_CHAIN_DESC1 scd = {0};
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // how the swap chain should be used
scd.BufferCount = 2; // a front buffer and a back buffer
scd.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // the most common swap chain format
scd.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // the recommended flip mode
scd.SampleDesc.Count = 1; // disable anti-aliasing
CoreWindow^ Window = CoreWindow::GetForCurrentThread(); // get the window pointer
hr = dxgiFactory->CreateSwapChainForCoreWindow(
dev.Get(), // address of the device
reinterpret_cast<IUnknown*>(Window), // address of the window
&scd, // address of the swap chain description
nullptr, // advanced
&swapchain);
*/
DXGI_SWAP_CHAIN_DESC1 scd = { 0 };
scd.Width = 1000; //BUG setting it arbitarily. Needs cleanup. by Ravi
scd.Height = 800;
scd.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // this is the most common swapchain format
scd.Stereo = false;
scd.SampleDesc.Count = 1; // don't use multi-sampling
scd.SampleDesc.Quality = 0;
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
scd.BufferCount = 2;
scd.Scaling = DXGI_SCALING_STRETCH;
scd.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // we recommend using this swap effect for all applications
scd.Flags = 0;
hr = dxgiFactory->CreateSwapChainForComposition(
dev.Get(),
&scd,
nullptr, // allow on any display
&swapchain);
if (FAILED(hr))
{
return 204;
}
pSwapChainNative->SetSwapChain(swapchain.Get());
// get a pointer directly to the back buffer
swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), &Backbuffer);
// create a render target pointing to the back buffer
dev->CreateRenderTargetView(Backbuffer.Get(), nullptr, &rendertarget);
// Width and Height
swapchain->GetDesc1(&scd);
Width = scd.Width;
Height = scd.Height;
TextureData = new UINT32[Width * Height];
// initialize graphics and the pipeline
InitGraphics();
return 0;
}
// this function performs updates to the state of the game
void CGame::Update()
{
}
// this function renders a single frame of 3D graphics
UINT32 CGame::Render()
{
UINT n, i;
UINT * psrc;
/*
// set our new render target object as the active render target
devcon->OMSetRenderTargets(1, rendertarget.GetAddressOf(), nullptr);
ScreenColour += 0.005f;
if (ScreenColour >0.9f)
ScreenColour = 0.0f;
// clear the back buffer to a deep blue
float color[4] = {ScreenColour, ScreenColour, ScreenColour, 1.0f};
devcon->ClearRenderTargetView(rendertarget.Get(), color);
*/
psrc = TextureData;
i = ScreenColourI & 255;
for (n=0; n<Width*Height; n++)
{
*psrc++ = (i<<16) | (i<<8) | i ;
i++;
i &= 255;
}
ScreenColourI += 1;
devcon->UpdateSubresource (Backbuffer.Get(), 0, NULL, TextureData, Width*4, 0);
// switch the back buffer and the front buffer
swapchain->Present(1, 0);
return 0;
}
// this function loads and initializes all graphics data
void CGame::InitGraphics()
{
ScreenColour = 0.0f;
ScreenColourI = 0;
}
И, наконец, не забудьте понравиться D3D11.lib
Итак, окно VB окрашивается из неуправляемой dll DirectX на частоте 60 Гц!
Ravi