📄 vncdesktop.cpp
字号:
m_server->PollFullScreen(TRUE); } else { vnclog.Print(LL_INTERR, VNCLOG("set hooks OK\n")); } // Start up the keyboard and mouse filters SetKeyboardFilterHook(m_server->LocalInputsDisabled()); SetMouseFilterHook(m_server->LocalInputsDisabled()); // Start a timer to handle Polling Mode. The timer will cause // an "idle" event once every second, which is necessary if Polling // Mode is being used, to cause TriggerUpdate to be called. m_timerid = SetTimer(m_hwnd, 1, 1000, NULL); // Initialise the buffer object m_buffer.SetDesktop(this); // Create the quarter-screen rectangle for polling m_qtrscreen = rfb::Rect(0, 0, m_bmrect.br.x, m_bmrect.br.y/4); // Everything is ok, so return TRUE return TRUE;}// Routine to shutdown all the hooks and stuffBOOLvncDesktop::Shutdown(){ // If we created a timer then kill it if (m_timerid != NULL) KillTimer(NULL, m_timerid); // If we created a window then kill it and the hooks if(m_hwnd != NULL) { // Remove the system hooks UnSetHooks(GetCurrentThreadId()); // 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\n")); } m_hrootdc = NULL; } if (m_hmemdc != NULL) { // Release our device context if (!DeleteDC(m_hmemdc)) { vnclog.Print(LL_INTERR, VNCLOG("failed to DeleteDC\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; } // *** // vncService::SelectHomeWinStation(); return TRUE;}// Routine to ensure we're on the correct NT desktopBOOLvncDesktop::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 CALLBACKKillScreenSaverFunc(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;}voidvncDesktop::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; } }}BOOLvncDesktop::InitBitmap(){ // Get the device context for the whole screen and find it's size m_hrootdc = ::GetDC(NULL); if (m_hrootdc == NULL) { vnclog.Print(LL_INTERR, VNCLOG("failed to get display context\n")); return FALSE; } m_bmrect = rfb::Rect(0, 0, GetDeviceCaps(m_hrootdc, HORZRES), GetDeviceCaps(m_hrootdc, VERTRES)); vnclog.Print(LL_INTINFO, VNCLOG("bitmap dimensions are %d x %d\n"), m_bmrect.br.x, m_bmrect.br.y); // Create a compatible memory DC m_hmemdc = CreateCompatibleDC(m_hrootdc); if (m_hmemdc == NULL) { vnclog.Print(LL_INTERR, VNCLOG("failed to create compatibleDC(%d)\n"), GetLastError()); return FALSE; } // Check that the device capabilities are ok if ((GetDeviceCaps(m_hrootdc, RASTERCAPS) & RC_BITBLT) == 0) { 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) { 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.br.x, m_bmrect.br.y); if (m_membitmap == NULL) { vnclog.Print(LL_INTERR, VNCLOG("failed to create memory bitmap(%d)\n"), GetLastError()); return FALSE; } vnclog.Print(LL_INTINFO, VNCLOG("created memory bitmap\n")); // Get the bitmap's format and colour details int result; memset(&m_bminfo, 0, sizeof(m_bminfo)); 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) { vnclog.Print(LL_INTERR, VNCLOG("unable to get display format\n")); return FALSE; } result = ::GetDIBits(m_hmemdc, m_membitmap, 0, 1, NULL, &m_bminfo.bmi, DIB_RGB_COLORS); if (result == 0) { vnclog.Print(LL_INTERR, VNCLOG("unable to get display colour info\n")); return FALSE; } vnclog.Print(LL_INTINFO, VNCLOG("got bitmap format\n")); // Henceforth we want to use a top-down scanning representation m_bminfo.bmi.bmiHeader.biHeight = - abs(m_bminfo.bmi.bmiHeader.biHeight); // Is the bitmap palette-based or truecolour? m_bminfo.truecolour = (GetDeviceCaps(m_hmemdc, RASTERCAPS) & RC_PALETTE) == 0; return TRUE;}BOOLvncDesktop::ThunkBitmapInfo(){ // If we leave the pixel format intact, the blist can be optimised (Will Dean's patch) m_formatmunged = FALSE; // HACK ***. Optimised blits don't work with palette-based displays, yet if (!m_bminfo.truecolour) { m_formatmunged = TRUE; } // Attempt to force the actual format into one we can handle // We can handle 8-bit-palette and 16/32-bit-truecolour modes switch (m_bminfo.bmi.bmiHeader.biBitCount) { case 1: case 4: vnclog.Print(LL_INTINFO, VNCLOG("DBG:used/bits/planes/comp/size = %d/%d/%d/%d/%d\n"), (int)m_bminfo.bmi.bmiHeader.biClrUsed, (int)m_bminfo.bmi.bmiHeader.biBitCount, (int)m_bminfo.bmi.bmiHeader.biPlanes, (int)m_bminfo.bmi.bmiHeader.biCompression, (int)m_bminfo.bmi.bmiHeader.biSizeImage); // Correct the BITMAPINFO header to the format we actually want m_bminfo.bmi.bmiHeader.biClrUsed = 0; m_bminfo.bmi.bmiHeader.biPlanes = 1; m_bminfo.bmi.bmiHeader.biCompression = BI_RGB; m_bminfo.bmi.bmiHeader.biBitCount = 8; m_bminfo.bmi.bmiHeader.biSizeImage = abs((m_bminfo.bmi.bmiHeader.biWidth * m_bminfo.bmi.bmiHeader.biHeight * m_bminfo.bmi.bmiHeader.biBitCount)/ 8); m_bminfo.bmi.bmiHeader.biClrImportant = 0; m_bminfo.truecolour = FALSE; // Display format is non-VNC compatible - use the slow blit method m_formatmunged = TRUE; break; case 24: // Update the bitmapinfo header m_bminfo.bmi.bmiHeader.biBitCount = 32; m_bminfo.bmi.bmiHeader.biPlanes = 1; m_bminfo.bmi.bmiHeader.biCompression = BI_RGB; m_bminfo.bmi.bmiHeader.biSizeImage = abs((m_bminfo.bmi.bmiHeader.biWidth * m_bminfo.bmi.bmiHeader.biHeight * m_bminfo.bmi.bmiHeader.biBitCount)/ 8); // Display format is non-VNC compatible - use the slow blit method m_formatmunged = TRUE; break; } return TRUE;}BOOLvncDesktop::SetPixFormat(){ // If we are using a memory bitmap then check how many planes it uses // The VNC code can only handle formats with a single plane (CHUNKY pixels) if (!m_DIBbits) { vnclog.Print(LL_INTINFO, VNCLOG("DBG:display context has %d planes!\n"), GetDeviceCaps(m_hrootdc, PLANES)); vnclog.Print(LL_INTINFO, VNCLOG("DBG:memory context has %d planes!\n"), GetDeviceCaps(m_hmemdc, PLANES)); if (GetDeviceCaps(m_hmemdc, PLANES) != 1) { MessageBox( NULL, "vncDesktop : current display is PLANAR, not CHUNKY!\n" "WinVNC cannot be used with this graphics device driver", szAppName, MB_ICONSTOP | MB_OK ); return FALSE; } } // Examine the bitmapinfo structure to obtain the current pixel format m_scrinfo.format.trueColour = m_bminfo.truecolour; m_scrinfo.format.bigEndian = 0; // Set up the native buffer width, height and format m_scrinfo.framebufferWidth = (CARD16) (m_bmrect.br.x - m_bmrect.tl.x); // Swap endian before actually sending m_scrinfo.framebufferHeight = (CARD16) (m_bmrect.br.y - m_bmrect.tl.y); // Swap endian before actually sending m_scrinfo.format.bitsPerPixel = (CARD8) m_bminfo.bmi.bmiHeader.biBitCount; m_scrinfo.format.depth = (CARD8) m_bminfo.bmi.bmiHeader.biBitCount; // Calculate the number of bytes per row m_bytesPerRow = m_scrinfo.framebufferWidth * m_scrinfo.format.bitsPerPixel / 8; return TRUE;}BOOLvncDesktop::SetPixShifts(){ // Sort out the colour shifts, etc. DWORD redMask=0, blueMask=0, greenMask = 0; switch (m_bminfo.bmi.bmiHeader.biBitCount) { case 16: // Standard 16-bit display if (m_bminfo.bmi.bmiHeader.biCompression == BI_RGB) { // each word single pixel 5-5-5 redMask = 0x7c00; greenMask = 0x03e0; blueMask = 0x001f; } else { if (m_bminfo.bmi.bmiHeader.biCompression == BI_BITFIELDS) { redMask = *(DWORD *) &m_bminfo.bmi.bmiColors[0]; greenMask = *(DWORD *) &m_bminfo.bmi.bmiColors[1]; blueMask = *(DWORD *) &m_bminfo.bmi.bmiColors[2]; } } break; case 32: // Standard 24/32 bit displays if (m_bminfo.bmi.bmiHeader.biCompression == BI_RGB) { redMask = 0xff0000; greenMask = 0xff00; blueMask = 0x00ff; } else { if (m_bminfo.bmi.bmiHeader.biCompression == BI_BITFIELDS) { redMask = *(DWORD *) &m_bminfo.bmi.bmiColors[0]; greenMask = *(DWORD *) &m_bminfo.bmi.bmiColors[1]; blueMask = *(DWORD *) &m_bminfo.bmi.bmiColors[2]; } } break; default: // Other pixel formats are only valid if they're palette-based if (m_bminfo.truecolour) { vnclog.Print(LL_INTERR, "unsupported truecolour pixel format for setpixshifts\n"); return FALSE; } return TRUE; } // Convert the data we just retrieved MaskToMaxAndShift(redMask, m_scrinfo.format.redMax, m_scrinfo.format.redShift); MaskToMaxAndShift(greenMask, m_scrinfo.format.greenMax, m_scrinfo.format.greenShift); MaskToMaxAndShift(blueMask, m_scrinfo.format.blueMax, m_scrinfo.format.blueShift); return TRUE;}BOOLvncDesktop::SetPalette(){ // Lock the current display palette into the memory DC we're holding // *** CHECK THIS FOR LEAKS! if (!m_bminfo.truecolour) { if (!m_DIBbits) { // - Handle the palette for a non DIB-Section LOGPALETTE *palette; UINT size = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * 256); palette = (LOGPALETTE *) new char[size]; if (palette == NULL) { vnclog.Print(LL_INTERR, VNCLOG("unable to allocate logical palette\n")); return FALSE; } // Initialise the structure palette->palVersion = 0x300; palette->palNumEntries = 256; // Get the system colours if (GetSystemPaletteEntries(m_hrootdc, 0, 256, palette->palPalEntry) == 0) { vnclog.Print(LL_INTERR, VNCLOG("unable to get system palette entries\n")); delete [] palette; return FALSE; } // Create a palette from those HPALETTE pal = CreatePalette(palette); if (pal == NULL) { vnclog.Print(LL_INTERR, VNCLOG("unable to create HPALETTE\n")); delete [] palette; return FALSE; } // Select the palette into our memory DC HPALETTE oldpalette = SelectPalette(m_hmemdc, pal, FALSE); if (oldpalette == NULL) { vnclog.Print(LL_INTERR, VNCLOG("unable to select() HPALETTE\n")); delete [] palette; DeleteObject(pal); return FALSE; } // Worked, so realise the palette if (RealizePalette(m_hmemdc) == GDI_ERROR) vnclog.Print(LL_INTWARN, VNCLOG("warning - failed to RealizePalette\n")); // It worked! delete [] palette; DeleteObject(oldpalette); vnclog.Print(LL_INTINFO, VNCLOG("initialised palette OK\n")); return TRUE; } else { // - Handle a DIB-Section's palette // - Fetch the system palette for the framebuffer PALETTEENTRY syspalette[256]; UINT entries = ::GetSystemPaletteEntries(m_hrootdc, 0, 256, syspalette); vnclog.Print(LL_INTERR, VNCLOG("framebuffer has %u palette entries"), entries); // - Store it and convert it to RGBQUAD format RGBQUAD dibpalette[256]; unsigned int i; for (i=0;i<entries;i++) { dibpalette[i].rgbRed = syspalette[i].peRed; dibpalette[i].rgbGreen = syspalette[i].peGreen; dibpalette[i].rgbBlue = syspalette[i].peBlue; dibpalette[i].rgbReserved = 0; } // - Set the rest of the palette to something nasty but usable for (i=entries;i<256;i++) { dibpalette[i].rgbRed = i % 2 ? 255 : 0; dibpalette[i].rgbGreen = i/2 % 2 ? 255 : 0; dibpalette[i].rgbBlue = i/4 % 2 ? 255 : 0; dibpalette[i].rgbReserved = 0; } // - Update the DIB section to use the same palette HDC bitmapDC=::CreateCompatibleDC(m_hrootdc); if (!bitmapDC) { vnclog.Print(LL_INTERR, VNCLOG("unable to create temporary DC"), GetLastError()); return FALSE; } HBITMAP old_bitmap = (HBITMAP)::SelectObject(bitmapDC, m_membitmap); if (!old_bitmap) { vnclog.Print(LL_INTERR, VNCLOG("unable to select DIB section into temporary DC"), GetLastError()); return FALSE; } UINT entries_set = ::SetDIBColorTable(bitmapDC, 0, 256, dibpalette); if (entries_set == 0) { vnclog.Print(LL_INTERR, VNCLOG("unable to set DIB section palette"), GetLastError()); return FALSE; } if (!::SelectObject(bitmapDC, old_bitmap)) { vnclog.Print(LL_INTERR, VNCLOG("unable to restore temporary DC bitmap"), GetLastError()); return FALSE; } } } // Not a palette based local screen - forget it! vnclog.Print(LL_INTERR, VNCLOG("no palette data for truecolour display\n")); return TRUE;}LRESULT CALLBACK DesktopWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);ATOM m_wndClass = 0;BOOLvncDesktop::InitWindow(){ if (m_wndClass == 0) { // Create the window class WNDCLASSEX wndclass; wndclass.cbSize = sizeof(wndclass); wndclass.style = 0; wndclass.lpfnWndProc = &DesktopWndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hAppInstance; wndclass.hIcon = NULL; wndclass.hCursor = NULL; wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); wndclass.lpszMenuName = (const char *) NULL; wndclass.lpszClassName = szDesktopSink; wndclass.hIconSm = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -