BitBlt转换为字节数组并从c++;到c# 我试图在C++中创建一个屏幕捕获DLL,并把结果字节数组发送给C。

BitBlt转换为字节数组并从c++;到c# 我试图在C++中创建一个屏幕捕获DLL,并把结果字节数组发送给C。,c#,c++,arrays,screenshot,bitblt,C#,C++,Arrays,Screenshot,Bitblt,我可以将大小返回到C#,但字节数组总是空的 这是C++代码(由我在互联网上找到的比特组成) 这是我在“ref”关键字中使用的C代码 我想我的GetDIBits可能有问题,但我不确定。我希望你们中的一些大师能让我走上正确的道路。谢谢 *编辑* 好的,非常感谢jdweng和filip为我指出了正确的方向。我现在以IntPtr的形式接收屏幕,并能够将其呈现给我的C#app。下面是现在可以工作的代码(我将在底部解释) { 尝试 { //获取屏幕尺寸 int nScreenWidth=GetSystemM

我可以将大小返回到C#,但字节数组总是空的

这是C++代码(由我在互联网上找到的比特组成)

这是我在“ref”关键字中使用的C代码

我想我的GetDIBits可能有问题,但我不确定。我希望你们中的一些大师能让我走上正确的道路。谢谢

*编辑*

好的,非常感谢jdweng和filip为我指出了正确的方向。我现在以IntPtr的形式接收屏幕,并能够将其呈现给我的C#app。下面是现在可以工作的代码(我将在底部解释)

{ 尝试 { //获取屏幕尺寸 int nScreenWidth=GetSystemMetrics(SM_CXSCREEN); int nScreenHeight=GetSystemMetrics(SM_CYSCREEN)

}

和C#

不确定我现在面临的问题是因为这样做,但是现在我从C++ DLL中得到了一个主要的内存泄漏。如果这是另一个问题,我需要创建一个新的线程吗? **编辑**

问题是通过在C++ DLL中创建一个新函数来删除返回的字符数组来解决的。


我要向菲利普表示衷心的感谢,菲利普的评论帮助我浏览了各种各样的地方,并看到了其他的东西。吉德翁,你的IntPtr是上帝的恩赐。我不知道我是如何按照吉德翁的回答来设置的。我很想奖励你们两位。

如果有人想要同样的东西,下面是对我有用的东西。我要向菲利普和吉德翁表示衷心的感谢ocica和jdweng的建议给了我一些想法,给了我很多帮助。非常感谢和感谢

C++

C#


尝试IntPtr:int hr=0;IntPtr gData=IntPtr.Zero;IntPtr gSize=IntPtr.Zero;hr=ScreenCap(gData,gSize);谢谢。我在dllimport中将字节[]更改为IntPtr,仅将gData更改为IntPtr,它返回argumentnullexception您得到了什么大小?要获得字节,需要使用封送:字节[]缓冲区=新字节[大小];元帅。复制(数据,缓冲区,0,大小);我没有得到任何方式。只有AgMUMUNULLLULL大小必须正确。请检查C++中的大小,看看它是否匹配C.*。DWORD是未签名的,因此可能需要在int中更改int到Uint。
    __declspec(dllexport) int ScreenCap(BYTE* *data, DWORD *size)
{
    try
    {
    //BITMAP bmpScreen;
    HWND DesktopHwnd = GetDesktopWindow();
    RECT DesktopParams;
    HDC DevC = GetDC(DesktopHwnd);
    GetWindowRect(DesktopHwnd,&DesktopParams);
    DWORD Width = DesktopParams.right - DesktopParams.left;
    DWORD Height = DesktopParams.bottom - DesktopParams.top;

    DWORD FileSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+(sizeof(RGBTRIPLE)+1*(Width*Height*4));
    *size = FileSize;
    char *BmpFileData = (char*)GlobalAlloc(0x0040,FileSize);

    PBITMAPFILEHEADER BFileHeader = (PBITMAPFILEHEADER)BmpFileData;
    PBITMAPINFOHEADER  BInfoHeader = (PBITMAPINFOHEADER)&BmpFileData[sizeof(BITMAPFILEHEADER)];

    BFileHeader->bfType = 0x4D42; // BM
    BFileHeader->bfSize = sizeof(BITMAPFILEHEADER);
    BFileHeader->bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);

    BInfoHeader->biSize = sizeof(BITMAPINFOHEADER);
    BInfoHeader->biPlanes = 1;
    BInfoHeader->biBitCount = 24;
    BInfoHeader->biCompression = BI_RGB;
    BInfoHeader->biHeight = Height;
    BInfoHeader->biWidth = Width;

    RGBTRIPLE *Image = (RGBTRIPLE*)&BmpFileData[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)];
    RGBTRIPLE color;

    HDC CaptureDC = CreateCompatibleDC(DevC);
    HBITMAP CaptureBitmap = CreateCompatibleBitmap(DevC,Width,Height);
    SelectObject(CaptureDC,CaptureBitmap);
    BOOL bRet = BitBlt(CaptureDC,0,0,Width,Height,DevC,0,0,SRCCOPY|CAPTUREBLT);
    //GetDIBits(CaptureDC,CaptureBitmap,0,Height,Image,(LPBITMAPINFO)BInfoHeader, DIB_RGB_COLORS);
    //GetObject(CaptureBitmap,sizeof(BITMAPFILEHEADER),&bmpScreen);
    //BYTE* lpPixels = new BYTE[sizeof((LPBITMAPINFO)BInfoHeader)];
    GetDIBits(CaptureDC, CaptureBitmap, 0, Height, *data, (LPBITMAPINFO)BInfoHeader, DIB_RGB_COLORS);
    //DWORD Junk;
    //DIBSECTION dib;
    //GetObject(CaptureBitmap, sizeof(dib), (LPVOID)&dib);

    //HANDLE FH = CreateFileA(BmpName,GENERIC_WRITE,FILE_SHARE_WRITE,0,CREATE_ALWAYS,0,0);
    //WriteFile(FH,BmpFileData,FileSize,&Junk,0);
    //CloseHandle(FH);
        GlobalFree(BmpFileData); 


        return 1;
    }
    catch(char *p)
    {
        return 0;
    }
}
        [DllImport("consoleapplication1.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern int ScreenCap(ref byte[] data, ref int size);

        public static void CapScreen()
    {
        try
        {
            int hr = 0;
            byte[] gData = null;
            int gSize = 0;
            hr = ScreenCap(ref gData, ref gSize);
            int a = 1;
        }
        catch(Exception ex)
        {
            int a = 1;
        }
__declspec(dllexport) char* ScreenCap(DWORD * size)
    *size = ((((24 * nScreenWidth + 31)&(~31)) / 8)*nScreenHeight);

    BITMAPINFO MyBMInfo = {0};
    MyBMInfo.bmiHeader.biSize = sizeof(MyBMInfo.bmiHeader); 

    // Create compatible DC, create a compatible bitmap and copy the screen using BitBlt()
    HDC hdcScreen = GetDC(GetDesktopWindow());
    HDC hdcCompatible  = CreateCompatibleDC(hdcScreen);
    HBITMAP hBmp = CreateCompatibleBitmap(hdcScreen, nScreenWidth, nScreenHeight);
    //HGDIOBJ hOldBmp = SelectObject(hdcCompatible, hBmp); 
    HGDIOBJ hOldBmp = (HGDIOBJ) SelectObject(hdcCompatible, hBmp);

    BOOL bOK = BitBlt(hdcCompatible,0,0,nScreenWidth, nScreenHeight, hdcScreen,0,0,SRCCOPY|CAPTUREBLT); 

    SelectObject(hdcCompatible, hOldBmp); // always select the previously selected object once done
    // Get the BITMAPINFO structure from the bitmap
    GetDIBits(hdcScreen, hBmp, 0, 0, NULL, &MyBMInfo, DIB_RGB_COLORS);

    // create the bitmap buffer
    char* lpPixels = new char[MyBMInfo.bmiHeader.biSizeImage];

    MyBMInfo.bmiHeader.biCompression = BI_RGB; 
    MyBMInfo.bmiHeader.biBitCount = 24;  

    // get the actual bitmap buffer
    GetDIBits(hdcScreen, hBmp, 0, MyBMInfo.bmiHeader.biHeight, (LPVOID)lpPixels, &MyBMInfo, DIB_RGB_COLORS);

    //Clean Up
    DeleteDC(hdcCompatible);
    ReleaseDC(GetDesktopWindow(), hdcScreen);
    DeleteDC(hdcScreen);
    DeleteObject(hBmp);
    //DeleteObject(hOldBmp);

    return lpPixels;
}
catch(char *p)
{
    return 0;
}
        [DllImport("consoleapplication1.dll", CallingConvention = CallingConvention.Cdecl)]
    static extern IntPtr ScreenCap(ref int size);
                while(true)
            {
                int size = 0;
                IntPtr ptr = ScreenCap(ref size);
                byte[] result = new byte[size];
                Marshal.Copy(ptr, result, 0, size);
                Marshal.Release(ptr);
                ptr = IntPtr.Zero;
                MainWindow.Dispatcher.Invoke(new Action(
                () =>
                    {
                        System.Windows.Media.ImageSource ThumbnailImage = System.Windows.Media.Imaging.BitmapSource.Create(1920, 1080, 96, 96, System.Windows.Media.PixelFormats.Bgr24, null, result, 1920 * 3);
                        MainWindow.canvasMain.Background = new System.Windows.Media.ImageBrush(ThumbnailImage);
                        result = null;
                        GC.Collect();
                        GC.WaitForPendingFinalizers();
                    }
                ), null);
            }
    char* lpPixels;
__declspec(dllexport) BOOL ScreenCapClean()
{
    delete[] lpPixels;
    return 1;
}

__declspec(dllexport) char* ScreenCap(DWORD * size)
{
    try
    {
        // Get screen dimensions
        int nScreenWidth = GetSystemMetrics(SM_CXSCREEN);
        int nScreenHeight = GetSystemMetrics(SM_CYSCREEN);

        *size = ((((24 * nScreenWidth + 31)&(~31)) / 8)*nScreenHeight);

        BITMAPINFO MyBMInfo = {0};
        MyBMInfo.bmiHeader.biSize = sizeof(MyBMInfo.bmiHeader);
        MyBMInfo.bmiHeader.biWidth = nScreenWidth;
        MyBMInfo.bmiHeader.biHeight = -nScreenHeight;
        MyBMInfo.bmiHeader.biPlanes = 1;
        MyBMInfo.bmiHeader.biBitCount = 24;
        MyBMInfo.bmiHeader.biCompression = BI_RGB;
        MyBMInfo.bmiHeader.biSizeImage = 0;
        MyBMInfo.bmiHeader.biXPelsPerMeter = 0;
        MyBMInfo.bmiHeader.biYPelsPerMeter = 0;
        MyBMInfo.bmiHeader.biClrUsed = 0;
        MyBMInfo.bmiHeader.biClrImportant = 0;

        // Create compatible DC, create a compatible bitmap and copy the screen using BitBlt()
        HDC hdcScreen = GetDC(0);
        HDC hdcCompatible  = CreateCompatibleDC(hdcScreen);
        HBITMAP hBmp = CreateCompatibleBitmap(hdcScreen, nScreenWidth, nScreenHeight);
        HGDIOBJ hOldBmp = (HGDIOBJ) SelectObject(hdcCompatible, hBmp);

        BOOL bOK = BitBlt(hdcCompatible,0,0,nScreenWidth, nScreenHeight, hdcScreen,0,0,SRCCOPY|CAPTUREBLT); 

        SelectObject(hdcCompatible, hOldBmp); // always select the previously selected object once done
        // Get the BITMAPINFO structure from the bitmap
        GetDIBits(hdcScreen, hBmp, 0, 0, NULL, &MyBMInfo, DIB_RGB_COLORS);

        // create the bitmap buffer
        lpPixels = new char[MyBMInfo.bmiHeader.biSizeImage];

        MyBMInfo.bmiHeader.biCompression = BI_RGB; 
        MyBMInfo.bmiHeader.biBitCount = 24;

        // get the actual bitmap buffer
        GetDIBits(hdcScreen, hBmp, 0, -MyBMInfo.bmiHeader.biHeight, (LPVOID)lpPixels, &MyBMInfo, DIB_RGB_COLORS);

        //Clean Up
        ReleaseDC(0, hdcScreen);
        ReleaseDC(0, hdcCompatible);
        DeleteDC(hdcCompatible);
        DeleteDC(hdcScreen);
        DeleteObject(hBmp);
        DeleteObject(hOldBmp);

        return lpPixels;
    }
    catch(char *p)
    {
        return 0;
    }
}
    [DllImport("consoleapplication1.dll", CallingConvention = CallingConvention.Cdecl)]
    static extern IntPtr ScreenCap(ref int size);
    [DllImport("consoleapplication1.dll", CallingConvention = CallingConvention.Cdecl)]
    static extern bool ScreenCapClean();

    int size = 0;
    IntPtr ptr = ScreenCap(ref size);
    byte[] result = new byte[size];
    Marshal.Copy(ptr, result, 0, size);
    Marshal.Release(ptr);
    ptr = IntPtr.Zero;
    //After doing what's required with the byte array
    bool hr = ScreenCapClean();