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

📄 vncdesktop.cpp

📁 Web VNC samples delphi
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	// Save the bounding rectangle
	m_cursorpos.left = CursorPos.x;
	m_cursorpos.top = CursorPos.y;
	m_cursorpos.right = CursorPos.x + GetSystemMetrics(SM_CXCURSOR);
	m_cursorpos.bottom = CursorPos.y + GetSystemMetrics(SM_CYCURSOR);
}

// Add the mouse pointer to the buffer
void vncDesktop::CaptureMouse(BYTE *scrBuff, UINT scrBuffSize)
{
	// Protect the memory bitmap
	omni_mutex_lock l(m_bitbltlock);

	CaptureMouseRect();

	// 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 
		m_cursorpos.left - m_bmrect.left,
		m_cursorpos.top - m_bmrect.top,
		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									// icon-drawing flags 
		);

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

	// Clip the bounding rect to the screen
	RECT screen = m_server->GetSharedRect();
	// Copy the mouse cursor into the screen buffer, if any of it is visible
	if (IntersectRect(&m_cursorpos, &m_cursorpos, &screen))
		CopyToBuffer(m_cursorpos, scrBuff);
}

// 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_bitbltlock);

	// 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)
	BITMAPINFO *bmi = (BITMAPINFO *)calloc(1, sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD));
	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);
	int 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
RECT
vncDesktop::MouseRect()
{
	return m_cursorpos;
}

void vncDesktop::SetCursor(HCURSOR cursor)
{
	if (cursor == NULL)
		m_hcursor = m_hdefcursor;
	else
		m_hcursor = cursor;
}

//
// DEBUG: Some visualization for LF->CRLF conversion code.
//
/*
static void ShowClipText(char *caption, char *text)
{
	int len = strlen(text);
	char *out_text = new char[len * 4 + 8];
	int pos = 0;

	out_text[pos++] = '"';
	for (int i = 0; i < len; i++) {
		if (text[i] == '\r') {
			strcpy(&out_text[pos], "\\r");
			pos += 2;
		} else if (text[i] == '\n') {
			strcpy(&out_text[pos], "\\n");
			pos += 2;
		} else if (text[i] < ' ') {
			strcpy(&out_text[pos], "\\?");
			pos += 2;
		} else {
			out_text[pos++] = text[i];
		}
	}
	out_text[pos++] = '"';
	out_text[pos++] = '\0';

	MessageBox(NULL, out_text, caption, MB_OK);

	delete[] out_text;
}
*/

//
// Convert text from Unix (LF only) format to CR+LF.
// NOTE: The size of dst[] buffer must be at least (strlen(src) * 2 + 1).
//

void
vncDesktop::ConvertClipText(char *dst, const char *src)
{
	const char *ptr0 = src;
	const char *ptr1;
	int dst_pos = 0;

	while ((ptr1 = strchr(ptr0, '\n')) != NULL) {
		// Copy the string before the LF
		if (ptr1 != ptr0) {
			memcpy(&dst[dst_pos], ptr0, ptr1 - ptr0);
			dst_pos += ptr1 - ptr0;
		}
		// Don't insert CR if there is one already
		if (ptr1 == ptr0 || *(ptr1 - 1) != '\r') {
			dst[dst_pos++] = '\r';
		}
		// Append LF
		dst[dst_pos++] = '\n';
		// Next position in the source text
		ptr0 = ptr1 + 1;
	}
	// Copy the last string with no LF, but with '\0'
	memcpy(&dst[dst_pos], ptr0, &src[strlen(src)] - ptr0 + 1);
}

//
// Manipulation of the clipboard
//

void
vncDesktop::SetClipText(LPSTR text)
{
	// Open the system clipboard
	if (OpenClipboard(m_hwnd))
	{
		// Empty it
		if (EmptyClipboard())
		{
			HANDLE hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,
									  strlen(text) * 2 + 1);

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

				// Get the data (with line endings converted to CR+LF)
				ConvertClipText(pMem, text);

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

	// 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(RECT rect, BYTE *destbuff)
{
	// Are we being asked to blit from the DIBsection to itself?
	if (destbuff == m_DIBbits)
	{
		// Yes.  Ignore the request!
		return;
	}

	// Protect the memory bitmap
	omni_mutex_lock l(m_bitbltlock);

	const int crect_re_vd_left = rect.left - m_bmrect.left;
	const int crect_re_vd_top = rect.top - m_bmrect.top;
	_ASSERTE(crect_re_vd_left >= 0);
	_ASSERTE(crect_re_vd_top >= 0);

	// Calculate the scanline-ordered y position to copy from
// NB: m_membitmap is bottom2top
	const int y_inv_re_vd = m_bmrect.bottom - m_bmrect.top - rect.bottom;
	_ASSERTE(y_inv_re_vd >= 0);

	// Calculate where in the output buffer to put the data
	BYTE * destbuffpos = destbuff + (m_bytesPerRow * crect_re_vd_top);

	// 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.bottom-rect.top) * 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_re_vd,
			rect.bottom - rect.top,
			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_re_vd, (rect.bottom-rect.top));
#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!]

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

		srcbuffpos += (m_bytesPerRow * crect_re_vd_top) + (bytesPerPixel * crect_re_vd_left);
		destbuffpos += bytesPerPixel * crect_re_vd_left;

		const int widthBytes = (rect.right - rect.left) * bytesPerPixel;

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

void vncDesktop::CopyToBuffer(RECT rect, BYTE *destbuff, const BYTE *srcbuffpos)
{
	const int crect_re_vd_left = rect.left - m_bmrect.left;
	const int crect_re_vd_top = rect.top - m_bmrect.top;
	_ASSERTE(crect_re_vd_left >= 0);
	_ASSERTE(crect_re_vd_top >= 0);

	const int bytesPerPixel = m_scrinfo.format.bitsPerPixel / 8;

	const int bmoffset = (m_bytesPerRow * crect_re_vd_top) + (bytesPerPixel * crect_re_vd_left);
	BYTE *destbuffpos = destbuff + bmoffset;
	srcbuffpos += bmoffset;

	const int widthBytes = (rect.right - rect.left) * bytesPerPixel;

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

// Callback routine used internally to catch window movement...
BOOL CALLBACK
EnumWindowsFnCopyRect(HWND hwnd, LPARAM arg)
{

	//For excluding the popup windows
	if ((GetWindowLong( hwnd, GWL_STYLE) & WS_POPUP) ==0)
	{
	
		HANDLE prop = GetProp(hwnd, (LPCTSTR) MAKELONG(VNC_WINDOWPOS_ATOM, 0));
		if (prop != NULL) {
			
			if (IsWindowVisible(hwnd)) {
				
				RECT dest;
				POINT source;

				// Get the window rectangle
				if (GetWindowRect(hwnd, &dest)) {
					// Old position
					source.x = (SHORT) LOWORD(prop);
					source.y = (SHORT) HIWORD(prop);

					// Got the destination position.  Now send to clients!
					if ((source.x != dest.left) || (source.y != dest.top)) {
						// Update the property entry
						SHORT x = (SHORT) dest.left;
						SHORT y = (SHORT) dest.top;
						SetProp(hwnd,
							(LPCTSTR) MAKELONG(VNC_WINDOWPOS_ATOM, 0),
							(HANDLE) MAKELONG(x, y));

						// Store of the copyrect 
						((vncDesktop*)arg)->CopyRect(dest, source);
						
					}
				} else {
					RemoveProp(hwnd, (LPCTSTR) MAKELONG(VNC_WINDOWPOS_ATOM, 0));
				}
			} else {
				RemoveProp(hwnd, (LPCTSTR) MAKELONG(VNC_WINDOWPOS_ATOM, 0));
			}
		} else {
			// If the window has become visible then save its position!
			if (IsWindowVisible(hwnd)) {
				RECT dest;

				if (GetWindowRect(hwnd, &dest)) {
					SHORT x = (SHORT) dest.left;
					SHORT y = (SHORT) dest.top;
					SetProp(hwnd,
						(LPCTSTR) MAKELONG(VNC_WINDOWPOS_ATOM, 0),
						(HANDLE) MAKELONG(x, y));
				}
			}
		}
	}
	return TRUE;
}


void
vncDesktop::SetLocalInputDisableHook(BOOL enable)
{
	SetKeyboardFilterHook(enable);
	SetMouseFilterHook(enable);
}

void
vncDesktop::SetLocalInputPriorityHook(BOOL enable)
{
	if (vncService::IsWin95()) {
		SetKeyboardPriorityHook(m_hwnd,enable,RFB_LOCAL_KEYBOARD);
		SetMousePriorityHook(m_hwnd,enable,RFB_LOCAL_MOUSE);
	} else {
		SetKeyboardPriorityLLHook(m_hwnd,enable,RFB_LOCAL_KEYBOARD);
		SetMousePriorityLLHook(m_hwnd,enable,RFB_LOCAL_MOUSE);
	}

	if (!enable)
// FIXME: incremental semantics broken here;
// that's why we're compelled to consume extra unlocks
		m_server->BlockRemoteInput(false);
}

// Routine to find out which windows have moved
void
vncDesktop::CalcCopyRects()
{
	// Enumerate all the desktop windows for movement
	EnumWindows((WNDENUMPROC)EnumWindowsFnCopyRect, (LPARAM) this);
}


// 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)
	{

		// GENERAL

	case WM_DISPLAYCHANGE:
		// The display resolution is changing

		// We must kick off any clients since their screen size will be wrong
		_this->m_displaychanged = TRUE;
		return 0;

	case WM_SYSCOLORCHANGE:
	case WM_PALETTECHANGED:
		// The palette colours have changed, so tell the server

		// Get the system palette
		if (!_this->SetPalette())
			PostQuitMessage(0);
		// Update any palette-based clients, too
		_this->m_server->UpdatePalette();
		return 0;

	case WM_TIMER:
		switch (wParam) {
		case vncDesktop::TIMER_POLL:
			_this->SetPollingFlag(true);
			break;
		case vncDesktop::TIMER_BLANK_SCREEN:
			if (_this->m_server->GetBlankScreen())
				_this->BlankScreen(TRUE);
			break;
		case vncDesktop::TIMER_RESTORE_SCREEN:
			_this->BlankScreen(FALSE);
			break;
		}
		return 0;

		// CLIPBOARD MESSAGES

	case WM_CHANGECBCHAIN:
		// The clipboard chain has changed - check our nextviewer handle
		if ((HWND)wParam == _this->m_hnextviewer)
			_this->m_hnextviewer = (HWND)lParam;
		else
			if (_this->m_hnextviewer != NULL)
				SendMessage(_this->m_hnextviewer,
							WM_CHANGECBCHAIN,
							wParam, lParam);

		return 0;

	case WM_DRAWCLIPBOARD:
		// The clipboard contents have changed
		if((GetClipboardOwner() != _this->Window()) &&
		    _this->m_initialClipBoardSeen &&
			_this->m_clipboard_active)
		{
			LPSTR cliptext = NULL;

			// Open the clipboard
			if (OpenClipboard(_this->Window()))
			{
				// Get the clipboard data
				HGLOBAL cliphandle = GetClipboardData(CF_TEXT);
				if (cliphandle != NULL)
				{
					LPSTR clipdata = (LPSTR) GlobalLock(cliphandle);

					// Copy it into a new buffer
					if (clipdata == NULL)
						cliptext = NULL;
					else
						cliptext = strdup(clipdata);

					// Release the buffer and close the clipboard
					GlobalUnlock(cliphandle);
				}

				CloseClipboard();
			}

			if (cliptext != NULL)
			{
				int cliplen = strlen(cliptext);
				LPSTR unixtext = (char *)malloc(cliplen+1);

				// Replace CR-LF with LF - never send CR-LF on the wire,
				// since Unix won't like it
				int unixpos=0;

⌨️ 快捷键说明

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