353 lines
8.3 KiB
C++
353 lines
8.3 KiB
C++
//------------------------------------------------------------------------------
|
|
// File: persist.cpp
|
|
//
|
|
// Desc: DirectShow sample code
|
|
// - State persistence helper functions
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//------------------------------------------------------------------------------
|
|
|
|
#include "project.h"
|
|
|
|
|
|
// Global data
|
|
RECENTFILES aRecentFiles[MAX_RECENT_FILES]={0};
|
|
int nRecentFiles=0;
|
|
|
|
// Global static data
|
|
static TCHAR cszWindow[] = TEXT("Window\0");
|
|
static TCHAR cszAppKey[] = TEXT("Software\\Microsoft\\Multimedia Tools\\VMRPlayer9\0");
|
|
|
|
|
|
|
|
#ifndef CheckPointer
|
|
#define CheckPointer(x, hr) if (x == NULL) { return hr; }
|
|
#endif
|
|
|
|
// Constants
|
|
const int CX_DEFAULT = 400; /* Default window width */
|
|
const int CY_DEFAULT = 400; /* Default window height */
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GetAppKey
|
|
*
|
|
\**************************************************************************/
|
|
HKEY
|
|
GetAppKey(
|
|
BOOL fCreate
|
|
)
|
|
{
|
|
HKEY hKey = 0;
|
|
|
|
if(fCreate)
|
|
{
|
|
if(RegCreateKey(HKEY_CURRENT_USER, cszAppKey, &hKey) == ERROR_SUCCESS)
|
|
return hKey;
|
|
}
|
|
else
|
|
{
|
|
if(RegOpenKey(HKEY_CURRENT_USER, cszAppKey, &hKey) == ERROR_SUCCESS)
|
|
return hKey;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* ProfileStringIn
|
|
*
|
|
\**************************************************************************/
|
|
UINT
|
|
ProfileStringIn(
|
|
LPTSTR szKey,
|
|
LPTSTR szDefault,
|
|
LPTSTR szProfileString,
|
|
DWORD cb
|
|
)
|
|
{
|
|
CheckPointer(szKey,0);
|
|
CheckPointer(szDefault,0);
|
|
CheckPointer(szProfileString,0);
|
|
|
|
HKEY hKey;
|
|
DWORD dwType;
|
|
|
|
if((hKey = GetAppKey(FALSE)) == 0)
|
|
{
|
|
StringCbCopy(szProfileString, cb, szDefault);
|
|
return lstrlen(szProfileString);
|
|
}
|
|
|
|
if((RegQueryValueEx(hKey, szKey, NULL, &dwType,
|
|
(LPBYTE)szProfileString, &cb) != ERROR_SUCCESS)
|
|
|| dwType != REG_SZ)
|
|
{
|
|
StringCbCopy(szProfileString, cb, szDefault);
|
|
cb = lstrlen(szProfileString);
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
return cb;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* ProfileStringOut
|
|
*
|
|
\**************************************************************************/
|
|
void
|
|
ProfileStringOut(
|
|
LPTSTR szKey,
|
|
LPTSTR szProfileString
|
|
)
|
|
{
|
|
assert(szKey);
|
|
assert(szProfileString);
|
|
|
|
HKEY hKey;
|
|
|
|
hKey = GetAppKey(TRUE);
|
|
if (hKey)
|
|
{
|
|
RegSetValueEx(hKey, szKey, 0, REG_SZ, (LPBYTE)szProfileString,
|
|
sizeof(TCHAR) * (lstrlen(szProfileString)+1));
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* LoadWindowPos
|
|
*
|
|
* Retrieve the window position information from the registry
|
|
*
|
|
\**************************************************************************/
|
|
|
|
#ifndef SPI_GETWORKAREA
|
|
#define SPI_GETWORKAREA 48 // because NT doesnt have this define yet
|
|
#endif
|
|
|
|
BOOL
|
|
LoadWindowPos(
|
|
LPRECT lprc
|
|
)
|
|
{
|
|
CheckPointer(lprc,FALSE);
|
|
|
|
static RECT rcDefault = {0,0,CX_DEFAULT,CY_DEFAULT};
|
|
RECT rcScreen, rc;
|
|
HKEY hKey = GetAppKey(FALSE);
|
|
|
|
// Read window placement from the registry.
|
|
//
|
|
*lprc = rcDefault;
|
|
|
|
if(hKey)
|
|
{
|
|
DWORD cb = sizeof(rc);
|
|
DWORD dwType;
|
|
|
|
if(ERROR_SUCCESS == RegQueryValueEx(hKey, cszWindow, NULL, &dwType, (LPBYTE)&rc, &cb)
|
|
&& dwType == REG_BINARY && cb == sizeof(RECT))
|
|
{
|
|
*lprc = rc;
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
// If we fail to get the working area (screen-tray), then assume
|
|
// the screen is 640x480
|
|
//
|
|
if(! SystemParametersInfo(SPI_GETWORKAREA, 0, &rcScreen, FALSE))
|
|
{
|
|
rcScreen.top = rcScreen.left = 0;
|
|
rcScreen.right = 640;
|
|
rcScreen.bottom = 480;
|
|
}
|
|
|
|
// If the proposed window position is outside the screen,
|
|
// use the default placement
|
|
//
|
|
if(! IntersectRect(&rc, &rcScreen, lprc))
|
|
{
|
|
*lprc = rcDefault;
|
|
}
|
|
|
|
return ! IsRectEmpty(lprc);
|
|
}
|
|
|
|
|
|
/*****************************Public*Routine******************************\
|
|
* SaveWindowPos
|
|
*
|
|
* Store the window position information in the registry
|
|
*
|
|
\**************************************************************************/
|
|
BOOL
|
|
SaveWindowPos(
|
|
HWND hwnd
|
|
)
|
|
{
|
|
WINDOWPLACEMENT wpl;
|
|
|
|
HKEY hKey = GetAppKey(TRUE);
|
|
if(!hKey)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// Save the current size and position of the window to the registry
|
|
//
|
|
ZeroMemory(&wpl, sizeof(wpl));
|
|
wpl.length = sizeof(wpl);
|
|
GetWindowPlacement(hwnd, &wpl);
|
|
|
|
RegSetValueEx(hKey, cszWindow, 0, REG_BINARY,
|
|
(LPBYTE)&wpl.rcNormalPosition,
|
|
sizeof(wpl.rcNormalPosition));
|
|
|
|
RegCloseKey(hKey);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*****************************Private*Routine******************************\
|
|
* GetRecentFiles
|
|
*
|
|
* Reads at most MAX_RECENT_FILES from the app's registry entry.
|
|
* Returns the number of files actually read.
|
|
* Updates the File menu to show the "recent" files.
|
|
*
|
|
\**************************************************************************/
|
|
int
|
|
GetRecentFiles(
|
|
int iLastCount,
|
|
int iMenuPosition // Menu position of start of MRU list
|
|
)
|
|
{
|
|
int i;
|
|
TCHAR FileName[MAX_PATH];
|
|
TCHAR szKey[32];
|
|
HMENU hSubMenu;
|
|
|
|
//
|
|
// Delete the files from the menu
|
|
//
|
|
hSubMenu = GetSubMenu(GetMenu(hwndApp), 0);
|
|
|
|
// Delete the separator at the requested position and all the other
|
|
// recent file entries
|
|
if(iLastCount != 0)
|
|
{
|
|
DeleteMenu(hSubMenu, iMenuPosition, MF_BYPOSITION);
|
|
|
|
for(i = 1; i <= iLastCount; i++)
|
|
{
|
|
DeleteMenu(hSubMenu, ID_RECENT_FILE_BASE + i, MF_BYCOMMAND);
|
|
}
|
|
}
|
|
|
|
for(i = 1; i <= MAX_RECENT_FILES; i++)
|
|
{
|
|
DWORD len;
|
|
TCHAR szMenuName[MAX_PATH + 3];
|
|
|
|
(void)StringCchPrintf(szKey, NUMELMS(szKey), TEXT("File %d\0"), i);
|
|
|
|
len = ProfileStringIn(szKey, TEXT(""), FileName, MAX_PATH * sizeof(TCHAR));
|
|
if(len == 0)
|
|
{
|
|
i = i - 1;
|
|
break;
|
|
}
|
|
|
|
StringCchCopy(aRecentFiles[i - 1], NUMELMS(aRecentFiles[i-1]), FileName);
|
|
(void)StringCchPrintf(szMenuName, NUMELMS(szMenuName), TEXT("&%d %s\0"), i, FileName);
|
|
|
|
if(i == 1)
|
|
{
|
|
InsertMenu(hSubMenu, iMenuPosition, MF_SEPARATOR | MF_BYPOSITION, (UINT)-1, NULL);
|
|
}
|
|
|
|
InsertMenu(hSubMenu, iMenuPosition + i, MF_STRING | MF_BYPOSITION,
|
|
ID_RECENT_FILE_BASE + i, szMenuName);
|
|
}
|
|
|
|
//
|
|
// i is the number of recent files in the array.
|
|
//
|
|
return i;
|
|
}
|
|
|
|
|
|
/*****************************Private*Routine******************************\
|
|
* SetRecentFiles
|
|
*
|
|
* Writes the most recent files to the registry.
|
|
* Purges the oldest file if necessary.
|
|
*
|
|
\**************************************************************************/
|
|
int
|
|
SetRecentFiles(
|
|
TCHAR *FileName, // File name to add
|
|
int iCount, // Current count of files
|
|
int iMenuPosition // Menu position of start of MRU list
|
|
)
|
|
{
|
|
TCHAR FullPathFileName[MAX_PATH];
|
|
TCHAR *lpFile=0;
|
|
TCHAR szKey[32];
|
|
int iCountNew, i;
|
|
|
|
//
|
|
// Check for duplicates - we don't allow them
|
|
//
|
|
for(i = 0; i < iCount; i++)
|
|
{
|
|
if(0 == lstrcmpi(FileName, aRecentFiles[i]))
|
|
{
|
|
return iCount;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Throw away the oldest entry
|
|
//
|
|
MoveMemory(&aRecentFiles[1], &aRecentFiles[0],
|
|
sizeof(aRecentFiles) - sizeof(aRecentFiles[1]));
|
|
|
|
//
|
|
// Copy in the full path of the new file.
|
|
//
|
|
GetFullPathName(FileName, MAX_PATH, FullPathFileName, &lpFile);
|
|
StringCchCopy(aRecentFiles[0], NUMELMS(aRecentFiles[0]), FullPathFileName);
|
|
|
|
//
|
|
// Update the count of files, saturate to MAX_RECENT_FILES.
|
|
//
|
|
iCountNew = min(iCount + 1, MAX_RECENT_FILES);
|
|
|
|
//
|
|
// Clear the old stuff and the write out the recent files to disk
|
|
//
|
|
for(i = 1; i <= iCountNew; i++)
|
|
{
|
|
(void)StringCchPrintf(szKey, NUMELMS(szKey),TEXT("File %d\0"), i);
|
|
ProfileStringOut(szKey, aRecentFiles[i - 1]);
|
|
}
|
|
|
|
//
|
|
// Update the file menu
|
|
//
|
|
GetRecentFiles(iCount, iMenuPosition);
|
|
|
|
return iCountNew; // the updated count of files.
|
|
}
|
|
|
|
|
|
|