SDL2.0在windows下渲染电脑锁屏后解锁出现画面卡住的现象
***解决方法,利用windows下的锁屏检测,当检测到锁屏过后判断用户解锁,将SDL的SDL_Renderer和SDL_Texture使用SDL_DestroyRenderer和SDL_DestroyTexture销毁重新创建,即可解决。
C++ 锁屏检测代码链接如下:
https://blog.csdn.net/flushhip/article/details/83141062
这个博客下提到的锁屏检测win7和win10返回状态不一致,我测试过确实如此,优化方法是对windows的版本进行判断,我由于处理逻辑只区分win7和其它版本,win8,win11版本没有单独区分,修改后的代码如下:
先定义个成员或全局变量:
bool m_bWin7 =false;
unsigned long dwMajorVer = 0;
unsigned long dwMinorVer = 0;
unsigned long dwBuildNumber = 0;
int nRet = GetNtVersionNumbers(dwMajorVer, dwMinorVer, dwBuildNumber);
if (TRUE != nRet)
{
printf("get Windows Version Fail!");
}
/*
5.0 Windows 2000";
5.1 Windows XP";
5.2 Windows 2003";
6.0 Windows Vista";
6.1 Windows 7";
6.2 Windows 8";
6.3 Windows 8.1";
10.0 Windows 10";
其他版本
*/
if (6 == dwMajorVer && 1 == dwMinorVer)
{
m_bWin7 = true;
}
int GetNtVersionNumbers(unsigned long& dwMajorVer, unsigned long& dwMinorVer, unsigned long& dwBuildNumber)
{
int bRet = FALSE;
HMODULE hModNtdll = NULL;
if (hModNtdll = ::LoadLibraryW(L"ntdll.dll"))
{
typedef void (WINAPI *pfRTLGETNTVERSIONNUMBERS)(unsigned long*, unsigned long*, unsigned long*);
pfRTLGETNTVERSIONNUMBERS pfRtlGetNtVersionNumbers;
pfRtlGetNtVersionNumbers = (pfRTLGETNTVERSIONNUMBERS)::GetProcAddress(hModNtdll, "RtlGetNtVersionNumbers");
if (pfRtlGetNtVersionNumbers)
{
pfRtlGetNtVersionNumbers(&dwMajorVer, &dwMinorVer, &dwBuildNumber);
dwBuildNumber &= 0x0ffff;
bRet = TRUE;
}
::FreeLibrary(hModNtdll);
hModNtdll = NULL;
}
return bRet;
}
bool IsSessionLocked()
{
typedef BOOL(PASCAL * WTSQuerySessionInformation)(HANDLE hServer, DWORD SessionId, WTS_INFO_CLASS WTSInfoClass, LPTSTR* ppBuffer, DWORD* pBytesReturned);
typedef void (PASCAL * WTSFreeMemory)(PVOID pMemory);
WTSINFOEXW * pInfo = NULL;
WTS_INFO_CLASS wtsic = WTSSessionInfoEx;
bool bRet = false;
if (m_bWin7)
{
bRet = true;
}
LPTSTR ppBuffer = NULL;
DWORD dwBytesReturned = 0;
LONG dwFlags = 0;
WTSQuerySessionInformation pWTSQuerySessionInformation = NULL;
WTSFreeMemory pWTSFreeMemory = NULL;
HMODULE hLib = LoadLibrary(L"wtsapi32.dll");
if (!hLib)
{
return false;
}
pWTSQuerySessionInformation = (WTSQuerySessionInformation)GetProcAddress(hLib, "WTSQuerySessionInformationW");
if (pWTSQuerySessionInformation)
{
pWTSFreeMemory = (WTSFreeMemory)GetProcAddress(hLib, "WTSFreeMemory");
if (pWTSFreeMemory != NULL)
{
DWORD dwSessionID = WTSGetActiveConsoleSessionId();
if (pWTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, dwSessionID, wtsic, &ppBuffer, &dwBytesReturned))
{
if (dwBytesReturned > 0)
{
pInfo = (WTSINFOEXW*)ppBuffer;
if (pInfo->Level == 1)
{
dwFlags = pInfo->Data.WTSInfoExLevel1.SessionFlags;
}
if (dwFlags == WTS_SESSIONSTATE_LOCK)
{
bRet = true;
if (m_bWin7)
{
bRet = false;
}
}
}
pWTSFreeMemory(ppBuffer);
ppBuffer = NULL;
}
}
}
if (hLib != NULL)
{
FreeLibrary(hLib);
}
return bRet;
}
当面临多分屏播放多对象时可开线程检测线程函数如下:
void LockScreenWork()
{
while (m_bLockScreen)
{
Sleep(5000);
bool bLockScreen = IsSessionLocked();
while (bLockScreen)
{
Sleep(2000);
bLockScreen = IsSessionLocked();
if (!bLockScreen)
{
printf( "解屏\n");
map<int , TaskObject *>::iterator itemTask = m_mapTask.begin();
for (; itemTask != m_mapTask.end(); itemTask++)
{
itemTask->second->LockScreen(true);//这个标志传入渲染对象内部作为重置渲染资源判断
}
}
}
}
printf("锁屏检测函数结束\n");
}