业务功能4.鼠标事件处理 5.屏幕监控发送

4.鼠标事件处理

Strategist_MOUSE.h

#pragma once
class CStrategist_MOUSE
{
public:
	CStrategist_MOUSE(){}

	virtual void DealCommand() = 0;

	~CStrategist_MOUSE(){}
};

Mouse.h

#pragma once
#include"ServerSocket.h"
#include"Strategist_MOUSE.h"

typedef struct MOUSEEVENT {//类型结构可以和函数重名
	MOUSEEVENT() {
		nAction = 0;
		nButton = -1;
		ptXY.x = 0;
		ptXY.y = 0;
	}
	WORD nAction;//点击、移动、双击
	WORD nButton;//左键右键中键
	POINT ptXY;//坐标
}MOUSEEV, * PMOUSEEV;


class CMouse: public CStrategist_MOUSE
{
public:
	CMouse() {
		if (CServerSocket::GetInstance()->GetPacket().PacketCommand == 11) {
			memcpy(&mouse, CServerSocket::GetInstance()->GetPacket().PacketData.c_str(), sizeof(MOUSEEV));
			return;
		}
		OutputDebugString(_T("获取鼠标的控制命令失败,不匹配!"));
	}

	~CMouse() {}
public:
	void DealCommand() override;
private:
	void MouseEvent();
private:
	MOUSEEV mouse;
};

Mouse.cpp

#include "pch.h"
#include "Mouse.h"

void CMouse::DealCommand()
{
    if (CServerSocket::GetInstance()->GetPacket().PacketCommand == 11) {
        MouseEvent();
    }
}

void CMouse::MouseEvent()
{
    DWORD nFlags = 0;
    if (nFlags != 8)
        switch (mouse.nButton)
        {
        case 0://左键
            nFlags = 1;
            break;
        case 1:
            nFlags = 2;
            break;//右键
        case 2://中键
            nFlags = 4;
            break;
        case 4:
            nFlags = 8;//没有按键
            break;
        }
    if (nFlags != 8)
        SetCursorPos(mouse.ptXY.x, mouse.ptXY.y);
    switch (mouse.nAction)
    {
    case 0://单击
        nFlags |= 0x10;
        break;
    case 1://双击
        nFlags |= 0x20;
        break;
    case 2://按下拖动
        nFlags |= 0x40;
        break;
    case 3://按键松开
        nFlags |= 0x80;
        break;
    default:
        break;
    }
    switch (nFlags)
    {
    case 0x21://左键双击
        mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, GetMessageExtraInfo());
        mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, GetMessageExtraInfo());
    case 0x11://左键单击
        mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, GetMessageExtraInfo());
        mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, GetMessageExtraInfo());
        break;

    case 0x41://左键按下
        mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, GetMessageExtraInfo());
        break;
    case 0x81://左键松起
        mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, GetMessageExtraInfo());
        break;
        //**
    case 0x22://右键双击
        mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, GetMessageExtraInfo());
        mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, GetMessageExtraInfo());
    case 0x12://右键单击
        mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, GetMessageExtraInfo());
        mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, GetMessageExtraInfo());
        break;
    case 0x42://右键按下
        mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, GetMessageExtraInfo());
        break;
    case 0x82://右键松起
        mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, GetMessageExtraInfo());
        break;
        //**
    case 0x24://中键双击
        mouse_event(MOUSEEVENTF_MIDDLEDOWN, 0, 0, 0, GetMessageExtraInfo());
        mouse_event(MOUSEEVENTF_MIDDLEUP, 0, 0, 0, GetMessageExtraInfo());
    case 0x14://中键单击
        mouse_event(MOUSEEVENTF_MIDDLEDOWN, 0, 0, 0, GetMessageExtraInfo());
        mouse_event(MOUSEEVENTF_MIDDLEUP, 0, 0, 0, GetMessageExtraInfo());
        break;
    case 0x44://中键按下
        mouse_event(MOUSEEVENTF_MIDDLEDOWN, 0, 0, 0, GetMessageExtraInfo());
        break;
    case 0x84://中键松起
        mouse_event(MOUSEEVENTF_MIDDLEUP, 0, 0, 0, GetMessageExtraInfo());
        break;
    case 0x08://单纯鼠标移动
        mouse_event(MOUSEEVENTF_MOVE, mouse.ptXY.x, mouse.ptXY.y, 0, GetMessageExtraInfo());
        break;
    default:
        break;
    }
    CPacket pack(11, NULL, 0);
    CServerSocket::GetInstance()->Send(pack); 
}

5.屏幕发送功能

Strategist_SCREEN.h

#pragma once
class CStrategist_SCREEN
{
public:
	CStrategist_SCREEN() {}
	virtual void DealCommand() = 0;

	~CStrategist_SCREEN() {}
};

Screen.h

#pragma once
#include<atlimage.h>//vs2008后有的

#include"Strategist_SCREEN.h"
#include"ServerSocket.h"
class CScreen : public CStrategist_SCREEN
{
public:
	CScreen() {

	}

	~CScreen() {}
public:
	void DealCommand() override;
private:
	void SendScreen();
private:
	CImage screen;//非常适合GlobalDeviceInterface编程
};

Screen.cpp

#include "pch.h"
#include "Screen.h"

void CScreen::DealCommand()
{
    SendScreen();
}

void CScreen::SendScreen()
{//Windows GDI(图形设备接口)和 GDI+ 库的一些函数。
	HDC hScreen = ::GetDC(NULL);//获取设备上下文
	//每个像素占用需要多少个bit通常RGB888用24bit表示,如果ARGB8888则是32bit。RGB565低性能手机用的
	int nBitPerPixel = GetDeviceCaps(hScreen, BITSPIXEL);
	int nWidth = GetDeviceCaps(hScreen, HORZRES);//获取屏幕水平分辨率我这里是1920
	int nHeight = GetDeviceCaps(hScreen, VERTRES);//1080
    screenImage.Create(nWidth, nHeight, nBitPerPixel);//screenImage被创建为存储屏幕图像数据的容器。
	BitBlt(screenImage.GetDC(), 0, 0, nWidth, nHeight, hScreen, 0, 0, SRCCOPY);//1920*1080,1020不截任务栏
    //如上行代码所示,利用位块传输函数讲屏幕图像从上下文复制到容器中
	ReleaseDC(NULL, hScreen);//释放上下文

    HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, 0);//内存分配一个全局句柄
    if (hMem == NULL) {
        return;
    }
    IStream* pStream = NULL;
    HRESULT ret = CreateStreamOnHGlobal(hMem, TRUE, &pStream);//全局句柄创建一个流对象,用于将图像数据保存在内存中
    if (ret == S_OK)
    {//存到内存中
        screenImage.Save(pStream, Gdiplus::ImageFormatPNG);//容器中的图像保存在内存流中以PNG格式
        LARGE_INTEGER bg = { 0 };
        pStream->Seek(bg, STREAM_SEEK_SET, NULL);//文件指针移动到流的开头
        PBYTE pData = (PBYTE)GlobalLock(hMem);//锁定内存后准备发送
        SIZE_T nSize = GlobalSize(hMem);
        //
        CPacket pack(12, pData, nSize);
        CServerSocket::GetInstance()->Send(pack);
        GlobalUnlock(hMem);//内存解锁
    }
    //DWORD tick = GetTickCount64();
    //screen.Save(_T("test.png"), Gdiplus::ImageFormatPNG);//png通常比jpeg小些。带宽小些
    //TRACE("png:%d\n", GetTickCount64() - tick);
    //tick = GetTickCount64();
    //screen.Save(_T("test2020.jpg"), Gdiplus::ImageFormatJPEG);//jpeg会快些
    //TRACE("jpeg:%d\n", GetTickCount64() - tick);
    pStream->Release();//释放流对象
    GlobalFree(hMem);//释放内存
    screenImage.ReleaseDC();//释放对象的设备上下文
}

内存流:内存流是一种将数据存储在内存中而不是文件中的数据流。在这个特定的情境中,内存流(IStream 接口)的使用是为了将图像数据保存到内存中,然后可以方便地对这块内存中的数据进行操作,例如读取、传输或其他处理。

  • 临时存储:暂存内存,相比于磁盘中形成图片文件,然后在去传输效率更快。
  • 灵活性:内存流允许在不涉及实际文件的情况下进行数据的读写。
  • 方便的接口: IStream 接口提供了一组用于在流中读写数据的通用方法,这些方法可以用于不同类型的数据源,包括文件、内存、网络等。使用内存流,可以更方便地利用这些通用方法进行数据处理。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值