2015-01-10 10 views
12

पर डायरेक्ट 2 डी प्रतिपादन को रीडायरेक्ट करें Direct2D के माध्यम से मैं Visual C++ में एक ड्राइंग एप्लिकेशन विकसित कर रहा हूं। मैं एक डेमो आवेदन जहां है:एक WPF नियंत्रण

// create the ID2D1Factory 
D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &m_pDirect2dFactory); 

// create the main window 
HWND m_hwnd = CreateWindow(...); 

// set the render target of type ID2D1HwndRenderTarget 
m_pDirect2dFactory->CreateHwndRenderTarget(
      D2D1::RenderTargetProperties(), 
      D2D1::HwndRenderTargetProperties(m_hwnd, size), 
      &m_pRenderTarget 
      ); 

और जब मैं WM_PAINT संदेश प्राप्त होता है मैं अपने आकार आकर्षित।

अब मैं एक WPF नियंत्रण (Panel का एक प्रकार) है कि मेरे लक्ष्य नई प्रस्तुत करना का प्रतिनिधित्व करता है विकसित करने की आवश्यकता, (इसलिए यह मुख्य विंडो m_hwnd जगह लेंगे) ताकि मैं मुख्य के साथ एक नया (सी #) WPF प्रोजेक्ट बना सकते हैं खिड़की जो बच्चों के रूप में मेरे कस्टम पैनल है, जबकि प्रतिपादन हिस्सा देशी सी ++/सीएलआई डीएलएल परियोजना में रहता है।

मैं यह कैसे कर सकता हूं? मुझे अपने नए प्रस्तुत लक्ष्य के रूप में क्या सेट करना है?

मैं अपने WPF खिड़की के हैंडल का उपयोग करने के बारे में सोचा:

IntPtr windowHandle = new WindowInteropHelper(MyMainWindow).Handle; 

लेकिन मैं अपने पैनल पर और मेरी खिड़की पर नहीं आकर्षित करने के लिए की जरूरत है।

कृपया ध्यान दें कि मैं प्रतिपादन भाग के लिए किसी भी WPF वर्गों का उपयोग नहीं करना चाहते हैं (Shapes, DrawingVisuals ...)

+2

मैं कैसे एक WPF आवेदन में Direct2D की मेजबानी करने का एक उदाहरण के लिए खोज करेंगे। अच्छा सवाल। –

+0

क्या आपके पास डीएलएल तक पहुंच है? क्या आप अपना कोड बदल सकते हैं? मेरा मानना ​​है कि CreateWindow() को कॉल करने में समस्या – Domysee

+0

डब्ल्यूपीएफ डब्ल्यूआईसी के बहुत करीब है, इसलिए मैं इसके बजाय d2d1.CreateWicBitmapRenderTarget का उपयोग अपने IWicBitmap के साथ करूँगा। इस IWicBitmap का उपयोग WPF के अमूर्त बिटमैप स्रोत से प्राप्त कक्षा में किया जा सकता है (जैसे इंटरऑप बिटमैप की तरह, लेकिन स्वयं की कक्षा के साथ क्योंकि डब्ल्यूपीएफ अपने डब्ल्यूआईसी बिटमैप्स का पर्दाफाश नहीं करता है ...)। यह बिटमैप स्रोत अब पैनल का बच्चा हो सकता है। यदि आपके पास काम करने के लिए नमूना ऐप है, तो हम इसे और विकसित कर सकते हैं। –

उत्तर

3

आप एक वर्ग है कि आपके Win32 विंडो m_hwnd होस्ट करता है को लागू करने की है। इस वर्ग को HwndHost से विरासत मिली है।

इसके अलावा, आप HwndHost.BuildWindowCore और HwndHost.DestroyWindowCore तरीकों को ओवरराइड करने के लिए है:

HandleRef BuildWindowCore(HandleRef hwndParent) 
{ 
    HWND parent = reinterpret_cast<HWND>(hwndParent.Handle.ToPointer()); 

    // here create your Window and set in the CreateWindow function 
    // its parent by passing the parent variable defined above 
    m_hwnd = CreateWindow(..., 
         parent, 
         ...); 

    return HandleRef(this, IntPtr(m_hwnd)); 
} 


void DestroyWindowCore(HandleRef hwnd) 
{ 
    DestroyWindow(m_hwnd); // hwnd.Handle 
} 

इस ट्यूटोरियल का पालन करें: Walkthrough: Hosting a Win32 Control in WPF

0

यह शायद WinForms के साथ संभव होगा, लेकिन WPF के साथ नहीं। यहाँ एक प्रलेखन के बारे में बात कैसे WPF HWNDs का उपयोग करता है:

WPF कैसे उपयोग करता है Hwnds

WPF "HWND इंटरॉप" के सबसे बनाने के लिए, आप को समझने के लिए WPF HWNDs का उपयोग करता है की जरूरत है। किसी भी एचडब्ल्यूएनडी के लिए, आप डायरेक्टएक्स प्रतिपादन या जीडीआई/जीडीआई + प्रतिपादन के साथ डब्ल्यूपीएफ प्रतिपादन मिश्रण नहीं कर सकते हैं। इसमें कई प्रभाव हैं। मुख्य रूप से, इन प्रतिपादन मॉडल को मिश्रण करने के लिए, आपको एक इंटरऑपरेक्शन समाधान बनाना होगा, और प्रत्येक प्रतिपादन मॉडल के लिए इंटरैपमेंट के नामित सेगमेंट का उपयोग करना होगा। इसके अलावा, प्रतिपादन व्यवहार आपके इंटरऑपरेक्शन समाधान को पूरा करने के लिए "एयरस्पेस" प्रतिबंध बनाता है। "एयर स्पेस" अवधारणा विषय प्रौद्योगिकी क्षेत्र अवलोकन में अधिक विस्तार से समझाया गया है। स्क्रीन पर सभी WPF तत्वों को अंततः एक HWND द्वारा समर्थित किया जाता है। जब आप एक WPF विंडो बनाते हैं, तो WPF एक शीर्ष-स्तरीय HWND बनाता है, और विंडो और उसकी WPF सामग्री को HWND के अंदर रखने के लिए HwndSource का उपयोग करता है। एप्लिकेशन में आपकी शेष WPF सामग्री एकवचन एचडब्ल्यूएनडी साझा करती है। मेनू, कॉम्बो बॉक्स ड्रॉप डाउन और अन्य पॉप-अप अपवाद है। ये तत्व अपनी स्वयं की शीर्ष-स्तरीय विंडो बनाते हैं, यही कारण है कि एक WPF मेनू संभावित रूप से विंडो HWND के किनारे से आगे जा सकता है जिसमें यह शामिल है। जब आप WPF के अंदर एक HWND डालने के लिए HwndHost का उपयोग करते हैं, तो WPF WP32 विंडो HWND से संबंधित नए बच्चे HWND को स्थिति देने के लिए Win32 कैसे सूचित करता है। एचडब्ल्यूएनडी के लिए संबंधित अवधारणा प्रत्येक एचडब्ल्यूएनडी के भीतर और उसके बीच पारदर्शिता है। इस विषय प्रौद्योगिकी क्षेत्र अवलोकन में भी चर्चा की गई है।

से https://msdn.microsoft.com/en-us/library/ms742522%28v=vs.110%29.aspx

मैं एक तरह से अध्ययन करने के लिए आप की सिफारिश करेंगे कॉपी किए गए अपने क्षेत्र प्रस्तुत करना का ट्रैक रखने के लिए और शायद यह के सामने एक "घृणित" चाइल्ड विंडो पैदा करते हैं। अन्य अनुसंधान आप शायद कर सकते हैं कोशिश करते हैं और पता लगाने के लिए/WPF ग्राफिक्स बफ़र और संकेत दिए गए हैं और कुछ उन्नत स्मृति प्रोग्रामिंग का उपयोग कर इसे सीधे अपने गाया दृश्य इंजेक्षन मिलता है।

+0

विंडोज फॉर्म का उपयोग करके यह कैसे संभव होगा? – Nick

+0

विंडोज़ में प्रत्येक नियंत्रण में सी/सी ++ win32 एचडब्ल्यूएनडी प्रारूप में एक हैंडल होता है, आप इसे कंट्रोल। हैंडल प्रॉपर्टी को कॉल करके प्राप्त कर सकते हैं, यह एक इंटिप्ट देता है, मुझे विश्वास है कि आप इसे एचडब्ल्यूएनडी में डाल सकते हैं। संदर्भ: https://msdn.microsoft.com/library/system.windows.forms.control.handle%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396 – Felype

2

मैं WPF 4.5 अनलेश अध्याय 1 9 पर आधारित प्रश्न का उत्तर देने का प्रयास करूंगा। यदि आप इसे देखना चाहते हैं, तो आप उपधारा में सभी जानकारी पा सकते हैं "WPF सामग्री के साथ मिक्सिंग डायरेक्टएक्स सामग्री "।

आपका सी ++ DLL होना चाहिए 3 उजागर तरीकों(), सफाई() प्रारंभ करें और रेंडर()।

xmlns:interop="clr-namespace:System.Windows.Interop;assembly=PresentationCore" 
<Button.Background> 
    <ImageBrush> 
     <ImageBrush.ImageSource> 
      <interop:D3DImage x:Name="d3dImage" /> 
     </ImageBrush.ImageSource> 
    </ImageBrush> 
</Button.Background> 

मैं निर्धारित किया है:

extern "C" __declspec(dllexport) IDirect3DSurface9* WINAPI Initialize(HWND hwnd, int width, int height) 
{ 
    // Initialize Direct3D 
    if(SUCCEEDED(InitD3D(hwnd))) 
    { 
     // Create the scene geometry 
     if(SUCCEEDED(InitGeometry())) 
     { 
      if (FAILED(g_pd3dDevice->CreateRenderTarget(width, height, 
       D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, 
       true, // lockable (true for compatibility with Windows XP. False is preferred for Windows Vista or later) 
       &g_pd3dSurface, NULL))) 
      { 
       MessageBox(NULL, L"NULL!", L"Missing File", 0); 
       return NULL; 
      } 
      g_pd3dDevice->SetRenderTarget(0, g_pd3dSurface); 
     } 
    } 
    return g_pd3dSurface; 
} 


HRESULT InitD3D(HWND hWnd) 
{ 
    // For Windows Vista or later, this would be better if it used Direct3DCreate9Ex: 
    if(NULL == (g_pD3D = Direct3DCreate9(D3D_SDK_VERSION))) 
     return E_FAIL; 

    // Set up the structure used to create the D3DDevice. Since we are now 
    // using more complex geometry, we will create a device with a zbuffer. 
    D3DPRESENT_PARAMETERS d3dpp; 
    ZeroMemory(&d3dpp, sizeof(d3dpp)); 
    d3dpp.Windowed = TRUE; 
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; 
    d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; 
    d3dpp.EnableAutoDepthStencil = TRUE; 
    d3dpp.AutoDepthStencilFormat = D3DFMT_D16; 

    // Create the D3DDevice 
    if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, 
             D3DCREATE_SOFTWARE_VERTEXPROCESSING, 
             &d3dpp, &g_pd3dDevice))) 
    { 
     return E_FAIL; 
    } 

    // Turn on the zbuffer 
    g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, TRUE); 

    // Turn on ambient lighting 
    g_pd3dDevice->SetRenderState(D3DRS_AMBIENT, 0xffffffff); 

    return S_OK; 
} 

