0

I'm working on a screen capture method for my program. For each screen capture, I'm trying to have the image named based on the DateTime down to the second. Right now, everything would be named screen.jpg.

How can I change "screen" to the current DateTime?

I've tried playing around with the line that names it, but I just keep getting errors such as "expression must have integral or unscoped enum type." I'm not sure what that means.

void BitmapToJpg(HBITMAP hbmpImage, int width, int height)
{
    time_t now = time(0);
    char* dt = ctime(&now);

    Bitmap *p_bmp = Bitmap::FromHBITMAP(hbmpImage, NULL);
    //Bitmap *p_bmp = new Bitmap(width, height, PixelFormat32bppARGB);

    CLSID pngClsid;
    int result = GetEncoderClsid(L"image/jpeg", &pngClsid);
    if (result != -1)
        std::cout << "Encoder succeeded" << std::endl;
    else
        std::cout << "Encoder failed" << std::endl;
    p_bmp->Save(L"screen_.jpg", &pngClsid, NULL);
    delete p_bmp;
}

UPDATE:

This version hasn't given me any errors, so I'm going to try to use it. I'll update this post to verify if it worked properly or not when my program attempts to use it! :)

Revised code:

void BitmapToJpg(HBITMAP hbmpImage, int width, int height)
{
    time_t now = time(0);
    char* dt = ctime(&now);

    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
    std::wstring wide = converter.from_bytes(dt);


    Bitmap *p_bmp = Bitmap::FromHBITMAP(hbmpImage, NULL);
    //Bitmap *p_bmp = new Bitmap(width, height, PixelFormat32bppARGB);

    CLSID pngClsid;
    int result = GetEncoderClsid(L"image/jpeg", &pngClsid);
    if (result != -1)
        std::cout << "Encoder succeeded" << std::endl;
    else
        std::cout << "Encoder failed" << std::endl;
    std::wstring fileName = std::wstring(L"screen_") + wide + (L".jpg");
    p_bmp->Save(fileName.c_str(), &pngClsid, NULL);
    delete p_bmp;
}
BigBlackBunny
  • 77
  • 1
  • 5
  • Did you try converting that date to string? – wdc May 30 '17 at 21:17
  • As the Save method accepts wide string, you need to convert the char* dt to wstring: https://stackoverflow.com/questions/2573834/c-convert-string-or-char-to-wstring-or-wchar-t and then just concatenate the result to the filename extension. – Dom May 30 '17 at 21:29
  • std::time(0) "is almost always an integral value holding the number of seconds (not counting leap seconds) since 00:00, Jan 1 1970 UTC, corresponding to POSIX time" Thus for a unique (per second) file name, you might consider appending to "image/" the POSIX time "std::to_string(std::time(0))" and then maybe "/jpeg"? – 2785528 May 30 '17 at 22:22
  • format the date as a string with strftime – Jerry Jeremiah May 30 '17 at 22:34
  • You're going to need to do something about the colons in the time if you want to use it as a filename in Windows. I'd suggest formatting the time as YYYYMMDD_HHMMSS and then it'll be easy to sort. – Retired Ninja May 30 '17 at 23:32

1 Answers1

4

You're actually almost there. However, one more thing needs to be done in order to get this working. As of the latest edit of the code, you pass the first parameter of Bitmap::Save (and, inherently, Image::Save) of type std::wstring, the latter being a typedef for std::basic_string<wchar_t>. However the method requires its first parameter to be WCHAR *. So, all you need to do, is to re-write problematic lines as follows:

std::wstring fileName = std::wstring(L"screen_") + wide + L(".jpg");
p_bmp->Save(fileName.c_str(), &pngClsid, NULL);

This should do the trick.

The reason of the problem is, std::basic_string<CharT> can't be converted to CharT* implicitly, and there is a specific interface for such conversion, namely std::basic_string<CharT>::c_str().

iehrlich
  • 3,572
  • 4
  • 34
  • 43