📄 vncdesktop.cpp
字号:
BOOL vncDesktop::Shutdown()
{
// If we created timers then kill them
if (m_timer_polling)
{
KillTimer(Window(), TIMER_POLL);
m_timer_polling = 0;
}
if (m_timer_blank_screen)
{
KillTimer(Window(), TIMER_BLANK_SCREEN);
m_timer_blank_screen = 0;
}
// If we created a window then kill it and the hooks
if (m_hwnd != NULL)
{
//Remove the system hooks
//Unset keyboard and mouse hooks
SetLocalInputPriorityHook(false);
m_hooks_may_change = false;
ShutdownHooks();
#ifndef HORIZONLIVE
// Stop the keyboard and mouse filters
SetKeyboardFilterHook(false);
SetMouseFilterHook(false);
#endif
// The window is being closed - remove it from the viewer list
ChangeClipboardChain(m_hwnd, m_hnextviewer);
// Close the hook window
DestroyWindow(m_hwnd);
m_hwnd = NULL;
m_hnextviewer = NULL;
}
// Now free all the bitmap stuff
if (m_hrootdc != NULL)
{
// Release our device context
if(ReleaseDC(NULL, m_hrootdc) == 0)
{
vnclog.Print(LL_INTERR, VNCLOG("failed to ReleaseDC(m_hrootdc)\n"));
}
m_hrootdc = NULL;
}
if (m_hmemdc != NULL)
{
// Release our device context
if (!DeleteDC(m_hmemdc))
{
vnclog.Print(LL_INTERR, VNCLOG("failed to DeleteDC(m_hmemdc)\n"));
}
m_hmemdc = NULL;
}
if (m_membitmap != NULL)
{
// Release the custom bitmap, if any
if (!DeleteObject(m_membitmap))
{
vnclog.Print(LL_INTERR, VNCLOG("failed to DeleteObject\n"));
}
m_membitmap = NULL;
}
// Free back buffer
if (m_backbuff != NULL)
{
delete [] m_backbuff;
m_backbuff = NULL;
}
if (m_freemainbuff)
{
// Slow blits were enabled - free the slow blit buffer
if (m_mainbuff != NULL)
{
delete [] m_mainbuff;
m_mainbuff = NULL;
}
}
// Free the WindowPos atom!
if (VNC_WINDOWPOS_ATOM != NULL)
{
if (GlobalDeleteAtom(VNC_WINDOWPOS_ATOM) != 0)
{
vnclog.Print(LL_INTERR, VNCLOG("failed to delete atom!\n"));
}
}
ShutdownVideoDriver();
return TRUE;
}
// Routines to set/unset hooks via VNCHooks.dll
void
vncDesktop::ActivateHooks()
{
BOOL enable = !(m_server->DontSetHooks() && m_server->PollFullScreen());
if (enable && !m_hooks_active) {
m_hooks_active = SetHook(m_hwnd,
RFB_SCREEN_UPDATE,
RFB_COPYRECT_UPDATE,
RFB_MOUSE_UPDATE);
if (!m_hooks_active) {
vnclog.Print(LL_INTERR, VNCLOG("failed to set system hooks\n"));
// Switch on full screen polling, so they can see something, at least...
m_server->PollFullScreen(TRUE);
}
} else if (!enable) {
ShutdownHooks();
}
}
void
vncDesktop::ShutdownHooks()
{
if (m_hooks_active)
m_hooks_active = !UnSetHook(m_hwnd);
}
void
vncDesktop::TryActivateHooks()
{
if (m_hooks_may_change)
ActivateHooks();
}
// Routine to ensure we're on the correct NT desktop
BOOL
vncDesktop::InitDesktop()
{
if (vncService::InputDesktopSelected())
return TRUE;
// Ask for the current input desktop
return vncService::SelectDesktop(NULL);
}
// Routine used to close the screen saver, if it's active...
BOOL CALLBACK
KillScreenSaverFunc(HWND hwnd, LPARAM lParam)
{
char buffer[256];
// - ONLY try to close Screen-saver windows!!!
if ((GetClassName(hwnd, buffer, 256) != 0) &&
(strcmp(buffer, "WindowsScreenSaverClass") == 0))
PostMessage(hwnd, WM_CLOSE, 0, 0);
return TRUE;
}
void
vncDesktop::KillScreenSaver()
{
OSVERSIONINFO osversioninfo;
osversioninfo.dwOSVersionInfoSize = sizeof(osversioninfo);
// Get the current OS version
if (!GetVersionEx(&osversioninfo))
return;
vnclog.Print(LL_INTINFO, VNCLOG("KillScreenSaver...\n"));
// How to kill the screen saver depends on the OS
switch (osversioninfo.dwPlatformId)
{
case VER_PLATFORM_WIN32_WINDOWS:
{
// Windows 95
// Fidn the ScreenSaverClass window
HWND hsswnd = FindWindow ("WindowsScreenSaverClass", NULL);
if (hsswnd != NULL)
PostMessage(hsswnd, WM_CLOSE, 0, 0);
break;
}
case VER_PLATFORM_WIN32_NT:
{
// Windows NT
// Find the screensaver desktop
HDESK hDesk = OpenDesktop(
"Screen-saver",
0,
FALSE,
DESKTOP_READOBJECTS | DESKTOP_WRITEOBJECTS
);
if (hDesk != NULL)
{
vnclog.Print(LL_INTINFO, VNCLOG("Killing ScreenSaver\n"));
// Close all windows on the screen saver desktop
EnumDesktopWindows(hDesk, (WNDENUMPROC) &KillScreenSaverFunc, 0);
CloseDesktop(hDesk);
// Pause long enough for the screen-saver to close
//Sleep(2000);
// Reset the screen saver so it can run again
SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, TRUE, 0, SPIF_SENDWININICHANGE);
}
break;
}
}
}
void vncDesktop::ChangeResNow()
{
// IMPORTANT: Screen mode alteration may only take place on a single-mon system.
if (IsMultiMonDesktop())
{
return;
}
BOOL settingsUpdated = false;
int i = 0;
_ASSERTE(!m_lpAlternateDevMode);
m_lpAlternateDevMode = new DEVMODE; // *** create an instance of DEVMODE - Jeremy Peaks
if (!m_lpAlternateDevMode)
{
vnclog.Print(LL_INTINFO, VNCLOG("SCR-WBB: failed to allocate memory "
"for alternate DEVMODE representation!\n"));
return;
}
// *** WBB - Obtain the current display settings.
// only on unimon
if (! EnumDisplaySettings(0, ENUM_CURRENT_SETTINGS, m_lpAlternateDevMode))
{
vnclog.Print(LL_INTINFO,
VNCLOG("SCR-WBB: could not get current display settings!\n"));
delete m_lpAlternateDevMode;
m_lpAlternateDevMode = NULL;
return;
}
vnclog.Print(LL_INTINFO,
VNCLOG("SCR-WBB: current display: w=%d h=%d bpp=%d vRfrsh=%d.\n"),
m_lpAlternateDevMode->dmPelsWidth,
m_lpAlternateDevMode->dmPelsHeight,
m_lpAlternateDevMode->dmBitsPerPel,
m_lpAlternateDevMode->dmDisplayFrequency);
origPelsWidth = m_lpAlternateDevMode->dmPelsWidth; // *** sets the original resolution for use later
origPelsHeight = m_lpAlternateDevMode->dmPelsHeight; // *** - Jeremy Peaks
// *** Open the registry key for resolution settings
HKEY checkdetails = 0;
RegOpenKeyEx(HKEY_LOCAL_MACHINE,
WINVNC_REGISTRY_KEY,
0,
KEY_READ,
&checkdetails);
if (checkdetails)
{
int slen=MAX_REG_ENTRY_LEN;
int valType;
char inouttext[MAX_REG_ENTRY_LEN];
memset(inouttext, 0, MAX_REG_ENTRY_LEN);
// *** Get the registry values for resolution change - Jeremy Peaks
RegQueryValueEx(checkdetails,
"ResWidth",
NULL,
(LPDWORD) &valType,
(LPBYTE) &inouttext,
(LPDWORD) &slen);
if ((valType == REG_SZ) &&
atol(inouttext)) { // *** if width is 0, then this isn't a valid resolution, so do nothing - Jeremy Peaks
m_lpAlternateDevMode->dmPelsWidth = atol(inouttext);
memset(inouttext, 0, MAX_REG_ENTRY_LEN);
RegQueryValueEx(checkdetails,
"ResHeight",
NULL,
(LPDWORD) &valType,
(LPBYTE) &inouttext,
(LPDWORD) &slen);
m_lpAlternateDevMode->dmPelsHeight = atol(inouttext);
if ((valType == REG_SZ ) &&
(m_lpAlternateDevMode->dmPelsHeight > 0)) {
vnclog.Print(LL_INTINFO,
VNCLOG("SCR-WBB: attempting to change "
"resolution w=%d h=%d\n"),
m_lpAlternateDevMode->dmPelsWidth,
m_lpAlternateDevMode->dmPelsHeight);
// *** make res change - Jeremy Peaks
// testing: predefined Width/Height may become incompatible
// with new clrdepth/timings
long resultOfResChange = ChangeDisplaySettings(m_lpAlternateDevMode, CDS_TEST);
if (resultOfResChange == DISP_CHANGE_SUCCESSFUL) {
ChangeDisplaySettings(m_lpAlternateDevMode, CDS_UPDATEREGISTRY);
settingsUpdated = true;
}
}
}
RegCloseKey(checkdetails);
}
if (! settingsUpdated)
{
// Did not change the resolution.
delete m_lpAlternateDevMode;
m_lpAlternateDevMode = NULL;
}
}
void
vncDesktop::SetupDisplayForConnection()
{
KillScreenSaver();
ChangeResNow(); // *** - Jeremy Peaks
}
void
vncDesktop::ResetDisplayToNormal()
{
if (m_lpAlternateDevMode != NULL)
{
// *** In case the resolution was changed, revert to original settings now
m_lpAlternateDevMode->dmPelsWidth = origPelsWidth;
m_lpAlternateDevMode->dmPelsHeight = origPelsHeight;
long resultOfResChange = ChangeDisplaySettings(m_lpAlternateDevMode, CDS_TEST);
if (resultOfResChange == DISP_CHANGE_SUCCESSFUL)
ChangeDisplaySettings(m_lpAlternateDevMode, CDS_UPDATEREGISTRY);
delete m_lpAlternateDevMode;
m_lpAlternateDevMode = NULL;
}
}
RECT vncDesktop::GetSourceRect()
{
if (m_server->WindowShared())
{
RECT wrect;
GetWindowRect(m_server->GetWindowShared(), &wrect);
return wrect;
}
else if (m_server->ScreenAreaShared())
{
return m_server->GetScreenAreaRect();
}
else if (m_server->PrimaryDisplayOnlyShared())
{
RECT pdr = { 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN) };
return pdr;
}
else
{
#ifdef _DEBUG
RECT rd;
_ASSERTE(GetSourceDisplayRect(rd));
_ASSERTE(EqualRect(&rd, &m_bmrect));
#endif
return m_bmrect;
}
}
RECT GetScreenRect()
{
RECT screenrect;
if (IsWinVerOrHigher(4, 10))
{
screenrect.left = GetSystemMetrics(SM_XVIRTUALSCREEN);
screenrect.top = GetSystemMetrics(SM_YVIRTUALSCREEN);
screenrect.right = screenrect.left + GetSystemMetrics(SM_CXVIRTUALSCREEN);
screenrect.bottom = screenrect.top + GetSystemMetrics(SM_CYVIRTUALSCREEN);
}
else
{
screenrect.left = 0;
screenrect.top = 0;
screenrect.right = GetSystemMetrics(SM_CXSCREEN);
screenrect.bottom = GetSystemMetrics(SM_CYSCREEN);
}
return screenrect;
}
BOOL vncDesktop::GetSourceDisplayRect(RECT &rdisp_rect)
{
if (!m_hrootdc)
m_hrootdc = ::GetDC(NULL);
if (!m_hrootdc)
{
vnclog.Print(LL_INTERR, VNCLOG("GetDC() failed, error=%d\n"), GetLastError());
return FALSE;
}
// TODO: refactor it
rdisp_rect = GetScreenRect();
return TRUE;
}
BOOL vncDesktop::InitBitmap()
{
// IMPORTANT: here an optimization may be implemented
// when only a fixed rect is shared.
// then m_bmrect should be set to that rect.
if (!GetSourceDisplayRect(m_bmrect))
{
return FALSE;
}
vnclog.Print(
LL_INTINFO,
VNCLOG("source desktop metrics: (%d, %d, %d, %d)\n"),
m_bmrect.left,
m_bmrect.top,
m_bmrect.right,
m_bmrect.bottom);
vnclog.Print(
LL_INTINFO,
VNCLOG("bitmap dimensions are %dx%d\n"),
m_bmrect.right - m_bmrect.left,
m_bmrect.bottom - m_bmrect.top);
// Create a compatible memory DC
m_hmemdc = CreateCompatibleDC(m_hrootdc);
if (m_hmemdc == NULL) {
vnclog.Print(LL_INTERR, VNCLOG("CreateCompatibleDC() failed, error=%d\n"),
GetLastError());
return FALSE;
}
// Check that the device capabilities are ok
if ((GetDeviceCaps(m_hrootdc, RASTERCAPS) & RC_BITBLT) == 0)
{
// FIXME: MessageBox in a service
MessageBox(
NULL,
"vncDesktop : root device doesn't support BitBlt\n"
"WinVNC cannot be used with this graphic device driver",
szAppName,
MB_ICONSTOP | MB_OK
);
return FALSE;
}
if ((GetDeviceCaps(m_hmemdc, RASTERCAPS) & RC_DI_BITMAP) == 0)
{
// FIXME: MessageBox in a service
MessageBox(
NULL,
"vncDesktop : memory device doesn't support GetDIBits\n"
"WinVNC cannot be used with this graphics device driver",
szAppName,
MB_ICONSTOP | MB_OK
);
return FALSE;
}
// Create the bitmap to be compatible with the ROOT DC!!!
m_membitmap = CreateCompatibleBitmap(
m_hrootdc,
m_bmrect.right - m_bmrect.left,
m_bmrect.bottom - m_bmrect.top);
if (m_membitmap == NULL)
{
vnclog.Print(
LL_INTERR,
VNCLOG("failed to create memory bitmap, error=%d\n"),
GetLastError());
return FALSE;
}
vnclog.Print(LL_INTINFO, VNCLOG("created memory bitmap\n"));
// Get the bitmap's format and colour details
int result;
m_bminfo.bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
m_bminfo.bmi.bmiHeader.biBitCount = 0;
result = ::GetDIBits(m_hmemdc, m_membitmap, 0, 1, NULL, &m_bminfo.bmi, DIB_RGB_COLORS);
if (result == 0) {
return FALSE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -