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

📄 vnckeymap.cpp

📁 teamviewer source code vc++
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		for (int i = 0; i < sizeof(keymap) / sizeof(keymap_t); i++) 
		{
			vkMap[keymap[i].keysym] = keymap[i].vk;
			extendedMap[keymap[i].keysym] = keymap[i].extended;
		}

		// Find dead characters for the current keyboard layout
		// XXX how could we handle the keyboard layout changing?
		BYTE keystate[256];
		memset(keystate, 0, 256);
		for (int j = 0; j < sizeof(latin1DeadChars); j++) 
		{
			SHORT s = VkKeyScan(latin1DeadChars[j]);
			if (s != -1) 
			{
				//rdr::U8 chars[2];		// a 2 Byte buffer seems to be to small, so I changed it to 2 WORD
				WORD chars[2];
				UINT vkCode = LOBYTE(s);
				BYTE modifierState = HIBYTE(s);
				keystate[VK_SHIFT] = (modifierState & 1) ? 0x80 : 0;
				keystate[VK_CONTROL] = (modifierState & 2) ? 0x80 : 0;
				keystate[VK_MENU] = (modifierState & 4) ? 0x80 : 0;
				int nchars = ToAscii(vkCode, 0, keystate, (LPWORD)chars, 0);
				if (nchars < 0) 
				{
					deadChars.push_back(latin1DeadChars[j]);

					// warning!: though the spacing version is returned, the non-spacing
					// version is still in the keyboard buffer, therefore it's recommended
					// to call ToAscii again with a non-dead key to form a combined character.
					// (as this will remove the deadkey from the keyb buffer)
					ToAscii(vkCode, 0, keystate, (LPWORD)chars, 0); //
				}
			}
		}
	}

	void keyEvent(rdr::U32 keysym, bool down)
	{
		vnclog.Print(LL_INTWARN, VNCLOG("keysym 0x%x down=%d"), keysym, down);
		if (keysym>=XK_dead_grave && keysym<=XK_dead_doublequote)
		{
			if(!down)
				return;
			if(keysymDead==0)
			{
				keysymDead=keysym;
				return;
			}
		}

		if ((keysym >= 32 && keysym <= 126) ||
			(keysym >= 160 && keysym <= 255) || 
			(keysym>=XK_dead_grave && keysym<=XK_dead_doublequote))
		{
			if (keysymDead!=0 && down)
			{
				rdr::U32 keysymold = keysym;
				//vnclog.Print(LL_INTWARN, VNCLOG(" Compose dead 0x%x 0x%x"),keysymDead,keysym);
				switch (keysymDead)
				{
				case XK_dead_grave:
					switch(keysym)
					{
					case XK_A: keysym=XK_Agrave;break;
					case XK_E: keysym=XK_Egrave;break;
					case XK_I: keysym=XK_Igrave;break;
					case XK_O: keysym=XK_Ograve;break;
					case XK_U: keysym=XK_Ugrave;break;
					case XK_a: keysym=XK_agrave;break;
					case XK_e: keysym=XK_egrave;break;
					case XK_i: keysym=XK_igrave;break;
					case XK_o: keysym=XK_ograve;break;
					case XK_u: keysym=XK_ugrave;break;
					}
					break;
				case XK_dead_acute:
				case XK_dead_quote:
					switch(keysym)
					{
					case XK_A: keysym=XK_Aacute;break;
					case XK_E: keysym=XK_Eacute;break;
					case XK_I: keysym=XK_Iacute;break;
					case XK_O: keysym=XK_Oacute;break;
					case XK_U: keysym=XK_Uacute;break;
					case XK_a: keysym=XK_aacute;break;
					case XK_e: keysym=XK_eacute;break;
					case XK_i: keysym=XK_iacute;break;
					case XK_o: keysym=XK_oacute;break;
					case XK_u: keysym=XK_uacute;break;
					case XK_y: keysym=XK_yacute;break;
					case XK_Y: keysym=XK_Yacute;break;
					}
					break;
				case XK_dead_circumflex:
					switch(keysym)
					{
					case XK_A: keysym=XK_Acircumflex;break;
					case XK_E: keysym=XK_Ecircumflex;break;
					case XK_I: keysym=XK_Icircumflex;break;
					case XK_O: keysym=XK_Ocircumflex;break;
					case XK_U: keysym=XK_Ucircumflex;break;
					case XK_a: keysym=XK_acircumflex;break;
					case XK_e: keysym=XK_ecircumflex;break;
					case XK_i: keysym=XK_icircumflex;break;
					case XK_o: keysym=XK_ocircumflex;break;
					case XK_u: keysym=XK_ucircumflex;break;
					}
					break;
				case XK_dead_tilde:
					switch(keysym)
					{
					case XK_A : keysym=XK_Atilde;break;
					case XK_N : keysym=XK_Ntilde;break;
					case XK_O : keysym=XK_Otilde;break;
					case XK_a : keysym=XK_atilde;break;
					case XK_n : keysym=XK_ntilde;break;
					case XK_o : keysym=XK_otilde;break;
					}
					break;
				case XK_dead_diaeresis:
				case XK_dead_doublequote:
					switch(keysym)
					{
					case XK_A: keysym=XK_Adiaeresis;break;
					case XK_E: keysym=XK_Ediaeresis;break;
					case XK_I: keysym=XK_Idiaeresis;break;
					case XK_O: keysym=XK_Odiaeresis;break;
					case XK_U: keysym=XK_Udiaeresis;break;
					case XK_a: keysym=XK_adiaeresis;break;
					case XK_e: keysym=XK_ediaeresis;break;
					case XK_i: keysym=XK_idiaeresis;break;
					case XK_o: keysym=XK_odiaeresis;break;
					case XK_u: keysym=XK_udiaeresis;break;
					case XK_y: keysym=XK_ydiaeresis;break;
					}
					break;
				case XK_dead_cedilla:
					switch(keysym)
					{
					case XK_C: keysym=XK_Ccedilla;break;
					case XK_c: keysym=XK_ccedilla;break;
					}
					break;
				}
				if(keysym == keysymold)						// not a composed key
				{
					doKeyPress(makeUndead(keysymDead), true);
					if(keysym == XK_space)					// do not print space after not composed dead char
						keysym = 0;	
					else 
						keysym = makeUndead(keysym);		
				}
				keysymDead=0;
			}
			doKeyPress(keysym, down);
		} 
		else 
		{
			// see if it's a recognised keyboard key, otherwise ignore it

			if (vkMap.find(keysym) == vkMap.end()) 
			{
				vnclog.Print(LL_INTWARN, VNCLOG("ignoring unknown keysym %d"),keysym);
				return;
			}
			BYTE vkCode = vkMap[keysym];
			DWORD flags = 0;
			if (extendedMap[keysym]) flags |= KEYEVENTF_EXTENDEDKEY;
			if (!down) flags |= KEYEVENTF_KEYUP;

			//      vnclog.Print(LL_INTINFO,
			//                "keyboard key: keysym %d(0x%x) vkCode 0x%x ext %d down %d\n",
			//               keysym, keysym, vkCode, extendedMap[keysym], down);

			if (down && (vkCode == VK_DELETE) &&
				((GetAsyncKeyState(VK_CONTROL) & 0x8000) != 0) &&
				((GetAsyncKeyState(VK_MENU) & 0x8000) != 0) &&
				vncService::IsWinNT())
			{
				vncService::SimulateCtrlAltDel();
				return;
			}

			if (vncService::IsWin95()) 
			{
				switch (vkCode) 
				{
					case VK_RSHIFT:   vkCode = VK_SHIFT;   break;
					case VK_RCONTROL: vkCode = VK_CONTROL; break;
					case VK_RMENU:    vkCode = VK_MENU;    break;
				}
			}
			doKeyboardEvent(vkCode, flags);
		}
	}

private:
	void doKeyPress(rdr::U32 keysym, bool down);
	rdr::U32 makeUndead(rdr::U32 key)
	{
		switch(key)						// so simulate the dead key as a normal keypress
		{
		case XK_dead_grave:
			return XK_grave;
		case XK_dead_acute: 
			return XK_acute;
		case XK_dead_circumflex:
			return XK_asciicircum;
		case XK_dead_tilde:
			return XK_asciitilde;
		case XK_dead_diaeresis:
			return XK_diaeresis;
		case XK_dead_cedilla:
			return XK_cedilla;
		case XK_dead_quote:
			return XK_apostrophe;
		case XK_dead_doublequote:
			return XK_quotedbl;
		default:
			return key;
		}
	}

  std::map<rdr::U32,rdr::U8> vkMap;
  std::map<rdr::U32,bool> extendedMap;
} key_mapper;

void Keymapper::doKeyPress(rdr::U32 keysym, bool down)
{
	if(keysym == 0)
		return;

vnclog.Print(LL_INTINFO, VNCLOG("doKeyPress %x, %d"), keysym, down);

	SHORT s = VkKeyScan(keysym);
vnclog.Print(LL_INTWARN, VNCLOG(" SHORT s %i"),s);
	bool undead = false;
	for (int j = 0; j < deadChars.size(); j++) 
		if(keysym == deadChars[j]) undead = true;

	if (s == -1 || undead)
	{	 
		if (down) 
		{
			//vnclog.Print(LL_INTWARN, VNCLOG("down"));
			// not a single keypress - try synthesizing dead chars.
			{
				bool initialzero = false;
				int ascii=0;
				if(keysym >= 0xa0 && keysym <= 0xff)
				{
					// map to latin1
					initialzero = true;
					ascii = keysym;
				}
				else
				{
					for (ascii=0;ascii<256;ascii++)						//Lookup ascii representation
					{
						if (keysym==ascii_to_x[ascii]) break;
					}
				}
				//vnclog.Print(LL_INTINFO, VNCLOG("simulating %s%d"), initialzero ? "0":"", ascii);
				rdr::U8 a0=ascii/100;
				ascii=ascii%100;
				rdr::U8 a1=ascii/10;
				ascii=ascii%10;
				rdr::U8 a2=ascii;
				if (ascii!=256)
				{
					KeyStateModifier shift(VK_SHIFT);
					shift.release();
					KeyStateModifier lshift(VK_LSHIFT);
					lshift.release();
					KeyStateModifier rshift(VK_RSHIFT);
					rshift.release();
					keybd_event(VK_MENU,MapVirtualKey( VK_MENU, 0 ), 0 ,0);
					if(initialzero)									// enter 0xxx on the numpad -> use latin1
					{												// instead of 850
						keybd_event(VK_NUMPAD0+a0, MapVirtualKey(VK_NUMPAD0, 0), 0, 0);
						keybd_event(VK_NUMPAD0+a0, MapVirtualKey(VK_NUMPAD0, 0),KEYEVENTF_KEYUP,0);
					}
					keybd_event(VK_NUMPAD0+a0, MapVirtualKey(VK_NUMPAD0+a0, 0), 0, 0);
					keybd_event(VK_NUMPAD0+a0, MapVirtualKey(VK_NUMPAD0+a0, 0),KEYEVENTF_KEYUP,0);
					keybd_event(VK_NUMPAD0+a1, MapVirtualKey(VK_NUMPAD0+a1, 0),0,0);
					keybd_event(VK_NUMPAD0+a1, MapVirtualKey(VK_NUMPAD0+a1, 0),KEYEVENTF_KEYUP, 0);
					keybd_event(VK_NUMPAD0+a2, MapVirtualKey(VK_NUMPAD0+a2, 0) ,0, 0);
					keybd_event(VK_NUMPAD0+a2, MapVirtualKey(VK_NUMPAD0+a2, 0),KEYEVENTF_KEYUP, 0);
					keybd_event(VK_MENU, MapVirtualKey( VK_MENU, 0 ),KEYEVENTF_KEYUP, 0);
					return;
				}
				else
					vnclog.Print(LL_INTWARN, VNCLOG("ignoring unrecognised Latin-1 keysym 0x%x"),keysym);
			}
		}
		return;
	}

	BYTE vkCode = LOBYTE(s);

	KeyStateModifier ctrl(VK_CONTROL);
	KeyStateModifier alt(VK_MENU);
	KeyStateModifier shift(VK_SHIFT);
	KeyStateModifier lshift(VK_LSHIFT);
	KeyStateModifier rshift(VK_RSHIFT);

	if (down) 
	{
		BYTE modifierState = HIBYTE(s);
		if (modifierState & 2) ctrl.press();
		if (modifierState & 4) alt.press();
		if (modifierState & 1) 
		{
			shift.press(); 
		} 
		else 
		{
			if (vncService::IsWin95()) 
			{
				shift.release();
			} 
			else 
			{
				lshift.release();
				rshift.release();
			}
		}
	}
	//vnclog.Print(LL_INTINFO,
	//             "latin-1 key: keysym %d(0x%x) vkCode 0x%x down %d\n",
	//             keysym, keysym, vkCode, down);
	doKeyboardEvent(vkCode, down ? 0 : KEYEVENTF_KEYUP);

}


void vncKeymap::keyEvent(CARD32 keysym, bool down)
{
  key_mapper.keyEvent(keysym, down);
}



void
SetShiftState(BYTE key, BOOL down)
{
	BOOL keystate = (GetAsyncKeyState(key) & 0x8000) != 0;

	// This routine sets the specified key to the desired value (up or down)
	if ((keystate && down) || ((!keystate) && (!down)))
		return;

	vnclog.Print(LL_INTINFO,
		VNCLOG("setshiftstate %d - (%s->%s)"),
		key, keystate ? "down" : "up",
		down ? "down" : "up");

	// Now send a key event to set the key to the new value
	doKeyboardEvent(key, down ? 0 : KEYEVENTF_KEYUP);
	keystate = (GetAsyncKeyState(key) & 0x8000) != 0;

	vnclog.Print(LL_INTINFO,
		VNCLOG("new state %d (%s)"),
		key, keystate ? "down" : "up");
}

void
vncKeymap::ClearShiftKeys()
{
	if (vncService::IsWinNT())
	{
		// On NT, clear both sets of keys

		// LEFT
		SetShiftState(VK_LSHIFT, FALSE);
		SetShiftState(VK_LCONTROL, FALSE);
		SetShiftState(VK_LMENU, FALSE);

		// RIGHT
		SetShiftState(VK_RSHIFT, FALSE);
		SetShiftState(VK_RCONTROL, FALSE);
		SetShiftState(VK_RMENU, FALSE);
	}
	else
	{
		// Otherwise, we can't distinguish the keys anyway...

		// Clear the shift key states
		SetShiftState(VK_SHIFT, FALSE);
		SetShiftState(VK_CONTROL, FALSE);
		SetShiftState(VK_MENU, FALSE);
	}
}

⌨️ 快捷键说明

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