海运的博客

windows下定时截屏对比相似度并关机/待机

发布时间:November 20, 2020 // 分类: // No Comments

先判断上次键盘鼠标活动时间,如果时间较长则隔一段时间截屏判断是否在看视频,如果图片符合相似度则执行待机操作。

#include <windows.h>
#include "bitmap.h"
#include "stdio.h"
#include <time.h>
#include <stdlib.h>
#include <PowrProf.h>
#include <math.h>

void echo(CHAR *str);
int getlastinput();
int CheckFullscreen();
int CaptureImage(CHAR *lpbitmap, int width, int height);
int save(char *outfile, CHAR *lpbitmap, DWORD dwBmpSize, int width, int height);

void echo(CHAR *str) {
  //MessageBox(NULL, str, NULL, MB_OK);
  time_t t1;
  struct tm *newtime;
  char time_str[128];
  t1 = time(NULL);
  newtime=localtime(&t1);
  strftime(time_str, 128, "%Y%m%d_%H%M%S", newtime);
  printf("%s:  %s \n", time_str, str);
  //printf("%s \n", str);
}

int main(int argc, char *argv[]) {
  INT width  = GetSystemMetrics(SM_CXSCREEN);  // 屏幕宽
  INT height = GetSystemMetrics(SM_CYSCREEN);  // 屏幕高
  DWORD dwBmpSize = width *  height * 4;
  INT  WidthBytes = width * 4;
  if (argc == 1) {
    printf("use sleep_time(sec) idle_time(min) similarity(<100) save_bmp(1) debug(1)\n");
    exit(1);
  }
  int sleep_idle, sleep_time, idle_time, save_bmp, debug;
  sleep_idle = sleep_time = idle_time = save_bmp = debug = 0;
  float similarity = 0;
  if (argc > 1)
    sleep_time = atoi(argv[1]);
  if (argc > 2)
    idle_time = atoi(argv[2]);
  if (argc > 3)
    similarity = atof(argv[3]);
  if (argc > 4)
    save_bmp = atoi(argv[4]);
  if (argc > 5)
    debug = atoi(argv[5]);
  if (!sleep_time && !idle_time) {
    exit(1);
  }
  if (sleep_time >= 30) {
    sleep_idle = round(sleep_time/5);
    printf("sleep_idle  = %d\n",  sleep_idle);
    sleep_idle = sleep_idle * 1000;
  } else {
    sleep_idle = sleep_time * 1000;
  }
  sleep_time = sleep_time * 1000; //sec
  idle_time = idle_time * 60 * 1000; //min

  HANDLE hDIB;
  hDIB = GlobalAlloc(GHND, dwBmpSize);
  CHAR *lpbitmap = (char *)GlobalLock(hDIB);
  HANDLE hDIB2;
  hDIB2 = GlobalAlloc(GHND, dwBmpSize);
  CHAR *lpbitmap2 = (char *)GlobalLock(hDIB2);

  if (!CaptureImage(lpbitmap, width, height)) {
    exit(1);
  }

  while (1) {
    //CheckFullscreen();
    long int idle = getlastinput();
    printf("%d \n", idle);
    if (!debug && idle < idle_time) {
      echo ("idle");
      Sleep(sleep_idle);
      continue;
    }
    if (!CaptureImage(lpbitmap2, width,height)) {
      Sleep(5*1000);
      continue;
    }

    int count = 0;
    int cmp = 0;
    int index = 0;
    for (int i = 0;i < width;++i)
    {
      for (int j = 0;j < height;++j)
      {
        count++;
        index = i * 4 + j * WidthBytes;
        if (lpbitmap[index + 2] != lpbitmap2[index + 2] || lpbitmap[index + 1] != lpbitmap2[index + 1] || lpbitmap[index + 0] != lpbitmap2[index + 0]) {
          cmp++;
        }
        //BYTE r = lpbitmap[index + 2];
        //BYTE g = lpbitmap[index + 1];
        //BYTE b = lpbitmap[index + 0];
        //printf("r  = %d\n",  r );
        //printf("g  = %d\n",  g );
        //printf("b  = %d\n",  b );
        //printf("index = %d\n",  index);
        //Sleep(1000);
      }
    }

    printf("count = %d\n", count);
    printf("cmp = %d\n", cmp);
    float percentage = (float)cmp / count * 100.0;
    printf("Percentage = %.2f%%\n", percentage);
    if (!debug && percentage <= similarity) {
      echo("SetSuspendState");
      SetSuspendState(0, 1, 1);
      Sleep(60*1000);
    }

    if (save_bmp == 1 && percentage <= similarity) {
      time_t t1;
      struct tm *newtime;
      char time_str[128];
      char outfile[128];
      t1 = time(NULL);
      newtime=localtime(&t1);
      //strftime(outfile, 128, "%Y%m%d_%H%M%S.bmp", newtime);
      strftime(time_str, 128, "%Y%m%d_%H%M%S", newtime);
      sprintf(outfile,"%s_1_%.2f%%.bmp",time_str,percentage);
      save(outfile,lpbitmap, dwBmpSize, width, height);
      sprintf(outfile,"%s_2_%.2f%%.bmp",time_str,percentage);
      save(outfile,lpbitmap2, dwBmpSize, width,height);
    }

    memcpy(lpbitmap, lpbitmap2, dwBmpSize);
    Sleep(sleep_time);
  }
  // 解锁堆内存并释放
  GlobalUnlock(hDIB);
  GlobalFree(hDIB);
  GlobalUnlock(hDIB2);
  GlobalFree(hDIB2);
  return 0;
}


int CaptureImage(CHAR *lpbitmap, int width, int height)
{
  int ret = 1;
  //GetDesktopWindow()
  HDC hScreenDC = GetDC(NULL); //获取显示设备上下文环境
  HDC hMemoryDC = CreateCompatibleDC(hScreenDC); // 创建与显示设备兼容的内存下文环境(设备描述表)
  if (!hMemoryDC) {
    echo(TEXT("CreateCompatibleDC has failed"));
    ret = 0;
    goto done;
  }

  //创建一个与显示设备描述表兼容的位图
  HBITMAP hBitmap = CreateCompatibleBitmap(hScreenDC, width, height);
  if (!hBitmap) {
    echo(TEXT("CreateCompatibleBitmap Failed"));
    ret = 0;
    goto done;
  }

  //把位图选到内存设备描述表中
  SelectObject(hMemoryDC, hBitmap);
  //HBITMAP hOldBitmap = (HBITMAP) SelectObject(hMemoryDC, hBitmap);
  //把屏幕设备描述表拷贝到内存设备描述表中。
  if (!BitBlt(
        hMemoryDC,    // 目的DC
        0, 0,        // 目的DC的 x,y 坐标
        width, height, // 目的 DC 的宽高
        hScreenDC,   // 来源DC
        0, 0,        // 来源DC的 x,y 坐标
        SRCCOPY))    // 粘贴方式
  {
    echo(TEXT("BitBlt has failed"));
    ret = 0;
    goto done;
  }

  //BITMAP bmpScreen;
  //Get the BITMAP from the HBITMAP
  //GetObject(hbmScreen, sizeof(BITMAP), &bmpScreen);
  //hBitmap = (HBITMAP) SelectObject(hMemoryDC, hOldBitmap);

  BITMAPINFOHEADER bi;
  bi.biSize = sizeof(BITMAPINFOHEADER);
  bi.biWidth = width;
  bi.biHeight = height;
  bi.biPlanes = 1;
  bi.biBitCount = 32;
  bi.biCompression = BI_RGB;
  bi.biSizeImage = 0;
  bi.biXPelsPerMeter = 0;
  bi.biYPelsPerMeter = 0;
  bi.biClrUsed = 0;
  bi.biClrImportant = 0;

  // 获取兼容位图的位并且拷贝结果到一个 lpbitmap 中.
  GetDIBits(
      hScreenDC,  // 设备环境句柄
      hBitmap,  // 位图句柄
      0,          // 指定检索的第一个扫描线
      (UINT)height, // 指定检索的扫描线数
      lpbitmap,   // 指向用来检索位图数据的缓冲区的指针
      (BITMAPINFO *)&bi, // 该结构体保存位图的数据格式
      DIB_RGB_COLORS // 颜色表由红、绿、蓝(RGB)三个直接值构成
      );

  //printf("sizeof((LPSTR)lpbitmap) = %d\n", sizeof((LPSTR)lpbitmap));
  //printf("sizeof(lpbitmap[0]) = %d\n", sizeof(lpbitmap[0]));

done:
  DeleteObject(hBitmap);
  DeleteObject(hMemoryDC);
  //DeleteDC(hMemoryDC);
  ReleaseDC(NULL, hScreenDC);
  return ret;
}

int getlastinput()
{
  long int      newTicks;        // time value for new ticks
  long int      inputTicks;      // time value for current time
  long int      elapsedTicks;    // time value for elapsed time
  LASTINPUTINFO lii;             // Structure for Windows time stuff

  // Set size of lii.cbsize
  lii.cbSize = sizeof(lii);

  // Get the time of the most recent (new) user input
  GetLastInputInfo(&lii);
  newTicks = lii.dwTime;

  inputTicks = GetTickCount();
  elapsedTicks = inputTicks - newTicks;

  return elapsedTicks;
}

int CheckFullscreen() {
  int bFullScreen = 0;
  HWND hWnd = GetForegroundWindow();
  RECT rcApp, rcDesk;
  GetWindowRect(GetDesktopWindow(), &rcDesk);

  if (hWnd!=GetDesktopWindow() && hWnd!=GetShellWindow()) {
    GetWindowRect(hWnd, &rcApp);
    if (rcApp.left<=rcDesk.left && rcApp.top<=rcDesk.top && rcApp.right>=rcDesk.right && rcApp.bottom>=rcDesk.bottom) {
      char wnd_name[256];
      char wnd_title[256];
      GetWindowText(hWnd,wnd_title,sizeof(wnd_title));
      GetClassName(hWnd, wnd_name, sizeof(wnd_name));
      printf("title: %s\n", wnd_title);
      printf("name: %s\n", wnd_name);

      if (strcmp(wnd_name, "Windows.UI.Core.CoreWindow") != 0 && strcmp(wnd_name, "WorkerW") != 0){
        bFullScreen =1;
      }
    }
  }
  return bFullScreen;
}

int save(char *outfile, CHAR *lpbitmap, DWORD dwBmpSize, int width, int height) {
  HANDLE hFile;
  DWORD dwSizeofDIB;
  DWORD dwBytesWritten;
  BITMAPFILEHEADER bmfHeader;

  BITMAPINFOHEADER bi;
  bi.biSize = sizeof(BITMAPINFOHEADER);
  bi.biWidth = width;
  bi.biHeight = height;
  bi.biPlanes = 1;
  bi.biBitCount = 32;
  bi.biCompression = BI_RGB;
  bi.biSizeImage = 0;
  bi.biXPelsPerMeter = 0;
  bi.biYPelsPerMeter = 0;
  bi.biClrUsed = 0;
  bi.biClrImportant = 0;

  // 创建一个文件来保存文件截图
  hFile = CreateFile(
      outfile,
      GENERIC_WRITE,
      0,
      NULL,
      CREATE_ALWAYS,
      FILE_ATTRIBUTE_NORMAL,
      NULL
      );

  // 将 图片头(headers)的大小, 加上位图的大小来获得整个文件的大小
  dwSizeofDIB = dwBmpSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

  // 设置 Offset 偏移至位图的位(bitmap bits)实际开始的地方
  bmfHeader.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);

  // 文件大小
  bmfHeader.bfSize = dwSizeofDIB;

  // 位图的 bfType 必须是字符串 "BM"
  bmfHeader.bfType = 0x4D42; //BM

  dwBytesWritten = 0;
  WriteFile(hFile, (LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL);
  WriteFile(hFile, (LPSTR)&bi, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL);
  WriteFile(hFile, (LPSTR)lpbitmap, dwBmpSize, &dwBytesWritten, NULL);
  // 关闭文件句柄
  CloseHandle(hFile);
  return 0;
}

使用tdm-gcc编译:

gcc screen.c -o screen.exe -lgdi32 -lPowrprof

参考:
https://docs.microsoft.com/zh-cn/windows/win32/gdi/capturing-an-image?redirectedfrom=MSDN
https://lellansin.wordpress.com/2014/03/16/c-gdi-%E5%B1%8F%E5%B9%95%E6%88%AA%E5%9B%BE/
https://bbs.csdn.net/topics/390838652?page=4
https://bbs.csdn.net/topics/340205786?page=2
https://blog.csdn.net/haogeai123/article/details/7030583

标签:none

评论已关闭

分类
最新文章
最近回复
  • 海运: 恩山有很多。
  • swsend: 大佬可以分享一下固件吗,谢谢。
  • Jimmy: 方法一 nghtp3步骤需要改成如下才能编译成功: git clone https://git...
  • 海运: 地址格式和udpxy一样,udpxy和msd_lite能用这个就能用。
  • 1: 怎么用 编译后的程序在家里路由器内任意一台设备上运行就可以吗?比如笔记本电脑 m参数是笔记本的...
  • 孤狼: ups_status_set: seems that UPS [BK650M2-CH] is ...
  • 孤狼: 擦。。。。apcupsd会失联 nut在冲到到100的时候会ONBATT进入关机状态,我想想办...
  • 海运: 网络,找到相应的url编辑重发请求,firefox有此功能,其它未知。
  • knetxp: 用浏览器F12网络拦截或监听后编辑重发请求,修改url中的set为set_super,将POS...
  • Albert: 啊啊啊啊啊啊啊啊啊 我太激动了,终于好了英文区搜索了半天,翻遍了 pve 论坛没找到好方法,博...