2008-11-11 7 views
3

Ce code fonctionne dans une application Windows Forms (il affiche l'aperçu) mais pas dans une application WPF.Comment prévisualiser une session Windows Media Encoder dans WPF?

WMEncoder _encoder; 
WMEncDataView _preview; 
_encoder = new WMEncoder(); 

IWMEncSourceGroupCollection SrcGrpColl = _encoder.SourceGroupCollection; 
IWMEncSourceGroup2 sourceGroup = (IWMEncSourceGroup2)SrcGrpColl.Add("SG_1"); 
IWMEncVideoSource2 videoDevice = (IWMEncVideoSource2)sourceGroup.AddSource(WMENC_SOURCE_TYPE.WMENC_VIDEO); 
videoDevice.SetInput("Default_Video_Device", "Device", ""); 
IWMEncAudioSource audioDevice = (IWMEncAudioSource)sourceGroup.AddSource(WMENC_SOURCE_TYPE.WMENC_AUDIO); 
audioDevice.SetInput("Default_Audio_Device", "Device", ""); 

IWMEncProfile2 profile = new WMEncProfile2(); 
profile.LoadFromFile("Recording.prx"); 
sourceGroup.set_Profile(profile); 

_encoder.PrepareToEncode(true); 

_preview = new WMEncDataView(); 
int lpreviewStream = videoDevice.PreviewCollection.Add(_preview); 

_encoder.Start(); 

_preview.SetViewProperties(lpreviewStream, (int)windowsFormsHost1.Handle); 
_preview.StartView(lpreviewStream); 

J'ai essayé d'utiliser le contrôle WindowsFormsHost pour obtenir une poignée de passer (comme indiqué dans l'échantillon), mais toujours pas de chance.

Répondre

3

J'ai récemment fait quelque chose de similaire pour intégrer un composant vidéo DirectShow existant avec une nouvelle interface utilisateur WPF. Il y a plusieurs façons de le faire, mais le plus simple est probablement de dériver une nouvelle classe de HwndHost. Vous devez simplement remplacer quelques méthodes, donner le handle de la fenêtre à votre flux de prévisualisation et tout devrait fonctionner. en fonction de vos besoins, vous devrez peut-être gérer quelques messages Windows dans votre WndProc pour gérer les changements d'affichage et redessiner lorsque la vidéo ne joue pas.

using System; 
using System.Runtime.InteropServices; 
using System.Windows; 
using System.Windows.Interop; 

namespace SOQuestion 
{ 
    public class VideoHost : HwndHost 
    { 
     protected override HandleRef BuildWindowCore(HandleRef hwndParent) 
     { 
      IntPtr hwndHost = IntPtr.Zero; 
      int hostHeight = (int) this.ActualHeight; 
      int hostWidth = (int) this.ActualWidth; 

      hwndHost = CreateWindowEx(0, "static", "", 
       WS_CHILD | WS_VISIBLE, 
       0, 0, 
       hostHeight, hostWidth, 
       hwndParent.Handle, 
       (IntPtr)HOST_ID, 
       IntPtr.Zero, 
       0); 

      return new HandleRef(this, hwndHost); 
     } 

     protected override void DestroyWindowCore(HandleRef hwnd) 
     { 
      DestroyWindow(hwnd.Handle); 
     } 

     protected override void OnWindowPositionChanged(Rect rcBoundingBox) 
     { 
      base.OnWindowPositionChanged(rcBoundingBox); 

      _preview.SetViewProperties(lpreviewStream, (int)this.Handle); 
     } 

     protected override IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) 
     { 
      // Handle a couple of windows messages if required - see MSDN for details 

      return base.WndProc(hwnd, msg, wParam, lParam, ref handled); 
     } 

     [DllImport("user32.dll", EntryPoint = "CreateWindowEx", CharSet = CharSet.Auto)] 
     internal static extern IntPtr CreateWindowEx(int dwExStyle, 
     string lpszClassName, 
     string lpszWindowName, 
     int style, 
     int x, int y, 
     int width, int height, 
     IntPtr hwndParent, 
     IntPtr hMenu, 
     IntPtr hInst, 
     [MarshalAs(UnmanagedType.AsAny)] object pvParam); 

     [DllImport("user32.dll", EntryPoint = "DestroyWindow", CharSet = CharSet.Auto)] 
     internal static extern bool DestroyWindow(IntPtr hwnd); 

     internal const int WS_CHILD = 0x40000000; 
     internal const int WS_VISIBLE = 0x10000000; 
     internal const int HOST_ID = 0x00000002; 
    } 
} 
+0

Cela fonctionne très bien! Impossible d'accéder à la variable _preview à partir du contrôle. Connaissez-vous un moyen de permettre de redimensionner l'aperçu lorsque le contrôle change de taille? – loraderon

+0

C'est exactement la raison pour laquelle mon exemple réinitialise le handle chaque fois que la position ou la taille de la fenêtre change, ce qui provoque la réinitialisation du rendu de DirectShow. Que se passe-t-il si vous appelez successivement StopView et StartView lorsque vous répondez au dimensionnement du contrôle? –

+0

Cela ne fonctionne pas même lorsque vous appelez StopView, SetViewProperties et StartView dans OnWindowPositionChanged ou un bouton séparé. Je dois démarrer/arrêter l'encodage (peut-être des problèmes avec l'encodeur Windows Media) – loraderon

Questions connexes