XAML कोड पर चलते हैं: दिलचस्प तरीकों Initialize() और InitD3D() है, जो Initialize() द्वारा कहा जाता है एक छवि ब्रश का उपयोग करके, यहां एक बटन की पृष्ठभूमि के रूप में। मेरा मानना ​​है कि इसे पृष्ठभूमि के रूप में जोड़ना डायरेक्टएक्स सामग्री को प्रदर्शित करने का एक अच्छा तरीका है। हालांकि, आप जिस तरह से चाहें छवि का उपयोग कर सकते हैं।

प्रारंभ करने के लिए प्रतिपादन वर्तमान विंडो के लिए एक संभाल के अधिग्रहण और इसके साथ DLL की विधि Initialize() फोन:

private void initialize() 
{ 
    IntPtr surface = DLL.Initialize(new WindowInteropHelper(this).Handle, 
      (int)button.ActualWidth, (int)button.ActualHeight); 

    if (surface != IntPtr.Zero) 
    { 
     d3dImage.Lock(); 
     d3dImage.SetBackBuffer(D3DResourceType.IDirect3DSurface9, surface); 
     d3dImage.Unlock(); 

     CompositionTarget.Rendering += CompositionTarget_Rendering; 
    } 
} 

CompositionTarget.Rendering घटना निकाल दिया जाता है बस से पहले यूआई प्रदान की गई है। तुम वहाँ में अपने DirectX सामग्री प्रस्तुत करना चाहिए:

