QT实现远程桌面共享与控制 文章转发
- 时间:2022-07-09
- 浏览:
//被控端 发送截屏
void MainWindow::startTransfer()
{
QDataStream sendOut(&outBlock, QIODevice::WriteOnly);
sendOut.setVersion(QDataStream::Qt_5_6);
//获取屏幕截图
pixbuf=screen->grabWindow(QApplication::desktop()->winId());
//转为base64数据
QImage image =pixbuf.toImage();
QString imageData = getImageData(image);
// 保留总大小信息空间、图像大小信息空间,然后输入图像信息
sendOut << qint64(0) << qint64(0) << imageData;
// 这里的总大小是总大小信息、图像大小信息和实际图像信息的总和
totalBytes_send += outBlock.size();
sendOut.device()->seek(0);
// 返回outBolock的开始,用实际的大小信息代替两个qint64(0)空间
sendOut << totalBytes_send << qint64((outBlock.size() - sizeof(qint64)*2));
//发出readyRead()信号
tcpServerConnection->write(outBlock);
outBlock.resize(0);
totalBytes_send = 0;
}
//控制端更新屏幕
void showWin::updateShowLb()
{
//用数据流的方式读取
QDataStream in(tcpClient);
in.setVersion(QDataStream::Qt_5_6);
// 如果已接收到的数据小于16个字节,保存到来的文件头结构
if (bytesReceived <= sizeof(qint64)*2)
{
if((tcpClient->bytesAvailable() >= sizeof(qint64)*2)&& (imageSize == 0))
{
// 接收数据总大小信息和文件名大小信息
in >> totalBytes >> imageSize;
bytesReceived += sizeof(qint64) * 2;
if(imageSize == 0)
ui->label_show->setText(tr("显示的图片为空!"));
}
if((tcpClient->bytesAvailable() >= imageSize)&& (imageSize != 0))
{
// 接收图片内容
in >> imageContent;
QImage imageData = getImage(imageContent);
QPixmap resImage = QPixmap::fromImage(imageData);
QPixmap* imgPointer = &resImage;
imgPointer->scaled(ui->label_show->size(), Qt::IgnoreAspectRatio);//重新调整图像大小以适应窗口
ui->label_show->setScaledContents(true);//设置label的属性,能够缩放pixmap充满整个可用的空间。
ui->label_show->setPixmap(*imgPointer);
bytesReceived += imageSize;
//接收图片成功
if(bytesReceived == totalBytes)
{
//发送一个确认
tcpClient->write("1");
totalBytes = 0;
bytesReceived = 0;
imageSize = 0;
}
}
}
}
/*键盘按下*/
void CmdThread::cmdKeyPress(QKeyEvent *e)
{
uchar uc[16];
uc[0] = CMD_KEY_PRESS;
uc[1] = translateKey(e->key());
uc[2] = Find_Key_linux(uc[1]);
qDebug()<<uc[1]<<uc[2];
writeAndBlock(cmdSocket, uc, 16);
e->ignore();
}
/*键盘释放*/
void CmdThread::cmdKeyRelease(QKeyEvent *e)
{
uchar uc[16];
uc[0] = CMD_KEY_RELEASE;
uc[1] = translateKey(e->key());//Windows端使用的字段
uc[2] = Find_Key_linux(uc[1]); //Linux端使用的字段
writeAndBlock(cmdSocket, uc, 16);
e->ignore();
}
//鼠标移动
void CmdThread::cmdMouseMoveTo(int x, int y,int frameWidth,int frameHeight)
{
uchar uc[16];
uc[0] = CMD_MOUSE_MOVE_TO;
setUchar( x, y, frameWidth, frameHeight, uc);
writeAndBlock(cmdSocket, uc, 16);
}
//鼠标左键按下
void CmdThread::cmdMouseLeftDown(int x, int y,int frameWidth,int frameHeight)
{
uchar uc[16];
uc[0] = CMD_MOUSE_LEFT_DOWN;
setUchar( x, y, frameWidth, frameHeight, uc);
writeAndBlock(cmdSocket, uc, 16);
}
//鼠标左键释放
void CmdThread::cmdMouseLeftUp(int x, int y,int frameWidth,int frameHeight)
{
uchar uc[16];
uc[0] = CMD_MOUSE_LEFT_UP;
setUchar( x, y, frameWidth, frameHeight, uc);
writeAndBlock(cmdSocket, uc, 16);
}
//鼠标右键按下
void CmdThread::cmdMouseRightDown(int x, int y,int frameWidth,int frameHeight)
{
uchar uc[16];
uc[0] = CMD_MOUSE_RIGHT_DOWN;
setUchar( x, y, frameWidth, frameHeight, uc);
writeAndBlock(cmdSocket, uc, 16);
}
//鼠标右键释放
void CmdThread::cmdMouseRightUp(int x, int y,int frameWidth,int frameHeight)
{
uchar uc[16];
uc[0] = CMD_MOUSE_RIGHT_UP;
setUchar( x, y, frameWidth, frameHeight, uc);
writeAndBlock(cmdSocket, uc, 16);
}
//鼠标滚轮事件
void CmdThread::cmdMouseWheel(int delta, int x, int y,int frameWidth,int frameHeight)
{
uchar uc[16];
uc[0] = CMD_MOUSE_WHEEL;
setUchar( x, y, frameWidth, frameHeight, uc);
//滚轮的数据,先除以256,再保留余数
uc[11] = delta / 0x100;
uc[12] = delta % 0x100;
//uc[13]用来判断delta的正负,负数为0,非负为1
uc[13] = delta < 0 ? 0 : 1;
writeAndBlock(cmdSocket, uc, 16);
}
对于鼠标来说,需要获取鼠标在界面上点击的相对位置以及滚轮滚动的角度等。对于键盘就只需要获取键值,但是QT与Windows及Linux对键盘的键值对应是不同的,这里采用一个Map保存好QT与Windows以及QT与Linux的键值对应关系。 //查找Linux下的键值 uchar CmdThread::Find_Key_linux(int key) { //Linux与Windows的键盘映射表<Windows,Linux> QMap<int,uchar> LinuxAndWindows_KeyMap; LinuxAndWindows_KeyMap.insert(8,14);//KEY_BACKSPACE LinuxAndWindows_KeyMap.insert(9,15);//KEY_TAB LinuxAndWindows_KeyMap.insert(13,28);//KEY_ENTER LinuxAndWindows_KeyMap.insert(16,42);//KEY_LEFTSHIFT LinuxAndWindows_KeyMap.insert(17,29);//KEY_LEFTCTRL LinuxAndWindows_KeyMap.insert(27,1);//KEY_ESC LinuxAndWindows_KeyMap.insert(32,57);//KEY_SPACE LinuxAndWindows_KeyMap.insert(37,125);//KEY_LEFT LinuxAndWindows_KeyMap.insert(38,103);//KEY_UP LinuxAndWindows_KeyMap.insert(39,126);//KEY_RIGHT LinuxAndWindows_KeyMap.insert(40,108);//KEY_DOWN LinuxAndWindows_KeyMap.insert(190,52);//KEY_DOT LinuxAndWindows_KeyMap.insert(46,52);//KEY_DOT LinuxAndWindows_KeyMap.insert(48,11);//KEY_0 LinuxAndWindows_KeyMap.insert(49,2);//KEY_1 LinuxAndWindows_KeyMap.insert(50,3);//KEY_2 LinuxAndWindows_KeyMap.insert(51,4);//KEY_3 LinuxAndWindows_KeyMap.insert(52,5);//KEY_4 LinuxAndWindows_KeyMap.insert(53,6);//KEY_5 LinuxAndWindows_KeyMap.insert(54,7);//KEY_6 LinuxAndWindows_KeyMap.insert(55,8);//KEY_7 LinuxAndWindows_KeyMap.insert(56,9);//KEY_8 LinuxAndWindows_KeyMap.insert(57,10);//KEY_9 LinuxAndWindows_KeyMap.insert(65,30);//KEY_A LinuxAndWindows_KeyMap.insert(66,48);//KEY_B LinuxAndWindows_KeyMap.insert(67,46);//KEY_C LinuxAndWindows_KeyMap.insert(68,32);//KEY_D LinuxAndWindows_KeyMap.insert(69,18);//KEY_E LinuxAndWindows_KeyMap.insert(70,33);//KEY_F LinuxAndWindows_KeyMap.insert(71,34);//KEY_G LinuxAndWindows_KeyMap.insert(72,35);//KEY_H LinuxAndWindows_KeyMap.insert(73,23);//KEY_I LinuxAndWindows_KeyMap.insert(74,36);//KEY_J LinuxAndWindows_KeyMap.insert(75,37);//KEY_K LinuxAndWindows_KeyMap.insert(76,38);//KEY_L LinuxAndWindows_KeyMap.insert(77,50);//KEY_M LinuxAndWindows_KeyMap.insert(78,49);//KEY_N LinuxAndWindows_KeyMap.insert(79,24);//KEY_O LinuxAndWindows_KeyMap.insert(80,25);//KEY_P LinuxAndWindows_KeyMap.insert(81,16);//KEY_Q LinuxAndWindows_KeyMap.insert(82,19);//KEY_R LinuxAndWindows_KeyMap.insert(83,31);//KEY_S LinuxAndWindows_KeyMap.insert(84,20);//KEY_T LinuxAndWindows_KeyMap.insert(85,22);//KEY_U LinuxAndWindows_KeyMap.insert(86,47);//KEY_V LinuxAndWindows_KeyMap.insert(87,17);//KEY_W LinuxAndWindows_KeyMap.insert(88,45);//KEY_X LinuxAndWindows_KeyMap.insert(89,21);//KEY_Y LinuxAndWindows_KeyMap.insert(90,44);//KEY_Z uchar k = 57;//找不到的字符用空格代替 if(LinuxAndWindows_KeyMap.contains(key)) k = LinuxAndWindows_KeyMap[key]; qDebug()<<"Windows:"<<key<<"Linux:"<<k; return k; } void CmdThread::KeyMap() { // {Qt::Key_Up, VK_UP} m_KeyMap.insert(Qt::Key_Left,0x25); m_KeyMap.insert(Qt::Key_Up,0x26); m_KeyMap.insert(Qt::Key_Right,0x27); m_KeyMap.insert(Qt::Key_Down,0x28); m_KeyMap.insert(Qt::Key_Backspace,0x08); m_KeyMap.insert(Qt::Key_Tab,0x09); m_KeyMap.insert(Qt::Key_Clear,0x0C); m_KeyMap.insert(Qt::Key_Return,0x0D); m_KeyMap.insert(Qt::Key_Enter,0x0D); m_KeyMap.insert(Qt::Key_Shift,0x10); m_KeyMap.insert(Qt::Key_Control,0x11); m_KeyMap.insert(Qt::Key_Alt,0x12); m_KeyMap.insert(Qt::Key_Pause,0x13); m_KeyMap.insert(Qt::Key_CapsLock,0x14); m_KeyMap.insert(Qt::Key_Escape,0x1B); m_KeyMap.insert(Qt::Key_Space,0x20); m_KeyMap.insert(Qt::Key_PageUp,0x21); m_KeyMap.insert(Qt::Key_PageDown,0x22); m_KeyMap.insert(Qt::Key_End,0x23); m_KeyMap.insert(Qt::Key_Home,0x24); m_KeyMap.insert(Qt::Key_Select,0x29); m_KeyMap.insert(Qt::Key_Print,0x2A); m_KeyMap.insert(Qt::Key_Execute,0x2B); m_KeyMap.insert(Qt::Key_Printer,0x2C); m_KeyMap.insert(Qt::Key_Insert,0x2D); m_KeyMap.insert(Qt::Key_Delete,0x2E); m_KeyMap.insert(Qt::Key_Help,0x2F); m_KeyMap.insert(Qt::Key_0,0x30); m_KeyMap.insert(Qt::Key_ParenRight,0x30); // ) m_KeyMap.insert(Qt::Key_1,0x31); m_KeyMap.insert(Qt::Key_Exclam,0x31); // ! m_KeyMap.insert(Qt::Key_2,0x32); m_KeyMap.insert(Qt::Key_At,0x32); // @ m_KeyMap.insert(Qt::Key_3,0x33); m_KeyMap.insert(Qt::Key_NumberSign,0x33); // # m_KeyMap.insert(Qt::Key_4,0x34); m_KeyMap.insert(Qt::Key_Dollar,0x34); // $ m_KeyMap.insert(Qt::Key_5,0x35); m_KeyMap.insert(Qt::Key_Percent,0x35); // % m_KeyMap.insert(Qt::Key_6,0x36); m_KeyMap.insert(Qt::Key_AsciiCircum,0x36); // ^ m_KeyMap.insert(Qt::Key_7,0x37); m_KeyMap.insert(Qt::Key_Ampersand,0x37); // & m_KeyMap.insert(Qt::Key_8,0x38); m_KeyMap.insert(Qt::Key_Asterisk,0x38); // * m_KeyMap.insert(Qt::Key_9,0x39); m_KeyMap.insert(Qt::Key_ParenLeft,0x39); // ( m_KeyMap.insert(Qt::Key_A,0x41); m_KeyMap.insert(Qt::Key_B,0x42); m_KeyMap.insert(Qt::Key_C,0x43); m_KeyMap.insert(Qt::Key_D,0x44); m_KeyMap.insert(Qt::Key_E,0x45); m_KeyMap.insert(Qt::Key_F,0x46); m_KeyMap.insert(Qt::Key_G,0x47); m_KeyMap.insert(Qt::Key_H,0x48); m_KeyMap.insert(Qt::Key_I,0x49); m_KeyMap.insert(Qt::Key_J,0x4A); m_KeyMap.insert(Qt::Key_K,0x4B); m_KeyMap.insert(Qt::Key_L,0x4C); m_KeyMap.insert(Qt::Key_M,0x4D); m_KeyMap.insert(Qt::Key_N,0x4E); m_KeyMap.insert(Qt::Key_O,0x4F); m_KeyMap.insert(Qt::Key_P,0x50); m_KeyMap.insert(Qt::Key_Q,0x51); m_KeyMap.insert(Qt::Key_R,0x52); m_KeyMap.insert(Qt::Key_S,0x53); m_KeyMap.insert(Qt::Key_T,0x54); m_KeyMap.insert(Qt::Key_U,0x55); m_KeyMap.insert(Qt::Key_V,0x56); m_KeyMap.insert(Qt::Key_W,0x57); m_KeyMap.insert(Qt::Key_X,0x58); m_KeyMap.insert(Qt::Key_Y,0x59); m_KeyMap.insert(Qt::Key_Z,0x5A); m_KeyMap.insert(Qt::Key_multiply,0x6A); m_KeyMap.insert(Qt::Key_F1,0x70); m_KeyMap.insert(Qt::Key_F2,0x71); m_KeyMap.insert(Qt::Key_F3,0x72); m_KeyMap.insert(Qt::Key_F4,0x73); m_KeyMap.insert(Qt::Key_F5,0x74); m_KeyMap.insert(Qt::Key_F6,0x75); m_KeyMap.insert(Qt::Key_F7,0x76); m_KeyMap.insert(Qt::Key_F8,0x77); m_KeyMap.insert(Qt::Key_F9,0x78); m_KeyMap.insert(Qt::Key_F10,0x79); m_KeyMap.insert(Qt::Key_F11,0x7A); m_KeyMap.insert(Qt::Key_F12,0x7B); m_KeyMap.insert(Qt::Key_F13,0x7C); m_KeyMap.insert(Qt::Key_F14,0x7D); m_KeyMap.insert(Qt::Key_F15,0x7E); m_KeyMap.insert(Qt::Key_F16,0x7F); m_KeyMap.insert(Qt::Key_F17,0x80); m_KeyMap.insert(Qt::Key_F18,0x81); m_KeyMap.insert(Qt::Key_F19,0x82); m_KeyMap.insert(Qt::Key_F20,0x83); m_KeyMap.insert(Qt::Key_F21,0x84); m_KeyMap.insert(Qt::Key_F22,0x85); m_KeyMap.insert(Qt::Key_F23,0x86); m_KeyMap.insert(Qt::Key_F24,0x87); m_KeyMap.insert(Qt::Key_NumLock,0x90); m_KeyMap.insert(Qt::Key_ScrollLock,0x91); m_KeyMap.insert(Qt::Key_VolumeDown,0xAE); m_KeyMap.insert(Qt::Key_VolumeUp,0xAF); m_KeyMap.insert(Qt::Key_VolumeMute,0xAD); m_KeyMap.insert(Qt::Key_MediaStop,0xB2); m_KeyMap.insert(Qt::Key_MediaPlay,0xB3); m_KeyMap.insert(Qt::Key_Plus,0xBB); // + m_KeyMap.insert(Qt::Key_Minus,0xBD); // - m_KeyMap.insert(Qt::Key_Underscore,0xBD); // _ m_KeyMap.insert(Qt::Key_Equal,0xBB); // = m_KeyMap.insert(Qt::Key_Semicolon,0xBA); // ; m_KeyMap.insert(Qt::Key_Colon,0xBA); // : m_KeyMap.insert(Qt::Key_Comma,0xBC); // , m_KeyMap.insert(Qt::Key_Less,0xBC); // < m_KeyMap.insert(Qt::Key_Period,0xBE); // . m_KeyMap.insert(Qt::Key_Greater,0xBE); // > m_KeyMap.insert(Qt::Key_Slash,0xBF); // / m_KeyMap.insert(Qt::Key_Question,0xBF); // ? m_KeyMap.insert(Qt::Key_BracketLeft,0xDB); // [ m_KeyMap.insert(Qt::Key_BraceLeft,0xDB); // { m_KeyMap.insert(Qt::Key_BracketRight,0xDD); // ] m_KeyMap.insert(Qt::Key_BraceRight,0xDD); // } m_KeyMap.insert(Qt::Key_Bar,0xDC); // | m_KeyMap.insert(Qt::Key_Backslash,0xDC); // m_KeyMap.insert(Qt::Key_Apostrophe,0xDE); // ' m_KeyMap.insert(Qt::Key_QuoteDbl,0xDE); // " m_KeyMap.insert(Qt::Key_QuoteLeft,0xC0); // ` m_KeyMap.insert(Qt::Key_AsciiTilde,0xC0); // ~ } //获取鼠标点击位置在屏幕中的比例 void setUchar(int x, int y,int frameWidth,int frameHeight,uchar uc[]) { //获取比例的小数点后1~2位 uc[1] = ((double)x/frameWidth)*100; uc[2] = ((double)y/frameHeight)*100; //获取比例的小数点后3~4位 uc[3] = (int)((double)x/frameWidth*10000)%100; uc[4] = (int)((double)y/frameHeight*10000)%100; //获取比例的小数点后5~6位 uc[5] = (int)((double)x/frameWidth*1000000)%100; uc[6] = (int)((double)y/frameHeight*1000000)%100; //获取比例的小数点后7~8位 uc[7] = (int)((double)x/frameWidth*100000000)%100; uc[8] = (int)((double)y/frameHeight*100000000)%100; //获取比例的小数点后9~10位 uc[9] = (long long)((long double)x/frameWidth*10000000000)%100; uc[10] = (long long)((long double)y/frameHeight*10000000000)%100; }
/*被控端 只接收 控制端 的数据,不发送控制数据*/
Pos_CmdThread::Pos_CmdThread(QTcpSocket* socket, QObject *parent) :
QThread(parent)
{
cmdSocket = socket;
cmd_buf_fill = 0;
connect(cmdSocket, SIGNAL(readyRead()), this, SLOT(newData()));
}
void Pos_CmdThread::run()
{
QThread::run();
}
//当tcp socket有新数据到达时运行此函数
void Pos_CmdThread::newData()
{
while(true)
{
int r = cmdSocket->read((char*)(cmd_buf + cmd_buf_fill), 16 - cmd_buf_fill);
if(r <= 0)
{
qWarning()<<"被控端:控制功能-控制数据读取发生错误!";
return;
}
cmd_buf_fill += r;
//每16个字节为一个完整命令数据
if(cmd_buf_fill == 16)
{
newCommand();
cmd_buf_fill = 0;
}
}
}
void Pos_CmdThread::newCommand()
{
qDebug()<<"被控端:被控线程-接收到新的控制信息-"<<cmd_buf[0];
int cmd = cmd_buf[0];
switch(cmd)
{
case CMD_MOUSE_MOVE_TO:
cmdMouseMoveTo();
break;
case CMD_MOUSE_LEFT_DOWN:
cmdMouseLeftDown();
break;
case CMD_MOUSE_LEFT_UP:
cmdMouseLeftUp();
break;
case CMD_MOUSE_RIGHT_DOWN:
cmdMouseRightDown();
break;
case CMD_MOUSE_RIGHT_UP:
cmdMouseRightUp();
break;
case CMD_MOUSE_WHEEL:
cmdMouseWheel();
break;
case CMD_KEY_PRESS:
cmdKeyPressed();
break;
case CMD_KEY_RELEASE:
cmdKeyReleased();
break;
default:
qWarning()<<"被控端:被控线程-控制命令类型出错!";
break;
}
}
//鼠标移动
void Pos_CmdThread::cmdMouseMoveTo()
{
QPoint p = transformCoordinate();
mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_MOVE, p.x(), p.y(), 0, 0);
}
//获取鼠标转换后所在的位置
QPoint Pos_CmdThread::transformCoordinate()
{
//获取比例;
long double x = cmd_buf[1]*0.01+cmd_buf[3]*0.0001+cmd_buf[5]*0.000001+cmd_buf[7]*0.00000001+cmd_buf[9]*0.0000000001;
long double y = cmd_buf[2]*0.01+cmd_buf[4]*0.0001+cmd_buf[6]*0.000001+cmd_buf[8]*0.00000001+cmd_buf[10]*0.0000000001;
//计算鼠标位置,将鼠标映射到65535*65535的矩阵上
int point_x = x*65535;
int point_y = y*65535;
return QPoint(point_x, point_y);
}
//鼠标左键按下
void Pos_CmdThread::cmdMouseLeftDown()
{
//执行点击事件
QPoint p = transformCoordinate();
mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_LEFTDOWN, p.x(), p.y(), 0, 0);
}
//鼠标左键释放
void Pos_CmdThread::cmdMouseLeftUp()
{
QPoint p = transformCoordinate();
mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_LEFTUP, p.x(), p.y(), 0, 0);
}
//鼠标右键按下
void Pos_CmdThread::cmdMouseRightDown()
{
//执行点击事件
QPoint p = transformCoordinate();
mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_RIGHTDOWN, p.x(), p.y(), 0, 0);
}
//鼠标右键释放
void Pos_CmdThread::cmdMouseRightUp()
{
//执行点击事件
QPoint p = transformCoordinate();
mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_RIGHTUP, p.x(), p.y(), 0, 0);
}
//鼠标滚轮事件
void Pos_CmdThread::cmdMouseWheel()
{
int delta = cmd_buf[11];
//乘以256加余数得到原值
delta = delta << 8;
delta += cmd_buf[12];
//判断正负
delta = cmd_buf[13]==0 ? delta*(-1) :delta;
QPoint p = transformCoordinate();
qDebug()<<p.x()<<p.y()<<delta;
mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_WHEEL, p.x(), p.y(), delta, 0);
}
//键盘按键按下
void Pos_CmdThread::cmdKeyPressed()
{
uchar key = cmd_buf[1];//Windows端,所以用【1】字段
keybd_event(key, 0x45, KEYEVENTF_EXTENDEDKEY, 0);
}
//键盘按键释放
void Pos_CmdThread::cmdKeyReleased()
{
uchar key = cmd_buf[1];//Windows端,所以用【1】字段
keybd_event(key, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
}
#include "pos_cmdthread.h"
/*被控端 只接收 控制端 的数据,不发送控制数据*/
Pos_CmdThread::Pos_CmdThread(QTcpSocket* socket, QObject *parent) :
QThread(parent)
{
cmdSocket = socket;
cmd_buf_fill = 0;
connect(cmdSocket, SIGNAL(readyRead()), this, SLOT(newData()));
}
void Pos_CmdThread::run()
{
QThread::run();
}
//当tcp socket有新数据到达时运行此函数
void Pos_CmdThread::newData()
{
// qDebug("被控端:获取到操作事件!");1
while(true)
{
int r = cmdSocket->read((char*)(cmd_buf + cmd_buf_fill), 16 - cmd_buf_fill);
if(r <= 0)
{
qWarning()<<"被控端:控制功能-控制数据读取发生错误!";
return;
}
cmd_buf_fill += r;
//每16个字节为一个完整命令数据
if(cmd_buf_fill == 16)
{
newCommand();
cmd_buf_fill = 0;
}
}
}
void Pos_CmdThread::newCommand()
{
qDebug()<<"被控端:被控线程-接收到新的控制信息-"<<cmd_buf[0]<<cmd_buf[1]<<cmd_buf[2];
int cmd = cmd_buf[0];
switch(cmd)
{
case CMD_MOUSE_MOVE_TO:
cmdMouseMoveTo();
break;
case CMD_MOUSE_LEFT_DOWN:
cmdMouseLeftDown();
break;
case CMD_MOUSE_LEFT_UP:
cmdMouseLeftUp();
break;
case CMD_MOUSE_RIGHT_DOWN:
cmdMouseRightDown();
break;
case CMD_MOUSE_RIGHT_UP:
cmdMouseRightUp();
break;
case CMD_MOUSE_WHEEL:
cmdMouseWheel();
break;
case CMD_KEY_PRESS:
cmdKeyPressed();
break;
case CMD_KEY_RELEASE:
cmdKeyReleased();
break;
default:
qWarning()<<"被控端:被控线程-控制命令类型出错!";
break;
}
}
//鼠标移动
void Pos_CmdThread::cmdMouseMoveTo()
{
QPoint p = transformCoordinate();
int fd_kbd = open("/dev/input/event2",O_RDWR);
if(fd_kbd<=0)
{
qWarning("Can not open mouse input file\n");
return ;
}
simulate_mouse(fd_kbd,p.x(),p.y());
close(fd_kbd);
}
//获取鼠标转换后所在的位置
QPoint Pos_CmdThread::transformCoordinate()
{
//获取比例;
long double x = cmd_buf[1]*0.01+cmd_buf[3]*0.0001+cmd_buf[5]*0.000001+cmd_buf[7]*0.00000001+cmd_buf[9]*0.0000000001;
long double y = cmd_buf[2]*0.01+cmd_buf[4]*0.0001+cmd_buf[6]*0.000001+cmd_buf[8]*0.00000001+cmd_buf[10]*0.0000000001;
//计算鼠标位置,将鼠标映射到65535*65535的矩阵上
int point_x = x*65535;
int point_y = y*65535;
return QPoint(point_x, point_y);
}
//鼠标左键按下
void Pos_CmdThread::cmdMouseLeftDown()
{
int fd_mouse = open("/dev/input/event2",O_RDWR);
if(fd_mouse<=0)
{
qWarning("Can not open mouse input file\n");
return ;
}
simulate_key_pressed(fd_mouse,BTN_LEFT);
close(fd_mouse);
}
//鼠标左键释放
void Pos_CmdThread::cmdMouseLeftUp()
{
int fd_mouse = open("/dev/input/event2",O_RDWR);
if(fd_mouse<=0)
{
qWarning("Can not open mouse input file\n");
return ;
}
simulate_key_released(fd_mouse,BTN_LEFT);
close(fd_mouse);
}
//鼠标右键按下
void Pos_CmdThread::cmdMouseRightDown()
{
int fd_mouse = open("/dev/input/event2",O_RDWR);
if(fd_mouse<=0)
{
qWarning("Can not open mouse input file\n");
return ;
}
simulate_key_pressed(fd_mouse,BTN_RIGHT);
close(fd_mouse);
}
//鼠标右键释放
void Pos_CmdThread::cmdMouseRightUp()
{
int fd_mouse = open("/dev/input/event2",O_RDWR);
if(fd_mouse<=0)
{
qWarning("Can not open mouse input file\n");
return ;
}
simulate_key_released(fd_mouse,BTN_RIGHT);
close(fd_mouse);
}
//鼠标滚轮事件
void Pos_CmdThread::cmdMouseWheel()
{
int delta = cmd_buf[11];
//乘以256加余数得到原值
delta = delta << 8;
delta += cmd_buf[12];
//判断正负
delta = cmd_buf[13]==0 ? delta*(-1) :delta;
QPoint p = transformCoordinate();
qDebug()<<p.x()<<p.y()<<delta;
// mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_WHEEL, p.x(), p.y(), delta, 0);
}
//键盘按键按下
void Pos_CmdThread::cmdKeyPressed()
{
uchar key = cmd_buf[2];//Linux端,所以用【2】字段
int fd_kbd = open("/dev/input/event1",O_RDWR);
if(fd_kbd<=0)
{
qWarning("Can not open keyboard input file\n");
return ;
}
simulate_key_pressed(fd_kbd,key);
// simulate_key(fd_kbd,key);
close(fd_kbd);
}
//键盘按键释放
void Pos_CmdThread::cmdKeyReleased()
{
uchar key = cmd_buf[2];//Linux端,所以用【2】字段
int fd_kbd = open("/dev/input/event1",O_RDWR);
if(fd_kbd<=0)
{
qWarning("Can not open keyboard input file\n");
return ;
}
simulate_key_released(fd_kbd,key);
close(fd_kbd);
}
//按键模拟,按键包含按下和松开两个环节
void Pos_CmdThread::simulate_key(int fd, int kval)
{
qDebug("Pos_CmdThread::simulate_key-按键模拟");
struct input_event event;
gettimeofday(&event.time, 0);
//按下kval键
event.type = EV_KEY;
event.value = 1;
event.code = kval;
write(fd, &event, sizeof(event));
//同步,也就是把它报告给系统
event.type = EV_SYN;
event.value = 1;
event.code = SYN_REPORT;
write(fd, &event, sizeof(event));
memset(&event, 0, sizeof(event));
gettimeofday(&event.time, 0);
//松开kval键
event.type = EV_KEY;
event.value = 0;
event.code = kval;
write(fd, &event, sizeof(event));
//同步,也就是把它报告给系统
event.type = EV_SYN;
event.value = 0;
event.code = SYN_REPORT;
write(fd, &event, sizeof(event));
}
//按键按下
void Pos_CmdThread::simulate_key_pressed(int fd, int kval)
{
qDebug("Pos_CmdThread::simulate_key_pressed——按下按键模拟");
struct input_event event;
gettimeofday(&event.time, 0);
//按下kval键
event.type = EV_KEY;
event.value = 1;
event.code = kval;
write(fd, &event, sizeof(event));
//同步,也就是把它报告给系统
event.type = EV_SYN;
event.value = 1;
event.code = SYN_REPORT;
write(fd, &event, sizeof(event));
memset(&event, 0, sizeof(event));
}
//按键释放
void Pos_CmdThread::simulate_key_released(int fd, int kval)
{
qDebug("Pos_CmdThread::simulate_key_released——释放按键模拟");
struct input_event event;
gettimeofday(&event.time, 0);
//按下kval键
event.type = EV_KEY;
event.value = 0;
event.code = kval;
write(fd, &event, sizeof(event));
//同步,也就是把它报告给系统
event.type = EV_SYN;
event.value = 0;
event.code = SYN_REPORT;
write(fd, &event, sizeof(event));
memset(&event, 0, sizeof(event));
}
//鼠标移动模拟
void Pos_CmdThread::simulate_mouse(int fd, int rel_x, int rel_y)
{
qDebug("鼠标移动模拟");
struct input_event event;
gettimeofday(&event.time, 0);
//x轴坐标的相对位移
event.type = EV_ABS;
event.value = rel_x;
event.code = ABS_X;
write(fd, &event, sizeof(event));
//y轴坐标的相对位移
event.type = EV_ABS;
event.value = rel_y;
event.code = ABS_Y;
write(fd, &event, sizeof(event));
//同步
event.type = EV_SYN;
event.value = 0;
event.code = SYN_REPORT;
write(fd, &event, sizeof(event));
}
//发送文件数据
void TransFile::startTransfer()
{
QDataStream sendOut(&outBlock,QIODevice::WriteOnly);
sendOut.setVersion(QDataStream::Qt_5_7);
localFile=new QFile(fileName);
if(!localFile->open(QFile::ReadOnly))
{
qWarning()<<"控制端:"<<"打开文件出错!";
return;
}
//文件大小
totalBytes=localFile->size();
//传输总大小,文件总大小、文件名大小、文件名
sendOut<<qint64(0)<<qint64(0)<<qint64(0)<<currentFileName;
//传输总大小
totalBytes+=outBlock.size();
sendOut.device()->seek(0);
//填充 传输总大小,文件总大小、文件名大小, 发送大小等头部信息
sendOut<<totalBytes<<localFile->size()<<qint64(outBlock.size()-sizeof(qint64)*3);
tcpClient->write(outBlock);
//发送真实数据
int sendSize = 0 , len = 0;
do
{
//每次发送数据的大小
char buf[1024] = {0};
len=0;
//往文件里读数据
len = localFile->read(buf,sizeof(buf));
if(len<=0)
{
qWarning()<<"发送端:文件传输-读取文件数据失败!";
return;
}
//发送数据,读多少,发多少
len = tcpClient->write(buf,len);
if(len<=0)
{
qWarning()<<"发送端:文件传输-发送数据失败!";
return;
}
sendSize+=len;
}while(len>0);
ui->label_Filestate->setText(tr("传送文件 %1 成功,对方已断开!").arg(currentFileName));
ui->pBt_Trans->setText("已发送");
ui->pBt_Trans->setEnabled(false);
outBlock.resize(0);
totalBytes = 0;
qDebug()<<"控制端:"<<"发送文件"<<currentFileName<<"成功!";
}
//当tcp socket有新数据到达时运行此函数
void Pos_TransThread::newData()
{
qDebug()<<"接收端:"<<"开始接收文件!";
//使用数据流读取
QDataStream in(transSocket);
in.setVersion(QDataStream::Qt_5_7);
// 如果接收到的数据小于24个字节,保存到来的文件头结构
if (m_bytesReceived<=sizeof(qint64)*3)
{
if((transSocket->bytesAvailable()>=sizeof(qint64)*3)&&(m_fileNameSize==0))
{
// 接收数据总大小信息,文件大小 和文件名大小信息
in>>m_totalBytes>>m_fileSize>>m_fileNameSize;
m_bytesReceived +=sizeof(qint64)*3;
}
if((transSocket->bytesAvailable()>=m_fileNameSize)&&(m_fileNameSize!=0))
{
// 接收文件名,并建立文件
in>>m_fileName;
m_bytesReceived+=m_fileNameSize;
m_localFile = new QFile(m_fileName);
//打开文件
if (!m_localFile->open(QFile::WriteOnly|QIODevice::Append)){
qWarning() << "接收端:文件打开失败!"<<m_fileName;
return;
}
}
else return;
}
// 如果接收的数据小于总数据,那么写入文件
if(m_bytesReceived<m_totalBytes) {
m_bytesReceived+=transSocket->bytesAvailable();
m_inBlock = transSocket->readAll();
quint64 len = m_localFile->write(m_inBlock);
if(len<=0)
{
qWarning()<<"文件传输接收端出现错误,写入文件失败!";
return;
}
m_inBlock.resize(0);
}
// 接收数据完成时
if (m_bytesReceived==m_totalBytes)
{
qDebug()<<"接收端:接收文件成功"<<m_fileName<<"自动断开连接!";
//弹窗提醒接收成功
QMessageBox::about(NULL,"","接收文件成功!");
transSocket->close();
m_localFile->close();
}
}
评论列表(条)