⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vncdesktop.cpp

📁 teamviewer source code vc++
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	else
		SetLastError(0);		// last error may be set though the call succeeded, so clear it now;

	// Delete the old memory bitmap
	if (m_membitmap != NULL) {
		DeleteObject(m_membitmap);
		m_membitmap = NULL;
	}

	// Replace old membitmap with DIB section
	m_membitmap = tempbitmap;
	vnclog.Print(LL_INTINFO, VNCLOG("enabled fast DIBsection blits OK"));
}

BOOL
vncDesktop::Init(vncServer *server)
{
	vnclog.Print(LL_INTINFO, VNCLOG("initialising desktop handler"));

	// Save the server pointer
	m_server = server;

	// Load in the arrow cursor
	m_hdefcursor = LoadCursor(NULL, IDC_ARROW);
	m_hcursor = m_hdefcursor;
	m_hOldcursor = m_hdefcursor; //sf@2002

	// Spawn a thread to handle that window's message queue
	vncDesktopThread *thread = new vncDesktopThread;
	if (thread == NULL) {
		vnclog.Print(LL_INTERR, VNCLOG("failed to start hook thread"));
		return FALSE;
	}
	m_thread = thread;
	//SINGEL WINDOW
	SWinit();
	// InitHookSettings();
	return thread->Init(this, m_server);
}

int
vncDesktop::ScreenBuffSize()
{
	return m_scrinfo.format.bitsPerPixel/8 *
		m_scrinfo.framebufferWidth *
		m_scrinfo.framebufferHeight;
}

void
vncDesktop::FillDisplayInfo(rfbServerInitMsg *scrinfo)
{
	memcpy(scrinfo, &m_scrinfo, sz_rfbServerInitMsg);
}

// Function to capture an area of the screen immediately prior to sending
// an update.
void
vncDesktop::CaptureScreen(const rfb::Rect &rect, BYTE *scrBuff, UINT scrBuffSize)
{
	assert(rect.enclosed_by(m_bmrect));

	// Select the memory bitmap into the memory DC
	HBITMAP oldbitmap;
	if ((oldbitmap = (HBITMAP) SelectObject(m_hmemdc, m_membitmap)) == NULL)
		return;

	// capture with alpha blending somehow doesn't work on 98
	DWORD rop = (OSVersion() == OSVERSION_2000_XP_VISTA && !DisableCaptureBlt ? 
				 CAPTUREBLT|SRCCOPY : 
				 SRCCOPY);
	BOOL blitok = BitBlt(m_hmemdc, rect.tl.x, rect.tl.y,
		(rect.br.x-rect.tl.x),
		(rect.br.y-rect.tl.y),
		m_hrootdc, rect.tl.x, rect.tl.y, rop);

	// Select the old bitmap back into the memory DC
	SelectObject(m_hmemdc, oldbitmap);

	if (blitok) {
		// Copy the new data to the screen buffer (CopyToBuffer optimises this if possible)
		CopyToBuffer(rect, scrBuff, scrBuffSize);
	}

}

