海运的博客

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

发表评论

分类
最新文章
最近回复
  • K: 好的,谢谢,我去试试!
  • 海运: 可以试试3proxy
  • daha: PHP的怎么使用???
  • 海运: 换回了5.3内核,5.8用5.3 dtb虽然能开机且负载正常,但也有其它问题,不建议使用。
  • shangyatsen: 后面的内核高精度计时器的问题使用5.4或者5.3的dtb会正常吗?我也发现有这个日志出现。感觉...
  • 海运: 缺少相应模块?
  • lee: 你好,我执行这条语句 iptables -t mangle -A PREROUTING -m ...
  • 海运: 只更新rootfs,不更新内核,我在用5.3配19.10,懒得再升最新版了,很稳定。 注意:更...
  • lyly168: 这是手动挂载吧,请问自动挂载要怎么弄?
  • swswsw1: 请问升级后,内核更新了吗?听说N1只有在5.0.2的内核下才稳定,怕升级了之后功耗太高