private void CompositionTarget_Rendering(object sender, EventArgs e) 
{ 
    if (d3dImage.IsFrontBufferAvailable) 
    { 
     d3dImage.Lock(); 
     DLL.Render(); 
     // Invalidate the whole area: 
     d3dImage.AddDirtyRect(new Int32Rect(0, 0, d3dImage.PixelWidth, d3dImage.PixelHeight)); 
     d3dImage.Unlock(); 
    } 
} 

वह मूल रूप से यह था, मुझे आशा है कि यह मदद करता है। अब बस कुछ ही महत्वपूर्ण sidenotes:

  • हमेशा की तरह, अपनी छवि को ताला कि WPF फ्रेम आंशिक रूप से
  • न कॉल डायरेक्ट 3 डी उपकरण पर मौजूद ड्रॉ से बचने के लिए। डब्ल्यूपीएफ आपके द्वारा बैकबफर प्रस्तुत करता है, जिस सतह पर आप d3dImage.SetBackBuffer() पर जाते हैं।
  • घटना IsFrontBufferAvailableChanged क्योंकि कभी-कभी frontbuffer अनुपलब्ध (उदाहरण के लिए, जब उपयोगकर्ता लॉक स्क्रीन में प्रवेश करती है) नहीं बन सकता संभाला जाना चाहिए। आपको बफर उपलब्धता के आधार पर संसाधनों को मुक्त या अधिग्रहित करना चाहिए।

    private void d3dImage_IsFrontBufferAvailableChanged(object sender, DependencyPropertyChangedEventArgs e) 
    { 
        if (d3dImage.IsFrontBufferAvailable) 
        { 
         initialize(); 
        } 
        else 
        { 
         // Cleanup: 
         CompositionTarget.Rendering -= CompositionTarget_Rendering; 
         DLL.Cleanup(); 
        } 
    } 
    
+0

मैं डायरेक्ट 3 डी का उपयोग नहीं कर सकता, मुझे इसकी आवश्यकता है Direct2D का उपयोग करें। – Nick

+1

afaik D3DImage Direct2D सामग्री को भी होस्ट कर सकता है। – Domysee

+1

@ निक डायरेक्ट 2 डी एक लाइब्रेरी है जो डायरेक्ट 3 डी का सबसेट लक्षित करती है। https://msdn.microsoft.com/en-us/library/windows/desktop/dd370966(v=vs.85).aspx – Aron

-2

https://github.com/SonyWWS/ATF/ मदद कर सकता है

यह एक Direct2D दृश्य के साथ एक स्तर संपादक शामिल

+2

यह प्रश्न का उत्तर कैसे देता है? –

संबंधित मुद्दे