Windows 7和ScreenShot.cpp GDI + PNG问题

|| 很长时间以来一直在使用XP。切换到7并尝试使用我以前运行的代码捕获屏幕截图不再起作用。简单的概念和相对通用的代码...只需找到我调用的窗口并将其另存为.png。有什么想法可能使这个坏男孩再次逃跑?无法使用我当前的设置进行调试,但是会一直执行,并在bmp-> save(...)...无法保存图像文件后吐出错误消息。编辑:也确实创建/保存了一个文件,但该文件为空白且未写入。也许位图编码或GDI搞砸了?
bool CScreenShot::Snap(CString wintitle, CString file, CString& ermsg)
{
    ermsg = \"\"; // no error message

    // create screen shot bitmap
    EnumWinProcStruct prm = {0, (LPSTR)(LPCTSTR)wintitle, 0};

    // Find the descriptor of the window with the caption wintitle
    EnumDesktopWindows(0, EnumWindowsProc, (LPARAM)&prm);
    if(!prm.hwnd)
    {
        ermsg.Format(\"couldn\'t find window \\\"%s\\\"\", wintitle);
        return false;
    }

    // Make the window the topmost window
    SetWindowPos(prm.hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
    Sleep(300);

    // Get device context for the top-level window and client rect
    HDC hDC = GetDC(prm.hwnd);
    RECT rc;
    GetClientRect(prm.hwnd, &rc);

    HDC memDC = CreateCompatibleDC(hDC);

    // Set the size and color depth for the screen shot image
    BITMAPINFO bmpInfo;
    memset(&bmpInfo, 0, sizeof(bmpInfo));
    bmpInfo.bmiHeader.biSize = sizeof(bmpInfo.bmiHeader);
    bmpInfo.bmiHeader.biWidth = rc.right - rc.left;
    bmpInfo.bmiHeader.biHeight = rc.bottom - rc.top;
    bmpInfo.bmiHeader.biPlanes = 1;
    bmpInfo.bmiHeader.biBitCount = 24;
    bmpInfo.bmiHeader.biCompression = BI_RGB;
    bmpInfo.bmiHeader.biSizeImage = bmpInfo.bmiHeader.biWidth * bmpInfo.bmiHeader.biHeight * 3;

    // Create memory buffer and perform a bit-block transfer of the color data from the window to the memory
    LPVOID  addr;
    HBITMAP memBM   = CreateDIBSection(memDC, &bmpInfo, DIB_RGB_COLORS, &addr, 0, 0);

    HGDIOBJ stdBM   = SelectObject(memDC, memBM);
    BOOL    OK      = BitBlt(memDC, 0, 0, bmpInfo.bmiHeader.biWidth, bmpInfo.bmiHeader.biHeight, hDC, 0, 0, SRCCOPY);
    ReleaseDC(prm.hwnd, hDC);

    SetWindowPos(prm.hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);

    // Initialize GDI+.
    GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR           gdiplusToken;
    if(GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL) != Ok)
    {
        ermsg.Format(\"couldn\'t start GDI+\");
        return false;
    }

    // Create a Bitmap object for work with images defined by pixel data from the GDI HBitmap and the GDI HPalette.
    Bitmap* bmp = ::new Bitmap(memBM, DIB_RGB_COLORS);
    SelectObject(memDC, stdBM);
    DeleteObject(memBM);
    DeleteDC(memDC);

    // Find the encoder for \"image/png\" mime type
    CLSID encoderClsid;
    EncoderParameters encoderParameters;

    GetEncoderClsid(L\"image/png\", &encoderClsid);

    encoderParameters.Count = 0;

    // Convert file name to Unicode (wide-char) string.
    WCHAR   fn[_MAX_PATH];
    MultiByteToWideChar(CP_THREAD_ACP, MB_PRECOMPOSED, file, file.GetLength() + 1, fn, _MAX_PATH);
    // Save the screen shot into the specified file using image encoder with the mime style \"image/png\"
    if(bmp->Save(fn, &encoderClsid, &encoderParameters) != Ok)
    {
        ermsg.Format(\"couldn\'t save image file \\\"%s\\\"\", file);
        return false;
    }

    ::delete bmp;
    GdiplusShutdown(gdiplusToken);

    return true;
}
    
已邀请:
由于某种原因,win7将不接受encoderParameters.Count == 0。将其设置为== 1,您应该被全部设置。 您可能还可以从Save()中删除该参数(已重载)     
该错误消息表示您正在尝试将文件保存到您没有写权限的文件夹中。现在,许多文件夹(如程序文件)都受到保护。由于您没有在示例代码中包含路径,因此我无法确定这是否是实际问题。 编辑:另一种可能性是位图构造不正确,这导致保存失败。构造函数的第二个参数应该是调色板的句柄,我认为DIB_RGB_COLORS在这里无效,您应该使用NULL。另外,Microsoft文档中还指出了一些警告,并且当您违反规则时,不同的OS版本可能会有不同的反应:   您负责删除GDI位图和GDI调色板。但是,在删除GDI + Bitmap :: Bitmap对象或超出范围后,才应删除GDI位图或GDI调色板。      不要将当前(或以前)选择到设备上下文中的GDI位图或GDI调色板传递给GDI + Bitmap :: Bitmap构造函数。     

要回复问题请先登录注册