5,695,118 members and growing! (14,146 online)
Email Password   helpLost your password?
Multimedia » Audio and Video » General     Intermediate

Using screensavers inside the Windows Media Player

By Justin Hallet

Wrapping a screensaver inside a WMP visualization plug-in.
VC8.0, C++Windows, Win2K, WinXP, Win2003, Vista, Visual Studio, MFC, Dev

Posted: 7 Jun 2006
Updated: 7 Jun 2006
Views: 27,327
Bookmarked: 27 times
Announcements
Loading...



Search    
Advanced Search
Sitemap
9 votes for this Article.
Popularity: 4.50 Rating: 4.71 out of 5
0 votes, 0.0%
1
0 votes, 0.0%
2
1 vote, 11.1%
3
0 votes, 0.0%
4
8 votes, 88.9%
5

Sample Image - SheepWMP.jpg

Introduction

A few days ago, I downloaded and installed the electricsheep screensaver. This is such a cool screensaver, I wanted to watch it while I worked, and I found the SheepWatcher.

So I started thinking: "that's cool, how did they do that, run the screen saver in a window?" Good old Microsoft had the anwser.

So being a Windows developer, I decided I could do better, a Windows Media Player plug-in to run ElectricSheep.scr. The first step was to get the WMP SDK:

It did not work with VS.NET 2005:

Test

OK, create a C++ project for a Windows Media Player Visualization Plug-in, we will call it SheepWMP. Actually, I wrote a quick test dialog application like so:

A small helper function to wrap CreateProcess:

static HANDLE LaunchProcess ( LPTSTR aProcessName, LPTSTR aArgs )
{
    STARTUPINFO lStartupInfo;            
    PROCESS_INFORMATION lProcessInfo;

    memset ( &lProcessInfo, 0, sizeof ( lProcessInfo ) );
    memset ( &lStartupInfo, 0, sizeof ( lStartupInfo ) );

    lStartupInfo.cb = sizeof ( lStartupInfo );
    lStartupInfo.dwFlags = STARTF_USESHOWWINDOW;
    lStartupInfo.wShowWindow = SW_SHOWNORMAL;

    // Create target process

    CreateProcess ( aProcessName, aArgs, NULL, NULL, FALSE, 0, 
                    NULL, NULL, & lStartupInfo, & lProcessInfo );

    WaitForInputIdle ( lProcessInfo.hProcess, INFINITE ) ;

    return lProcessInfo.hProcess ;
}
BOOL CSheepTestDlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    // Set the icon for this dialog.

    // The framework does this automatically

    //  when the application's main window is not a dialog

    SetIcon(m_hIcon, TRUE);   // Set big icon

    SetIcon(m_hIcon, FALSE);  // Set small icon


    TCHAR lCommand [ 1024 ] ;
    _stprintf_s ( lCommand, 1024, _T(" /p %u"), 
                  (DWORD) GetSafeHwnd () ) ;

    TCHAR lExe [ 1024 ] ;
    _stprintf_s ( lExe, 1024, 
       _T("c:\\windows\\system32\\electricsheep.scr") ) ;

    TRACE ( lCommand ) ;
    LaunchProcess ( lExe, lCommand ) ;
    return TRUE;  // return TRUE  unless you set the focus to a control

}

Code

Right, let's get to the Media Player plug-in. VS2005, with the WMPSDK, will create a basic visualization plug-in. The first steps are to remove all the rendering code and simply attach the screensaver to the desired HWND:

STDMETHODIMP CSheepWMP::RenderWindowed(TimedLevel *pLevels, 
                                       BOOL fRequiredRender )
{
....

    TCHAR lCommand [ 1024 ] ;
    _stprintf_s ( lCommand, 1024, _T(" /p %u"), 
                  (DWORD) m_hwndParent ) ;

    TCHAR lExe [ 1024 ] ;
    _stprintf_s ( lExe, 1024, 
                  _T("c:\\windows\\system32\\electricsheep.scr") ) ;

    TRACE ( lCommand ) ;
    LaunchProcess ( lExe, lCommand ) ;
....
}

But what happens when Windows Media Player changes size:

// Has the window changed dimensions

RECT lRect ;
GetClientRect ( gWnd, &lRect ) ;
if ( memcmp ( &gRect, &lRect, sizeof ( RECT ) ) != 0 )
{
    ATLTRACE ( DEFAULT_TRACE_PREFIX 
               _T("Window size changed...\n") ) ;
    memcpy ( &gRect, &lRect, sizeof ( RECT ) ) ;

    // Try to update the exinsing window

    HWND lWnd = FindWindowEx ( gWnd, NULL, 
                _T("WindowsScreenSaverClass"), NULL ) ;
    if ( lWnd ) 
    {
        ATLTRACE ( DEFAULT_TRACE_PREFIX 
                   _T("Moving screensaver window...\n") ) ;
        SetWindowPos ( lWnd, NULL, lRect . left, lRect . top, 
                       lRect . right - lRect . left, 
                       lRect . bottom - lRect . top, 
                       SWP_SHOWWINDOW ) ;
    }
}

So now, we have the basics working. If you examine my source, you will see that it locates all the Windows screensavers and can run them all inside the Window Media Player. It's done like so:

CAtlString lPath ;
SHGetFolderPath ( NULL, CSIDL_SYSTEM, NULL, 0, 
                  lPath . GetBufferSetLength ( MAX_PATH ) ) ;
lPath . ReleaseBuffer () ;

ATLTRACE ( DEFAULT_TRACE_PREFIX _T("Finding all scrs in %s\n"), lPath ) ;


CAtlString lSearch = lPath ;
PathAppend ( lSearch . GetBufferSetLength ( MAX_PATH ), DEFAULT_SCR_EXT ) ;
lSearch . ReleaseBuffer () ;

WIN32_FIND_DATA lFindFileData;
HANDLE lFind = FindFirstFile ( lSearch, &lFindFileData ) ;
if ( lFind != INVALID_HANDLE_VALUE )
{
    do
    {
        CAtlString lScr = lPath ;
        PathAppend ( lScr .GetBufferSetLength ( MAX_PATH ), 
                           lFindFileData . cFileName  ) ;
        lScr . ReleaseBuffer () ;
    
        ATLTRACE ( DEFAULT_TRACE_PREFIX _T("Adding scr, %s\n"), lScr ) ;

        m_Scrs . push_back ( lScr ) ;
    }
    while ( FindNextFile ( lFind, &lFindFileData ) ) ;

    FindClose ( lFind ) ;
}

Now, inside the Windows Media Player, we list all the screensavers using nice names. You have to get the names from the screensaver .scr files, which can be loaded like resource DLLs:

CAtlString CSheepWMP::GetScrName ( CAtlString aScr ) 
{
    // Initially get the filename and remove extension

    CAtlString lName = PathFindFileName ( aScr ) ;
    PathRemoveExtension ( lName . GetBufferSetLength ( MAX_PATH ) ) ;
    lName . ReleaseBuffer () ;

    // Load the DLL as a data file, and do not resolve any references

    ATLTRACE ( DEFAULT_TRACE_PREFIX _T("Loading library %s\n"), aScr ) ;
    HINSTANCE lInstance = LoadLibraryEx ( aScr, NULL, 
              DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE ) ;
    if ( lInstance )
    {
        // Examining all SCR, string 1 is the description

        // used by the display properties

        CAtlString lDesc ;
        LoadString ( lInstance, 1, 
                     lDesc.GetBufferSetLength(MAX_PATH), MAX_PATH ) ;
        lDesc . ReleaseBuffer () ;

        // Clean up

        FreeLibrary ( lInstance ) ;

        // If we have a valid description use it

        if ( lDesc . IsEmpty () == FALSE )
        {
            ATLTRACE ( DEFAULT_TRACE_PREFIX 
                       _T("Set scr name to description, %s\n"), lDesc ) ;
            lName = lDesc ;
        }
    }
    return lName ;
}

That's all!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Justin Hallet


Developing windows applications for over 10 years now starting on Win 3.1 with Object Oriented Pascal, progressed to C++ and OWL, in 1996 switch to MFC and never looked back.


Occupation: Web Developer
Location: United Kingdom United Kingdom

Other popular Audio and Video articles:

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Noise ToleranceSearch Search Messages 
 Layout  Per page   
 Msgs 1 to 3 of 3 (Total in Forum: 3) (Refresh)FirstPrevNext
QuestionHOW DO I GET THE PLUGIN TO INSTALLmemberZBow7:07 15 Oct '08  
QuestionChanging the Visualization in Media PlayermemberFadik9:32 26 Sep '06  
AnswerRe: Changing the Visualization in Media PlayermemberJustin Hallet22:57 26 Sep '06  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 7 Jun 2006
Editor: Smitha Vijayan
Copyright 2006 by Justin Hallet
Everything else Copyright © CodeProject, 1999-2008
Web09 | Advertise on the Code Project