// Add the mouse pointer to the buffer
void
vncDesktop::CaptureMouse(BYTE *scrBuff, UINT scrBuffSize)
{
	POINT CursorPos;
	ICONINFO IconInfo;

	// If the mouse cursor handle is invalid then forget it
	if (m_hcursor == NULL)
		return;

	// Get the cursor position
	if (!GetCursorPos(&CursorPos))
		return;
	//vnclog.Print(LL_INTINFO, VNCLOG("CursorPos %i %i"),CursorPos.x, CursorPos.y);
	// Translate position for hotspot
	if (GetIconInfo(m_hcursor, &IconInfo))
	{
		CursorPos.x -= ((int) IconInfo.xHotspot);
		CursorPos.y -= ((int) IconInfo.yHotspot);
		/// Buffer has (0,0) coordinates, Cursor (screencoordinates)
		CursorPos.x -= m_ScreenOffsetx;
		CursorPos.y -= m_ScreenOffsety;
		///
		if (IconInfo.hbmMask != NULL)
			DeleteObject(IconInfo.hbmMask);
		if (IconInfo.hbmColor != NULL)
			DeleteObject(IconInfo.hbmColor);
	}

	// Select the memory bitmap into the memory DC
	HBITMAP oldbitmap;
	if ((oldbitmap = (HBITMAP) SelectObject(m_hmemdc, m_membitmap)) == NULL)
		return;

	// Draw the cursor
	DrawIconEx(
		m_hmemdc,									// handle to device context 
		CursorPos.x, CursorPos.y,
		m_hcursor,									// handle to icon to draw 
		0,0,										// width of the icon 
		0,											// index of frame in animated cursor 
		NULL,										// handle to background brush 
		DI_NORMAL | DI_COMPAT						// icon-drawing flags 
		);

	// Select the old bitmap back into the memory DC
	SelectObject(m_hmemdc, oldbitmap);

	// Save the bounding rectangle
	m_cursorpos.tl = CursorPos;
	m_cursorpos.br = rfb::Point(GetSystemMetrics(SM_CXCURSOR),
		GetSystemMetrics(SM_CYCURSOR)).translate(CursorPos);

	// Clip the bounding rect to the screen
	// Copy the mouse cursor into the screen buffer, if any of it is visible
	m_cursorpos = m_cursorpos.intersect(m_bmrect);
	if (!m_cursorpos.is_empty()) {
		CopyToBuffer(m_cursorpos, scrBuff, scrBuffSize);
	}
}


// CURSOR HANDLING
// Obtain cursor image data in server's local format.
// The length of databuf[] should be at least (width * height * 4).
BOOL
vncDesktop::GetRichCursorData(BYTE *databuf, HCURSOR hcursor, int width, int height)
{
	// Protect the memory bitmap (is it really necessary here?)
	omni_mutex_lock l(m_update_lock);

	// Create bitmap, select it into memory DC
	HBITMAP membitmap = CreateCompatibleBitmap(m_hrootdc, width, height);
	if (membitmap == NULL) {
		return FALSE;
	}
	HBITMAP oldbitmap = (HBITMAP) SelectObject(m_hmemdc, membitmap);
	if (oldbitmap == NULL) {
		DeleteObject(membitmap);
		return FALSE;
	}

	// Draw the cursor
	DrawIconEx(m_hmemdc, 0, 0, hcursor, 0, 0, 0, NULL, DI_IMAGE);
	SelectObject(m_hmemdc, oldbitmap);

	// Prepare BITMAPINFO structure (copy most m_bminfo fields)
	int lines = 0;
	BITMAPINFO *bmi = (BITMAPINFO *)calloc(1, sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD));
	if(!bmi)
	{
		vnclog.Print(LL_INTERR, VNCLOG("calloc == NULL"));
	}
	else
	{
		memcpy(bmi, &m_bminfo.bmi, sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD));
		bmi->bmiHeader.biWidth = width;
		bmi->bmiHeader.biHeight = -height;

		// Clear data buffer and extract RGB data
		memset(databuf, 0x00, width * height * 4);
		lines = GetDIBits(m_hmemdc, membitmap, 0, height, databuf, bmi, DIB_RGB_COLORS);

		// Cleanup
		free(bmi);
	}
	DeleteObject(membitmap);

	return (lines != 0);
}

// Return the current mouse pointer position
rfb::Rect
vncDesktop::MouseRect()
{
	return m_cursorpos;
}

void
vncDesktop::SetCursor(HCURSOR cursor)
{
	if (cursor == NULL)
		m_hcursor = m_hdefcursor;
	else
	{
		m_hOldcursor = m_hcursor; // sf@2002
		m_hcursor = cursor;
	}
}

// Manipulation of the clipboard
void vncDesktop::SetClipText(char* rfbStr)
{
  int len = strlen(rfbStr);
  char* winStr = new char[len*2+1];

  int j = 0;
  for (int i = 0; i < len; i++)
  {
    if (rfbStr[i] == 10)
      winStr[j++] = 13;
    winStr[j++] = rfbStr[i];
  }
  winStr[j++] = 0;

  // Open the system clipboard
  if (OpenClipboard(m_hwnd))
  {
    // Empty it
    if (EmptyClipboard())
    {
      HANDLE hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, j);

      if (hMem != NULL)
      {
        LPSTR pMem = (char*)GlobalLock(hMem);

        // Get the data
        strcpy(pMem, winStr);

        // Tell the clipboard
        GlobalUnlock(hMem);
        SetClipboardData(CF_TEXT, hMem);
      }
    }
  }

  delete [] winStr;

  // Now close it
  CloseClipboard();
}

// INTERNAL METHODS

inline void
vncDesktop::MaskToMaxAndShift(DWORD mask, CARD16 &max, CARD8 &shift)
{
	for (shift = 0; (mask & 1) == 0; shift++)
		mask >>= 1;
	max = (CARD16) mask;
}

// Copy data from the memory bitmap into a buffer
void
vncDesktop::CopyToBuffer(const rfb::Rect &rect, BYTE *destbuff, UINT destbuffsize)
{
	// Finish drawing anything in this thread 
	// Wish we could do this for the whole system - maybe we should
	// do something with LockWindowUpdate here.
	GdiFlush();

	// Are we being asked to blit from the DIBsection to itself?
	if (destbuff == m_DIBbits) {
		// Yes.  Ignore the request!
		return;
	}

	int y_inv;
	BYTE * destbuffpos;

	// Calculate the scanline-ordered y position to copy from
	y_inv = m_scrinfo.framebufferHeight-rect.tl.y-(rect.br.y-rect.tl.y);

	// Calculate where in the output buffer to put the data
	destbuffpos = destbuff + (m_bytesPerRow * rect.tl.y);

	// Set the number of bytes for GetDIBits to actually write
	// NOTE : GetDIBits pads the destination buffer if biSizeImage < no. of bytes required
	m_bminfo.bmi.bmiHeader.biSizeImage = (rect.br.y-rect.tl.y) * m_bytesPerRow;

	// Get the actual bits from the bitmap into the bit buffer
	// If fast (DIBsection) blits are disabled then use the old GetDIBits technique
	if (m_DIBbits == NULL) {
		if (GetDIBits(m_hmemdc, m_membitmap, y_inv,
					(rect.br.y-rect.tl.y), destbuffpos,
					&m_bminfo.bmi, DIB_RGB_COLORS) == 0)
		{
#ifdef _MSC_VER
			_RPT1(_CRT_WARN, "vncDesktop : [1] GetDIBits failed! %d\n", GetLastError());
			_RPT3(_CRT_WARN, "vncDesktop : thread = %d, DC = %d, bitmap = %d\n", omni_thread::self(), m_hmemdc, m_membitmap);
			_RPT2(_CRT_WARN, "vncDesktop : y = %d, height = %d\n", y_inv, (rect.br.y-rect.tl.y));
#endif
		}
	} else {
		// Fast blits are enabled.  [I have a sneaking suspicion this will never get used, unless
		// something weird goes wrong in the code.  It's here to keep the function general, though!]

		int bytesPerPixel = m_scrinfo.format.bitsPerPixel / 8;
		BYTE *srcbuffpos = (BYTE*)m_DIBbits;

		srcbuffpos += (m_bytesPerRow * rect.tl.y) + (bytesPerPixel * rect.tl.x);
		destbuffpos += bytesPerPixel * rect.tl.x;

		int widthBytes = (rect.br.x-rect.tl.x) * bytesPerPixel;

		for(int y = rect.tl.y; y < rect.br.y; y++)
		{
			memcpy(destbuffpos, srcbuffpos, widthBytes);
			srcbuffpos += m_bytesPerRow;
			destbuffpos += m_bytesPerRow;
		}
	}
}

