2014-12-22 5 views
2

Я пишу программу дистанционного управления с графическим интерфейсом. Вот часть кода сервера:Как скопировать такое растровое изображение в DC?

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] = '\0'; 

     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 - ничего не появляется. Как я могу это сделать?

EDIT

Вот мой новый код:

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; 
} 

EDIT 2

Проблема решена:

То есть, как я назвал темы:

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

Как вы можете видеть, я использовал ссылку на дескриптор окна в аргументе функции вызова потока. Это тайно вызвало глупые ошибки. Никто не мог решить это без полного кода.

+0

SelectObject возвращает дескриптор к ранее выбранному объекту. Вы должны выбрать этот объект обратно в DC, когда закончите. – rrirower

ответ

1

Не создавайте совместимое растровое изображение. Создать раздел 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(.... 
+0

Еще никаких эффектов. Я также заметил, что я могу записать полученное растровое изображение в файл, но вверх ногами. – user3366592

+0

Вы перешли на DIB как на сервере, так и на клиента и удалили GlobalAlloc? – Photon

+0

Что вы имеете в виду, перейдя на DIB? Замена GetBitmapBits() с помощью GetDIBits()? И зачем удалять GlobalAlloc()? – user3366592

Смежные вопросы