📄 vncdesktop.cpp
字号:
vnclog.Print(LL_INTERR, VNCLOG("unable to get display format"));
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"));
return FALSE;
}
vnclog.Print(LL_INTINFO, VNCLOG("got bitmap format"));
// 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;
InvalidateRect(NULL,NULL,TRUE);
return TRUE;
}
BOOL
vncDesktop::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"),
(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;
}
BOOL
vncDesktop::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!"),
GetDeviceCaps(m_hrootdc, PLANES));
vnclog.Print(LL_INTINFO, VNCLOG("DBG:memory context has %d planes!"),
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;
}
BOOL
vncDesktop::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, VNCLOG("unsupported truecolour pixel format for setpixshifts"));
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;
}
BOOL
vncDesktop::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"));
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"));
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"));
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"));
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"));
// It worked!
delete [] palette;
DeleteObject(oldpalette);
vnclog.Print(LL_INTINFO, VNCLOG("initialised palette OK"));
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"));
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////
DWORD WINAPI Driverwatch(LPVOID lpParam)
{
//Mouse shape changed
if(OSVersion() == OSVERSION_2000_XP_VISTA)
{
HANDLE event;
//DrvWatch *mywatch=(DrvWatch*)lpParam;
HWND hwnd=(HWND)lpParam;
event=NULL;
while (event==NULL)
{
event = OpenEvent (SYNCHRONIZE, FALSE, "VncEvent") ;
Sleep(900);
if (!IsWindow(hwnd))
{
if (event) CloseHandle(event);
return 0;
}
}
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
for (;;)
{
if (WaitForSingleObject(event, 2000) == WAIT_OBJECT_0)
{
PostMessage(hwnd, WM_USER, 0, 0);
}
if (!IsWindow(hwnd) || !g_Desktop_running)
{
if (event) CloseHandle(event);
break;
}
}
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////
DWORD WINAPI Driverwatch2(LPVOID lpParam)
{
//new screen update
if(OSVersion() == OSVERSION_2000_XP_VISTA)
{
HANDLE event;
//DrvWatch *mywatch=(DrvWatch*)lpParam;
HWND hwnd=(HWND)lpParam;
event=NULL;
while (event==NULL)
{
event = OpenEvent (SYNCHRONIZE, FALSE, "VncEvent2") ;
Sleep(900);
if (!IsWindow(hwnd))
{
if (event) CloseHandle(event);
return 0;
}
}
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
counterwatch=0;
for (;;)
{
if (WaitForSingleObject(event, 50) == WAIT_OBJECT_0)
{
//if (!g_update_triggered)
PostMessage(hwnd, WM_TIMER, 0, 0);
Sleep(100);
}
else
{
counterwatch++;
if (counterwatch==100)
{
PostMessage(hwnd, WM_USER+2, 0, 0);
counterwatch=0;
}
}
if (!IsWindow(hwnd) || !g_Desktop_running)
{
if (event) CloseHandle(event);
break;
}
}
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK DesktopWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
ATOM m_wndClass = 0;
BOOL
vncDesktop::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;
// Register it
m_wndClass = RegisterClassEx(&wndclass);
if (!m_wndClass) {
vnclog.Print(LL_INTERR, VNCLOG("failed to register window class"));
return FALSE;
}
}
// And create a window
m_hwnd = CreateWindow(szDesktopSink,
"WinVNC",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
400, 200,
NULL,
NULL,
hAppInstance,
NULL);
if (m_hwnd == NULL) {
vnclog.Print(LL_INTERR, VNCLOG("failed to create hook window"));
return FALSE;
}
// Set the "this" pointer for the window
SetWindowLong(m_hwnd, GWL_USERDATA, (long)this);
// Enable clipboard hooking
m_hnextviewer = SetClipboardViewer(m_hwnd);
StopDriverWatches=false;
DrvWatch mywatch;
mywatch.stop=&StopDriverWatches;
mywatch.hwnd=m_hwnd;
if (VideoBuffer())
{
DWORD myword;
HANDLE T1=CreateThread(NULL,0,Driverwatch,m_hwnd,0,&myword);
// HANDLE T2=CreateThread(NULL,0,Driverwatch2,m_hwnd,0,&myword);
// CloseHandle(T2);
CloseHandle(T1);
}
return TRUE;
}
void
vncDesktop::EnableOptimisedBlits()
{
vnclog.Print(LL_INTINFO, VNCLOG("attempting to enable DIBsection blits"));
// Create a new DIB section
//HBITMAP tempbitmap=NULL;
HBITMAP tempbitmap = CreateDIBSection(m_hmemdc, &m_bminfo.bmi, DIB_RGB_COLORS, &m_DIBbits, NULL, 0);
if (tempbitmap == NULL) {
vnclog.Print(LL_INTINFO, VNCLOG("failed to build DIB section - reverting to slow blits"));
m_DIBbits = NULL;
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -