手机控制PPT good
以前做了一个小东西,通过手机来控制PPT的翻页,最大化和最小化,东西很简单,近期整理电脑发现了拿来和大家分享一下
主要分为两个部分,客户端和服务器
客户端实现
当初考虑到跨平台的特性就选择了qt来写的,代码很简单,主要是通过socket连接运行在电脑上的server,发送不同的指令完成不同的操作。由于Qt的跨平台性可以将其移植到安卓和iOS上,安卓上使用完全没问题,ios也应该是没问题,我不是土豪,没法用苹果手机测试,有兴趣的大家可以试试
Control_PPT.pro
#-------------------------------------------------
#
# Project created by QtCreator 2016-06-20T09:20:20
#
#-------------------------------------------------
QT += core gui
QT += network
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = Control_PPT
TEMPLATE = app
SOURCES += main.cpp\
mainwidget.cpp
HEADERS += mainwidget.h
mainwidget.h
#ifndef MAINWIDGET_H
#define MAINWIDGET_H
#include <QWidget>
#include <QtNetwork/QtNetwork>
#include <QLabel>
#include <QPushButton>
#include <QLineEdit>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QGridLayout>
#include <QMessageBox>
#include <QMouseEvent>
#include <QStatusBar>
class MainWidget : public QWidget
{
Q_OBJECT
public:
MainWidget(QWidget *parent = 0);
~MainWidget();
void initIpLayout();
void initControlBtnLayout();
// void mouseMoveEvent(QMouseEvent *event);
private:
QLabel *ipLbl;
QLineEdit *ipLineEdit;
QPushButton *connectBtn;
/*
控制按钮 上一页、写一页等
*/
QPushButton *upBtn;
QPushButton *downBtn;
QPushButton *leftBtn;
QPushButton *rightBtn;
QPushButton *f5Btn;
QPushButton *escBtn;
/*
布局
*/
QHBoxLayout *ipHLayout;
QGridLayout *controlBtnLayout;
QVBoxLayout *mainVLayout;
QTcpSocket *client;
QStatusBar *statusBar;
QLabel *msgLabel;
bool flag;
public slots:
void conncSlot();
void upSlot();
void downSlot();
void leftSlot();
void rightSlot();
void f5Slot();
void escSlot();
void displayError(QAbstractSocket::SocketError);
};
#endif // MAINWIDGET_H
main.widget.cpp
#include "mainwidget.h"
MainWidget::MainWidget(QWidget *parent)
: QWidget(parent)
{
flag = true;
msgLabel = new QLabel;
//msgLabel->setMinimumSize(msgLabel->sizeHint());
msgLabel->setAlignment(Qt::AlignHCenter);
statusBar = new QStatusBar(this);
statusBar->setFixedHeight(30);
statusBar->setFixedWidth(this->width());
statusBar->addWidget(msgLabel); //头文件要添加include<QStatusBar>才不会报错
initIpLayout();
initControlBtnLayout();
mainVLayout = new QVBoxLayout;
mainVLayout->addLayout(ipHLayout);
mainVLayout->addLayout(controlBtnLayout);
this->setLayout(mainVLayout);
connect(connectBtn,SIGNAL(clicked()),this, SLOT(conncSlot()));
connect(upBtn,SIGNAL(clicked()),this, SLOT(upSlot()));
connect(downBtn,SIGNAL(clicked()),this, SLOT(downSlot()));
connect(f5Btn,SIGNAL(clicked()),this, SLOT(f5Slot()));
connect(leftBtn,SIGNAL(clicked()),this, SLOT(leftSlot()));
connect(rightBtn,SIGNAL(clicked()),this, SLOT(rightSlot()));
connect(escBtn,SIGNAL(clicked()),this, SLOT(escSlot()));
}
/*
设置获取ip连接的布局
*/
void MainWidget::initIpLayout()
{
ipLbl = new QLabel(tr("IP:"));
ipLineEdit = new QLineEdit();
ipLineEdit->setPlaceholderText(tr("127.0.0.1"));
connectBtn = new QPushButton(tr("连接"));
ipHLayout = new QHBoxLayout;
ipHLayout->addWidget(ipLbl);
ipHLayout->addWidget(ipLineEdit);
ipHLayout->addWidget(connectBtn);
// ipHLayout->setMargin(10);
}
void MainWidget::initControlBtnLayout()
{
upBtn = new QPushButton(tr("上"));
leftBtn = new QPushButton(tr("左"));
f5Btn = new QPushButton(tr("f5"));
rightBtn = new QPushButton(tr("右"));
downBtn = new QPushButton(tr("下"));
escBtn = new QPushButton(tr("esc"));
controlBtnLayout = new QGridLayout();
controlBtnLayout->addWidget(upBtn,0,1);
controlBtnLayout->addWidget(leftBtn, 1, 0);
controlBtnLayout->addWidget(f5Btn,1,1);
controlBtnLayout->addWidget(rightBtn, 1, 2);
controlBtnLayout->addWidget(downBtn, 2, 1);
controlBtnLayout->addWidget(escBtn, 3, 1);
}
//void MainWidget::mouseMoveEvent(QMouseEvent *event)
//{
// int x = event->x();
// int y = event->y();
// QPoint point = cursor().pos();
// int x = point.x();
// int y = point.y();
// QString xy;
// xy.clear();
// xy = tr("%1%2%3").arg(x).arg("#").arg(y);
// qDebug() << xy;
// char* chxy;
// QByteArray ba = xy.toLatin1();
// chxy=ba.data();
// if(flag)
// client->write(chxy);
//}
void MainWidget::displayError(QAbstractSocket::SocketError)
{
flag = false;
qDebug() << client->errorString(); //输出错误信息
}
void MainWidget::conncSlot()
{
QString ip = ipLineEdit->text();
QString pattern("^(\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])[.](\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])[.](\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])[.](\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])$");
QRegExp rx(pattern);
if(ip.isEmpty())
{
QMessageBox::information(this,"请输入IP","请输入服务器的IP地址!");
return ;
}
else if(!(rx.exactMatch(ip)))
{
QMessageBox::information(this,"格式错误","请输入正确的IP地址!");
return ;
}
client = new QTcpSocket(this);
client->connectToHost(QHostAddress(ip), 5588);
//connect(client, SIGNAL(connected()),this, SLOT(is_connect_ok()));
connect(client,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(displayError(QAbstractSocket::SocketError)));
if(flag)
{
msgLabel->setText(tr("连接成功!"));
QMessageBox::information(this,tr("连接提示"),tr("恭喜你连接成功"));
flag = false;
}
else
{
msgLabel->setText(tr("连接失败!"));
QMessageBox::information(this,tr("连接提示"),tr("连接失败,请检查ip是否正确"));
}
ipLineEdit->clear();
}
void MainWidget::escSlot()
{
client->write("esc");
msgLabel->setText(tr("退出全屏显示"));
//client->write("100#100");
}
void MainWidget::upSlot()
{
client->write("up");
msgLabel->setText(tr("上一页!"));
}
void MainWidget::downSlot()
{
msgLabel->setText(tr("下一页!"));
client->write("down");
}
void MainWidget::leftSlot()
{
msgLabel->setText(tr("上一页!"));
client->write("left");
}
void MainWidget::rightSlot()
{
msgLabel->setText(tr("下一页!"));
client->write("right");
}
void MainWidget::f5Slot()
{
msgLabel->setText(tr("全屏显示!"));
client->write("f5");
}
MainWidget::~MainWidget()
{
}
main.cpp
#include "mainwidget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWidget w;
w.show();
return a.exec();
}
服务器端
服务器端是Python写的,当然用c++也是可以的,考虑到代码的简洁就选择了python,正好当时刚学了几点的python就用了它,代码写的很烂。服务器的作用主要是调用微软提供的PPT接口完成操作。
server.py
# Echo server program
from socket import*
from time import ctime
import win32com.client
import win32api
import win32con
import time
import pythoncom
from ctypes import *
class PowerPointControler:
def __init__(self):
pythoncom.CoInitialize()
self.app = win32com.client.Dispatch("PowerPoint.Application")
def fullScreen(self):
#全屏播放
if self.hasActivePresentation():
#使用Run方法创建一个新的幻灯片放映窗口并将其添加到SlideShowWindows集合
self.app.ActivePresentation.SlideShowSettings.Run()#该方法用于运行指定演示文稿的幻灯片放映。
return self.getActivePresentationSlideIndex()
def closeFull(self):#结束第一个幻灯片放映窗口中的幻灯片放映
if self.app.ActivePresentation.SlideShowSettings.Run():
self.app.SlideShowWindows(1).View.Exit()
def gotoSlide(self,index):
#跳转到指定的页面
if self.hasActivePresentation():
try:
self.app.ActiveWindow.View.GotoSlide(index)
return self.app.ActiveWindow.View.Slide.SlideIndex
except:
self.app.SlideShowWindows(1).View.GotoSlide(index)
return self.app.SlideShowWindows(1).View.CurrentShowPosition
def nextPage(self):#下一页ppt
if self.hasActivePresentation():
count = self.getActivePresentationSlideCount()
index = self.getActivePresentationSlideIndex()
return count if index >= count else self.gotoSlide(index+1)
def prePage(self):#上一页ppt
if self.hasActivePresentation():
index = self.getActivePresentationSlideIndex()
return index if index <= 1 else self.gotoSlide(index-1)
def drawLine(self, x, y):
index = self.getActivePresentationSlideIndex()
windll.user32.SetCursorPos(x, y)
#参数1位x的起点 第二个参数是y的起点 这两个参数决定了起始的位置
#参数3是x的终点位置 第四个参数是 y的终点位置
self.app.SlideShowWindows(index).View.DrawLine(x, y, x + 500, y)
def getActivePresentationSlideIndex(self):
#得到活跃状态的PPT当前的页数
if self.hasActivePresentation():
try:
index = self.app.ActiveWindow.View.Slide.SlideIndex
except:
index = self.app.SlideShowWindows(1).View.CurrentShowPosition
return index
def getActivePresentationSlideCount(self):
#返回处于活跃状态的PPT的页面总数
return self.app.ActivePresentation.Slides.Count
def getPresentationCount(self):
#返回打开的PPT数目
return self.app.Presentations.Count
def hasActivePresentation(self):
#判断是否有打开PPT文件
return True if self.getPresentationCount() > 0 else False
if __name__ == '__main__':
HOST = ''
PORT = 5588
BUFSIZE = 1024
ADDR = (HOST, PORT)
tcpSerSock = socket(AF_INET, SOCK_STREAM)
tcpSerSock.bind(ADDR)
tcpSerSock.listen(5)
ppt = PowerPointControler()
while True:
print('waiting for connection...')
tcpCliSock, addr = tcpSerSock.accept()
print('...connected from:', addr)
while True:
data = tcpCliSock.recv(BUFSIZE).decode()
print(data)
if not data:
break
if ppt.hasActivePresentation():
if data == "f5":
ppt.fullScreen()
elif data == "up":
ppt.prePage()
elif data == "down":
ppt.nextPage()
elif data == "left":
ppt.prePage()
elif data == "right":
ppt.nextPage()
elif data == "esc":
ppt.closeFull()
#else:未完成画线操作,只能话简单的直线
#xy = data.split('#')
#print(xy[0],xy[1])
#ppt.drawLine(int(xy[0]), int(xy[1]))
#xy.clear();
else:
tcpCliSock.send("close")
tcpCliSock.close()
tcpSerSock.close()
吾还年轻,写的代码比较烂,希望大家指正。
项目下载地址:https://github.com/gqqcode/Mobile-phone-control-ppt
http://blog.csdn.net/guoqianqian5812/article/details/52627502
手机控制PPT good的更多相关文章
- 基于windowsphone7的控制ppt播放
最近突然想起了一个学长的一个利用手机控制ppt播放的一个创意,并想将其在windows phone7上实现一下. 经过几天的努力已经可以控制ppt的播放,暂停,上一张,下一张了,并且电脑会将当前ppt ...
- nodePPT初认识启动与手机控制
最近要做个PPT,想起之前看到过个网页PPT,于是这次就想尝试下,搜了下弹出个nodeppt---有可能是最好的网页PPT,那,就这个吧. 按照文档来,貌似有点问题,百度,又是一堆粘贴复制,没点用.自 ...
- 手机控制电脑,在WIFI局域网下(关机,重启,遥控)
这个软件叫百变遥控:http://blog.sina.com.cn/s/blog_9abc7dbc0101hmut.html 今天周末,在家里看电影,家里用的是台式电脑,我自己买了一个投影仪来专门看视 ...
- 蓝牙4.0BLE 手机控制 cc2540 CC2541 的串口透传功能已实现
蓝牙4.0BLE 手机控制 cc2540 CC2541 的串口透传功能已实现 尽管蓝牙4.0 BLE芯片CC2540 是单芯片(即用户能够对它进行芯片级代码编写), 是80 ...
- 手机控制电脑定时关机,重启WiFi
需求 晚上上床,电脑开着WiFi让手机上网.要么上床之前就给电脑设置定时关机:要么就电脑开通宵:要么就待会下来关电脑.这3种情况都非常不好,要么麻烦,要么浪费. 最无奈的是电脑刚开好WiFi,上床后才 ...
- 我的Android进阶之旅------>Android实现用Android手机控制PC端的关机和重启的功能(三)Android客户端功能实现
我的Android进阶之旅------>Android实现用Android手机控制PC端的关机和重启的功能(一)PC服务器端(地址:http://blog.csdn.net/ouyang_pen ...
- Kinect 开发 —— 控制PPT播放
实现Kinect控制幻灯片播放很简单,主要思路是:使用Kinect捕捉人体动作,然后根据识别出来的动作向系统发出点击向前,向后按键的事件,从而使得幻灯片能够切换. 这里的核心功能在于手势的识别,我们在 ...
- Python 脚本利用adb 进行手机控制
相关参考:https://www.cnblogs.com/bravesnail/articles/5850335.html 一. adb 相关命令: 1. 关闭adb服务:adb kill-serv ...
- python:使用itchat实现手机控制电脑
1.准备材料 首先电脑上需要安装了python,安装了opencv更好(非必需) 如果安装了opencv的话,在opencv的python目录下找到cv2.pyd,将该文件放到python的库搜索路径 ...
随机推荐
- 要求两个异步任务都完成后, 才能回到主线程:dispatch_group_t
需求:两个异步任务都完成后, 回到主线程 /** 1.下载图片1和图片2 2.将图片1和图片2合并成一张图片后显示到imageView上 思考: * 下载图片 : 子线程 * 等2张图片都下载完毕后, ...
- spring data jpa auditing
审计日志,记录实体版本的修改信息,创建时间,修改时间,创建人,修改人等 可以采用切片AOP的方式实现,也可以通过Spring Data JPA的审计功能实现 切片方式 Spring AOP中Point ...
- Objective-C 中的Runtime的使用
Runtime的使用 一直以来,OC被大家冠以动态语言的称谓,其实是因为OC中包含的runtime机制.Runtime 又叫运行时,是一套底层的 C 语言 API,其为 iOS 内部的核心之一,我们平 ...
- M创aterial Design作风Android申请书--创建列表和卡
本人全部文章首先公布于个人博客,欢迎关注,地址:http://blog.isming.me 上次说过使用主题,应用Material Design的样式,同一时候卡片布局也是Material Desig ...
- webpack的单vue组件(.vue)加载sass配置
在通过vue-cli安装了webpack-simple 后,就自动安装好vue-loader了,但此时若写了含有sass的.vue组件,运行npm run dev时会报错.此时,需要我们在webpac ...
- 【39.77%】【codeforces 724B】Batch Sort
time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...
- 手推机器学习公式(一) —— BP 反向传播算法
方便起见,本文仅以三层的神经网络举例. f(⋅):表示激励函数 xi:表示输入层: yj:表示中间的隐层: yj=f(netj) netj=∑i=0nvijxi ok:表示输出层,dk 则表示期望输出 ...
- protobuf反射详解
本文主要介绍protobuf里的反射功能,使用的pb版本为2.6.1,同时为了简洁,对repeated/extension字段的处理方法没有说明. 最初是起源于这样一个问题: 给定一个pb对象,如何自 ...
- http_load测试入门
大致步骤: 1.在对应文件夹下边新建.TXT文件: 2.在该文件下填上待测试URL地址,建议100行以上: 3.管理员权限CMD,对应目录下运行命令即可,如: a) http_load -pa ...
- Java--ConcurrentHashMap原理分析
一.背景: 线程不安全的HashMap 因为多线程环境下,使用Hashmap进行put操作会引起死循环,导致CPU利用率接近100%,所以在并发情况下不能使用HashMap. 效率低下的H ...