// Routine to find out which windows have moved
// If copyrect detection isn't perfect then this call returns
// the copyrect destination region, to allow the caller to check
// for mistakes
bool
vncDesktop::CalcCopyRects(rfb::UpdateTracker &tracker)
{
	HWND foreground = GetForegroundWindow();
	RECT foreground_rect;

	// Actually, we just compare the new and old foreground window & its position
	if (foreground != m_foreground_window) {
		m_foreground_window=foreground;
		// Is the window invisible or can we not get its rect?
		if (!IsWindowVisible(foreground) ||
			!GetWindowRect(foreground, &foreground_rect)) {
			//Buffer coordinates
			m_foreground_window_rect.clear();
		} else {
			foreground_rect.left-=m_ScreenOffsetx;
			foreground_rect.right-=m_ScreenOffsetx;
			foreground_rect.top-=m_ScreenOffsety;
			foreground_rect.bottom-=m_ScreenOffsety;
			m_foreground_window_rect = foreground_rect;
		}
	} else {
		// Same window is in the foreground - let's see if it's moved
		RECT destrect;
		rfb::Rect dest;
		rfb::Point source;

		// Get the window rectangle
		if (IsWindowVisible(foreground) && GetWindowRect(foreground, &destrect))
		{
			//screen to buffer coordinates
			destrect.left-=m_ScreenOffsetx;
			destrect.right-=m_ScreenOffsetx;
			destrect.top-=m_ScreenOffsety;
			destrect.bottom-=m_ScreenOffsety;

			rfb::Rect old_foreground_window_rect = m_foreground_window_rect;
			source = m_foreground_window_rect.tl;
			m_foreground_window_rect = dest = destrect;
			if (!dest.is_empty() && !old_foreground_window_rect.is_empty())
			{
				// Got the destination position.  Now send to clients!
				if (!source.equals(dest.tl))
				{
					rfb::Point delta;
					delta= rfb::Point(dest.tl.x-source.x, dest.tl.y-source.y);
				//	if (dest.tl.x-source.x==0 || dest.tl.y-source.y==0) return false;

					// Clip the destination rectangle
					dest = dest.intersect(m_bmrect);
					if (dest.is_empty()) return false;
					// Clip the source rectangle
					dest = dest.translate(delta.negate()).intersect(m_bmrect);
					m_buffer.ClearCacheRect(dest);
					dest = dest.translate(delta);
					m_buffer.ClearCacheRect(dest);
					if (!dest.is_empty()) {
						tracker.add_copied(dest, delta);
						return true;
					}
				}
			}
		} else {
			m_foreground_window_rect.clear();
		}
	}
	return false;
}

// Window procedure for the Desktop window
LRESULT CALLBACK
DesktopWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
	vncDesktop *_this = (vncDesktop*)GetWindowLong(hwnd, GWL_USERDATA);

	switch (iMsg)
	{
	///ddihook
	case WM_SYSCOMMAND:
		// User has clicked an item on the tray menu
		switch (wParam)
		{
			case SC_MONITORPOWER:
				vnclog.Print(LL_INTINFO, VNCLOG("Monitor2 %i"),lParam);
		}
		vnclog.Print(LL_INTINFO, VNCLOG("Monitor3 %i %i"),wParam,lParam);
		return DefWindowProc(hwnd, iMsg, wParam, lParam);
	case WM_POWER:
	case WM_POWERBROADCAST:
		// User has clicked an item on the tray menu
		switch (wParam)
		{
			case SC_MONITORPOWER:
				vnclog.Print(LL_INTINFO, VNCLOG("Monitor2 %i"),lParam);
		}
		vnclog.Print(LL_INTINFO, VNCLOG("Power3 %i %i"),wParam,lParam);
		return DefWindowProc(hwnd, iMsg, wParam, lParam);

	case WM_COPYDATA:
			_this->pMyCDS= (PCOPYDATASTRUCT) lParam;
			if (_this->pMyCDS->dwData==112233)
			{
					DWORD mysize=_this->pMyCDS->cbData;
					char mytext[1024];
					char *myptr;
					char split[4][6];
					strcpy(mytext,(LPCSTR)_this->pMyCDS->lpData);
					myptr=mytext;
					for (int j =0; j<(mysize/20);j++)
					{
						for (int i=0;i<4;i++)
							{
								strcpy(split[i],"     ");
								strncpy(split[i],myptr,4);
								myptr=myptr+5;
							}
						_this->QueueRect(rfb::Rect(atoi(split[0]), atoi(split[1]), atoi(split[2]), atoi(split[3])));
					}
					
			}
			//vnclog.Print(LL_INTINFO, VNCLOG("copydata"));	
			return 0;

	// GENERAL

	case WM_DISPLAYCHANGE:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -