Программа застревает после снятия скриншота - PullRequest
0 голосов
/ 27 января 2020
#include "screenshot.h"
#include "changewallpaper.h"

using namespace std;

int main()
{
    screenshot();
    changewallpaper();
}

Мой скриншот ();

#include <windows.h>
#include <gdiplus.h>
#include <stdio.h>

using namespace Gdiplus;

int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
   UINT  num = 0;          // number of image encoders
   UINT  size = 0;         // size of the image encoder array in bytes

   ImageCodecInfo* pImageCodecInfo = NULL;

   GetImageEncodersSize(&num, &size);
   if(size == 0)
      return -1;  // Failure

   pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
   if(pImageCodecInfo == NULL)
      return -1;  // Failure

   GetImageEncoders(num, size, pImageCodecInfo);

   for(UINT j = 0; j < num; ++j)
   {
      if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 )
      {
         *pClsid = pImageCodecInfo[j].Clsid;
         free(pImageCodecInfo);
         return j;  // Success
      }
   }

   free(pImageCodecInfo);
   return -1;  // Failure
}

void screenshot()
{
    // get the device context of the screen
    HDC hScreenDC = CreateDC("DISPLAY", NULL, NULL, NULL);

    int width = GetDeviceCaps(hScreenDC, HORZRES);
    int height = GetDeviceCaps(hScreenDC, VERTRES);

    POINT a,b;

    a.x=0;
    a.y=0;

    b.x=width;
    b.y=height;

    // copy screen to bitmap
    HDC     hScreen = GetDC(NULL);
    HDC     hDC     = CreateCompatibleDC(hScreen);
    HBITMAP hBitmap = CreateCompatibleBitmap(hScreen, abs(b.x-a.x), abs(b.y-a.y));
    HGDIOBJ old_obj = SelectObject(hDC, hBitmap);
    BOOL    bRet    = BitBlt(hDC, 0, 0, abs(b.x-a.x), abs(b.y-a.y), hScreen, a.x, a.y, SRCCOPY);

    //Initialize GDI+
    GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR gdiplusToken;
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

    Gdiplus::Bitmap bitmap(hBitmap, NULL);

    CLSID pngClsid;
    GetEncoderClsid(L"image/png", &pngClsid);
    bitmap.Save(L"D:\\Pictures\\screen.png", &pngClsid, NULL);

    // clean up
    SelectObject(hDC, old_obj);
    DeleteDC(hDC);
    ReleaseDC(NULL, hScreen);
    DeleteObject(hBitmap);

    //delete image;
    GdiplusShutdown(gdiplusToken);
}

Моя проблема в том, что changewallpaper (); никогда не бежит. Если я размещу changewallpaper (); до скриншота (); в моем основном все работает, но не, если у меня есть как выше. Мне нужна моя программа, чтобы сделать снимок экрана до того, как он поменяет обои, поэтому я не могу просто поменять их. Кто-нибудь знает в чем может быть проблема? Я невежественен.

Ответы [ 2 ]

0 голосов
/ 28 января 2020

Как @ xsoft ie, вы зависаете в image::~image().

В соответствии с GdiplusShutdown :

вы должны удалить все Ваши объекты GDI + (или выведите их go из области видимости) перед вызовом GdiplusShutdown.

Gdiplus::Bitmap bitmap(hBitmap, NULL);

bitmap сохраняются в стеке, и система автоматически освобождает их в конце их жизненный цикл (после {}). Метод scoft ie является одним из возможных решений.

Конечно, вы также можете использовать new для запроса указателей объектов GDI + в куче, как это sample :

Gdiplus::Bitmap *bitmap = new Gdiplus::Bitmap(hBitmap, NULL);
CLSID pngClsid;
GetEncoderClsid(L"image/png", &pngClsid);
bitmap->Save(L"D:\\Pictures\\screen.png", &pngClsid, NULL);

//...
delete bitmap;
GdiplusShutdown(gdiplusToken);

Или введите GdiplusStartup и GdiplusShutdown в основную функцию:

int main()
{
    GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR gdiplusToken;
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
    screenshot();
    changewallpaper();
    GdiplusShutdown(gdiplusToken);
}

И, кроме того, если вам больше не нужен hScreenDC, вызовите DeleteDC функция.

0 голосов
/ 27 января 2020

Пара изменений. Область видимости необходима, чтобы вывести растровое изображение из области видимости и очистить его после себя. Второй - выпуск hScreenD C, хотя я оставлю это в качестве упражнения для вас, чтобы увидеть, нужно ли это. Вы висели на изображении :: ~ функция изображения. Дайте мне знать, если это исправит это для вас.

  {
    Gdiplus::Bitmap bitmap(hBitmap, NULL);

    CLSID pngClsid;
    GetEncoderClsid(L"image/png", &pngClsid);
    bitmap.Save(L"c:\\temp\\screen.png", &pngClsid, NULL);
}

// clean up
SelectObject(hDC, old_obj);
DeleteDC(hDC);
ReleaseDC(NULL, hScreen);
DeleteObject(hBitmap);
DeleteDC(hScreenDC);
...