如何将此类位图复制到 DC

How to copy such bitmap to a DC?

本文关键字:复制 DC 位图      更新时间:2023-10-16

我正在编写一个带有GUI的远程控制程序。下面是服务器代码的一部分:

HDC desktopHdc = GetDC(NULL);
int bm_x = GetDeviceCaps(desktopHdc, HORZRES);
int bm_y = GetDeviceCaps(desktopHdc, VERTRES);
DWORD bmSize = ((bm_x * 32 + 31) / 32) * bm_y * 4;
HDC memHdc = CreateCompatibleDC(desktopHdc);
HBITMAP bitmap = CreateCompatibleBitmap(desktopHdc, bm_x, bm_y);
while(TRUE)
{
    SelectObject(memHdc, (HGDIOBJ)bitmap);
    HANDLE hDIB = GlobalAlloc(GHND, bmSize);
    char* bmbits = (char*)GlobalLock(hDIB);
    BitBlt(memHdc, 0, 0, bm_x, bm_y, desktopHdc, 0, 0, SRCCOPY);
    GetBitmapBits(bitmap, bmSize, bmbits);
    int bytes = send(secondarySocket, bmbits, bmSize, 0);
    if(bytes == 0 || bytes == -1)
    {
        MessageBox(NULL, "disconnected", "", 0);
        break;
    }
    GlobalUnlock(hDIB);
    GlobalFree(hDIB);
    Sleep(1000);
}

下面是一些客户端代码:

HDC windowHdc = GetDC(hwnd);
HDC memHdc = CreateCompatibleDC(windowHdc);
// bm_x and bm_y are sent by the server and received by the client
DWORD bmSize = ((bm_x * 32 + 31) / 32) * bm_y * 4;
while(TRUE)
{
    HANDLE hDIB = GlobalAlloc(GHND, bmSize);
    char* buf = (char*)GlobalLock(hDIB);
    int bytes = recv(mainSocket, buf, bmSize, 0);
    if(bytes == 0 || bytes == -1)
    {
        MessageBox(NULL, "disconnected", "", 0);
        break;
    }
    else
    {
        buf[bytes] = '';
        HBITMAP bmp = CreateCompatibleBitmap(memHdc, bm_x, bm_y);
        SetBitmapBits(bmp, bmSize, buf);
        SelectObject(memHdc, bmp);
        BitBlt(windowHdc, 0, 0, bm_x, bm_y, memHdc, 0, 0, SRCCOPY); // should copy received bitmap to the window DC
    }
    GlobalUnlock(hDIB);
    GlobalFree(hDIB);
}

我在客户端中正确接收了整个缓冲区。我用它制作了一个位图。然后我只是无法将其复制到窗口 DC - 什么也没出现。我该怎么做?

编辑

这是我的新代码:

DWORD thServerSend(LPVOID param) 
{
    HDC memHdc = CreateCompatibleDC(desktopHdc);
    HBITMAP bitmap;
    while(TRUE)
    {
        BITMAPINFO bmi;
        ZeroMemory(&bmi,sizeof(BITMAPINFO));
        bmi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
        bmi.bmiHeader.biWidth=bm_x;
        bmi.bmiHeader.biHeight=bm_y;
        bmi.bmiHeader.biPlanes=1;
        bmi.bmiHeader.biBitCount=32;
        char* bmbits;
        bitmap = CreateDIBSection(memHdc, &bmi, DIB_RGB_COLORS, (void**)&bmbits, NULL, 0);
        HBITMAP restore = (HBITMAP)SelectObject(memHdc, (HGDIOBJ)bitmap);
        BitBlt(memHdc, 0, 0, bm_x, bm_y, desktopHdc, 0, 0, SRCCOPY);
        int bytes = send(secondarySocket, bmbits, bmSize, 0);
        if(bytes == 0 || bytes == -1)
        {
            MessageBox(NULL, "disconnected", "", 0);
            break;
        }
        std::cout << "bmsize: " << bmSize << " bytes: " << bytes << " bmbits: " << bmbits << std::endl; // for debugging
        SelectObject(memHdc, restore);
        DeleteObject(bitmap);
        Sleep(1000);
    }
    DeleteDC(memHdc);
    DeleteObject(bitmap);
    shutdown(mainSocket, SD_BOTH);
    shutdown(secondarySocket, SD_BOTH);
    return 0;
}
DWORD thClient(LPVOID param) // window handle is passed through "param" parameter
{
    HDC windowHdc = GetDC((HWND)param);
    HDC memHdc = CreateCompatibleDC(windowHdc);
    HBITMAP restore;
    while(TRUE)
    {
        BITMAPINFO bmi;
        ZeroMemory(&bmi,sizeof(BITMAPINFO));
        bmi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
        bmi.bmiHeader.biWidth=bm_x;
        bmi.bmiHeader.biHeight=bm_y;
        bmi.bmiHeader.biPlanes=1;
        bmi.bmiHeader.biBitCount=32;
        char* buffer;
        HBITMAP bitmap = CreateDIBSection(windowHdc, &bmi, DIB_RGB_COLORS, (void**)&buffer, NULL, 0);
        int bytes = recv(mainSocket, buffer, bmSize, 0);
        if(bytes == 0 || bytes == -1)
        {
            MessageBox(NULL, "Disconnected.", "", 0);
            break;
        }
        else
        {
            restore = (HBITMAP)SelectObject(memHdc,bitmap);
            BitBlt(windowHdc, 0, 0, bm_x, bm_y, memHdc, 0, 0, SRCCOPY);
            std::cout << "bmsize: " << bmSize << " bytes: " << bytes << " bmbits: " << buffer << std::endl; // for debugging
            SelectObject(memHdc, restore);
        }
    }
DeleteDC(memHdc);
return 0;
}

编辑 2

已解决的问题:

也就是说,我如何调用线程:

CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)thClient, (PVOID)&hwnd, 0, NULL);
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)thServerSend, (PVOID)hwnd, 0, NULL);

如您所见,我在线程调用函数的参数中使用了对窗口句柄的引用。这秘密地造成了愚蠢的错误。没有完整的代码,没有人能解决它。

不要创建兼容的位图。创建 DIB 部分:http://msdn.microsoft.com/en-us/library/windows/desktop/dd183494%28v=vs.85%29.aspx

BITMAPINFO bi;
ZeroMemory(&bi,sizeof(BITMAPINFO));
bi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biWidth=Width;
bi.bmiHeader.biHeight=Height;
bi.bmiHeader.biPlanes=1;
bi.bmiHeader.biBitCount=32;
char* buffer;
HBITMAP bitmap=CreateDIBSection(dc,&bi,DIB_RGB_COLORS,&buffer,NULL,0);
// copy pixels to buffer
SelectObject(dc,bitmap);
BitBlt(....