在 Windows Media Player 中使用屏幕保护程序






4.94/5 (12投票s)
将屏幕保护程序封装到 WMP 可视化插件中。
引言
几天前,我下载并安装了 电羊屏幕保护程序。这个屏幕保护程序太酷了,我想在工作时观看它,然后我找到了 SheepWatcher。
所以我开始思考:“这很酷,他们是怎么做到的,在窗口中运行屏幕保护程序?” 微软提供了答案 微软的解答。
作为一名 Windows 开发者,我决定做得更好,创建一个 Windows Media Player 插件来运行 ElectricSheep.scr。第一步是获取 WMP SDK
它无法在 VS.NET 2005 上运行
测试
好的,创建一个用于 Windows Media Player 可视化插件的 C++ 项目,我们将其命名为 SheepWMP。实际上,我编写了一个快速的测试对话框应用程序,如下所示
一个小的辅助函数,用于封装 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
}
代码
好了,让我们开始编写媒体播放器插件。使用 WMPSDK 的 VS2005 将创建一个基本的可视化插件。第一步是删除所有渲染代码,并简单地将屏幕保护程序附加到所需的 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 ) ;
....
}
但是当 Windows Media Player 改变大小时会发生什么?
// 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 ) ;
}
}
现在,我们已经完成了基本的工作。如果你检查我的源代码,你将会看到它会定位所有 Windows 屏幕保护程序,并且可以在 Window Media Player 中运行它们。它的实现方式如下
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 ) ;
}
现在,在 Windows Media Player 中,我们使用友好的名称列出所有屏幕保护程序。你必须从屏幕保护程序 .scr 文件中获取名称,这些文件可以像资源 DLL 一样加载
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 ;
}
就是这样!
历史
- 2011 年 7 月 15 日:更新了 Electric Sheep 的源代码。还包括 C# .NET 实现和 Microsoft Windows 安装脚本。