2012-10-02 93 views
2

我在C#中開發了一個小型媒體播放器,現在我需要將它轉換爲C++。我的老師希望我們比較兩種方法,看看哪些方法實際上更好/更快。C#/ WPF項目中的類不在C++/CLI項目中工作

我有一個C#WPF項目,有幾個類在新的C++ CLI項目中使用時似乎不能正常運行。例如,我無法使用MediaPlayer類。 Visual Studio 2008找不到System.Windows.Media::MediaPlayer。以下是我從MSDN獲得的信息:http://msdn.microsoft.com/fr-fr/library/system.windows.media.mediaplayer.aspx#Y100

任何關於如何將C#WPF項目轉換爲C++ CLI項目的想法?我認爲這實際上很簡單,但由於某些原因,VS2008找不到我需要的大部分類。

+1

於C++。 NET或純粹的Win32 C++? – zerkms

+0

C++ .NET,VS2008,CLI。 – dnLL

+1

「看看實際上更好/更快。」 ---那麼代碼將99%相同,以及結果二進制。 PS:用於媒體播放器的「CLI」? – zerkms

回答

1

下應接近,但我可以保證,它不會太大的差別在速度方面,因爲它也託管代碼(我把它全部在頭文件):

using namespace System; 
using namespace System::Collections::Generic; 
using namespace System::Linq; 
using namespace System::Windows; 
using namespace System::Windows::Controls; 
using namespace System::Windows::Media; 
using namespace System::Windows::Media::Imaging; 
using namespace System::Windows::Threading; 
using namespace Microsoft::Win32; 

namespace VideoThumbnailer 
{ 
    /*---------------------------------------------------------------------------------* 
    * CLASSE WINDOW1 
    /*---------------------------------------------------------------------------------*/ 
    public ref class Window1 : Window 
    { 
     // Inheritable attached dependency property indicates whether processing is going on 
    public: 
     static bool GetProcessing(DependencyObject ^obj) 
     { 
      return safe_cast<bool>(obj->GetValue(ProcessingProperty)); 
     } 
     static void SetProcessing(DependencyObject ^obj, bool value) 
     { 
      obj->SetValue(ProcessingProperty, value); 
     } 
     static initonly DependencyProperty ^ProcessingProperty = DependencyProperty::RegisterAttached("Processing", bool::typeid, Window1::typeid, gcnew FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions::Inherits)); 

     // Dependency property indicates the file name of the current media 
     property String ^FileName 
     { 
      String ^get() 
      { 
       return safe_cast<String^>(GetValue(FileNameProperty)); 
      } 
      void set(String ^value) 
      { 
       SetValue(FileNameProperty, value); 
      } 
     } 
     static initonly DependencyProperty ^FileNameProperty = DependencyProperty::Register("FileName", String::typeid, Window1::typeid); 

     // Member variables 
    private: 
     MediaPlayer ^_mediaPlayer; 
     Queue<TimeSpan> ^_positionsToThumbnail; 
     //private TimeSpan _positionsToThumbnail = new TimeSpan(); 
     DispatcherTimer ^_watchdogTimer; 
     array<Byte> ^framePixels; 
     array<Byte> ^previousFramePixels; 
     float m_iContrast; 
     int m_iBrightness; 

    public: 
     Window1() 
     { 
      // Initialize window and hook up to events of interest 
      InitializeInstanceFields(); 
      InitializeComponent(); 
      _mediaPlayer->MediaOpened += gcnew EventHandler(this, &Window1::HandleMediaPlayerMediaOpened); 
      _mediaPlayer->Changed += gcnew EventHandler(this, &Window1::HandleMediaPlayerChanged); 
      _watchdogTimer->Interval = TimeSpan::FromSeconds(1); 
      _watchdogTimer->Tick += gcnew EventHandler(this, &Window1::HandleWatchdogTimerTick); 
     } 


#pragma region Utils 
    private: 
     void SeekToNextThumbnailPosition() 
     { 
      // If more frames remain to capture... 
      if (0 < _positionsToThumbnail->Count) 
      { 
       // Seek to next position and start watchdog timer 
       _mediaPlayer->Position = _positionsToThumbnail->Dequeue(); 
       _watchdogTimer->Start(); 
      } 
      else 
      { 
       // Done; close media file and stop processing 
       _mediaPlayer->Close(); 
       framePixels = nullptr; 
       previousFramePixels = nullptr; 
       SetProcessing(this, false); 
      } 
     } 

     void CaptureCurrentFrame(bool forceCapture) 
     { 
      // Capture the current frame as an ImageSource 
      WriteableBitmap ^imageSource = RenderBitmapAndCapturePixels(framePixels); 

      // If captured pixels are different than the previous frame... 
      if (forceCapture || !framePixels->SequenceEqual(previousFramePixels)) 
      { 
       // Stop the watchdog timer 
       _watchdogTimer->Stop(); 

       // Add an Image for the Thumbnail 
       ThumbnailPanel::Children->Clear(); // en effaçant a chaque fois, on réécrit au même endroit 
       ThumbnailPanel::Children->Add(gcnew Image {Source = imageSource, ToolTip = _mediaPlayer->Position, MaxWidth = _mediaPlayer->NaturalVideoWidth, MaxHeight = _mediaPlayer->NaturalVideoHeight, Margin = Thickness(0)}); // distance entre chaque image 

       // Swap the pixel buffers (moves current to previous and avoids allocating a new buffer for current) 
       array<Byte> ^tempPixels = framePixels; 
       framePixels = previousFramePixels; 
       previousFramePixels = tempPixels; 

       // Seek to the next thumbnail position 
       SeekToNextThumbnailPosition(); 
      } 
     } 

     WriteableBitmap ^RenderBitmapAndCapturePixels(array<Byte> ^pixels) 
     { 
      // Render the current frame into a bitmap 
      DrawingVisual ^drawingVisual = gcnew DrawingVisual(); 
      RenderTargetBitmap ^renderTargetBitmap = gcnew RenderTargetBitmap(_mediaPlayer->NaturalVideoWidth, _mediaPlayer->NaturalVideoHeight, 96, 96, PixelFormats::Default); 
      Rect videoRect = Rect(0, 0, _mediaPlayer->NaturalVideoWidth, _mediaPlayer->NaturalVideoHeight); 

//C# TO C++ CONVERTER NOTE: The following 'using' block is replaced by its C++ equivalent: 
//   using (var drawingContext = drawingVisual.RenderOpen()) 
      System::Windows::Media::DrawingContext ^drawingContext = drawingVisual->RenderOpen(); 
      try 
      { 
       drawingContext->DrawVideo(_mediaPlayer, videoRect); 
      } 
      finally 
      { 
       delete drawingContext; 
      } 
      renderTargetBitmap->Render(drawingVisual); 

      // Copy the pixels to the specified location 
      renderTargetBitmap->CopyPixels(pixels, _mediaPlayer->NaturalVideoWidth * 4, 0); 

      // Effectuer un traitement 
      TraiterImage(pixels); 


      // Utiliser un "WritableBitMap" 
      WriteableBitmap ^wrBitMap = gcnew WriteableBitmap(renderTargetBitmap); 
      Int32Rect wrRect = Int32Rect(); 
      wrRect.X = safe_cast<int>(videoRect.X); 
      wrRect.Y = safe_cast<int>(videoRect.Y); 
      wrRect.Width = safe_cast<int>(videoRect.Width); 
      wrRect.Height = safe_cast<int>(videoRect.Height); 

      wrBitMap->WritePixels(wrRect, pixels, _mediaPlayer->NaturalVideoWidth * 4, 0); 

      // Return the bitmap 
      return wrBitMap; 
     } 

     void TraiterImage(array<Byte> ^pixels) 
     { 
      try 
      { 
       for (int i = 0; i < pixels->Length; i++) 
       { 
        double tempPixel = pixels[i]; 

        tempPixel = (pixels[i] + m_iBrightness) * m_iContrast; 

        if (tempPixel < 0) 
         tempPixel = 0; 
        else if (tempPixel > 255) 
         tempPixel = 255; 

        pixels[i] = Convert::ToByte(tempPixel); 
       } 
      } 
      catch (Exception ^e) 
      { 
       Console::WriteLine("Une exception c'est produite : " + e->ToString()); 
      } 
     } 
#pragma endregion 
#pragma region Events 
     void but_brightnessDown_Click(Object ^sender, RoutedEventArgs ^e) 
     { 
      if (m_iBrightness > -255) 
       m_iBrightness -= 5; 

      lb_brightnessValue->Content = m_iBrightness; 
     } 

     void but_brightnessUp_Click(Object ^sender, RoutedEventArgs ^e) 
     { 
      if (m_iBrightness < 255) 
       m_iBrightness += 5; 

      lb_brightnessValue->Content = m_iBrightness; 
     } 

     void but_constrastDown_Click(Object ^sender, RoutedEventArgs ^e) 
     { 
      if (m_iContrast > 0.5) 
       m_iContrast -= 0.5F; 

      lb_contrastValue->Content = m_iContrast; 
     } 

     void but_contrastUp_Click(Object ^sender, RoutedEventArgs ^e) 
     { 
      if (m_iContrast < 2) 
       m_iContrast += 0.5F; 

      lb_contrastValue->Content = m_iContrast; 
     } 

#pragma endregion 
#pragma region handle 
     void HandleWatchdogTimerTick(Object ^sender, EventArgs ^e) 
     { 
      // Stop the watchdog timer 
      _watchdogTimer->Stop(); 

      // Capture the current frame (even if it's not different than the previous) 
      CaptureCurrentFrame(true); 
     } 

     void HandleOpenFileButtonClick(Object ^sender, RoutedEventArgs ^e) 
     { 
      // Display open file dialog 
      OpenFileDialog ^openFileDialog = gcnew OpenFileDialog {CheckFileExists = true, Filter = "Video Files (*.wmv;*.dvr-ms;*.mpeg;*.mpg;*.avi)|*.wmv;*.dvr-ms;*.mpeg;*.mpg;*.avi|All Files (*)|*"}; 

      // Show dialog 
      System::Nullable<System::Boolean> result = openFileDialog->ShowDialog(); 

      // If a file was chosen... 
      if (result.HasValue && result.Value) 
      { 
       // Reset state 
       System::String ^fileName = openFileDialog->FileName; 
       SetProcessing(this, true); 
       ThumbnailPanel::Children->Clear(); 
       FileName = fileName; 

       // Open media file 
       _mediaPlayer->ScrubbingEnabled = true; 
       _mediaPlayer->Open(gcnew Uri(fileName)); 
      } 
     } 

     void HandleMediaPlayerMediaOpened(Object ^sender, EventArgs ^e) 
     { 
      // Get details about opened file 
      //var numberFramesToThumbnail = (ThumbnailPanel.Columns * ThumbnailPanel.Rows); 
      System::Double totalMilliseconds = _mediaPlayer->NaturalDuration.TimeSpan::TotalMilliseconds; 
//C# TO C++ CONVERTER TODO TASK: There is no equivalent to implicit typing in C++ unless the C++11 inferred typing option is selected: 
      var numberFramesToThumbnail = 1 * totalMilliseconds/67; // le vidéo sera joué à 8 frame par seconde 
      framePixels = gcnew array<Byte>(_mediaPlayer->NaturalVideoWidth * _mediaPlayer->NaturalVideoHeight * 4); 
      previousFramePixels = gcnew array<Byte>(framePixels->Length); 

      // Enqueue a position for each frame (at the center of each of the N segments) 
      for (int i = 0; i < numberFramesToThumbnail; i++) 
      { 
       _positionsToThumbnail->Enqueue(TimeSpan::FromMilliseconds((((2 * i) + 1) * totalMilliseconds)/(2 * numberFramesToThumbnail))); 
       //_positionsToThumbnail = (TimeSpan.FromMilliseconds((((2 * i) + 1) * totalMilliseconds)/(2 * numberFramesToThumbnail))); 
      } 

      // Capture the first frame as a baseline 
      RenderBitmapAndCapturePixels(previousFramePixels); 

      // Seek to the first thumbnail position 
      SeekToNextThumbnailPosition(); 
     } 

     void HandleMediaPlayerChanged(Object ^sender, EventArgs ^e) 
     { 
      // If still processing the file (i.e., not done)... 
      if (GetProcessing(this)) 
      { 
       // Capture the current frame 
       CaptureCurrentFrame(false); 
      } 
     } 

    private: 
     void InitializeInstanceFields() 
     { 
      _mediaPlayer = gcnew MediaPlayer(); 
      _positionsToThumbnail = gcnew Queue<TimeSpan>(); 
      _watchdogTimer = gcnew DispatcherTimer(); 
      m_iContrast = 1; 
     } 
    }; 
#pragma endregion 
} 
相關問題