2010-08-22 75 views
3

C++의 원격 제어 응용 프로그램과 유사한 작업을 시작했습니다. 특정 창 캡쳐 화면을 다른 PC로 전송하여 창에 표시하고 싶습니다. GetDIBits 및 SetDIBits 함수가 모두 성공하면 연결이 설정되고 데이터가 전송되지만 이미지가 다른쪽에 표시되지 않고 검정색으로 표시됩니다.Winsock, GetDIBits 및 SetDiBits를 사용한 비트 맵 전송

여기에 내 보내는 코드입니다 :

void GetScreenData(BITMAPINFO* bi, BYTE* buf) //gets the bitmap data 
{ 
    HBITMAP hBitmap; 
    BITMAP Bitmap; 
    RECT r; 

    HDC ActiveDC = GetDC(hActive); 
    HDC CopyDC = CreateCompatibleDC(ActiveDC); 

    GetWindowRect(hActive, &r); 

    int scrWidth = r.right-r.left; 
    int scrHeight = r.bottom-r.top; 

    hBitmap = CreateCompatibleBitmap(ActiveDC, scrWidth, scrHeight); 
    SelectObject(CopyDC, hBitmap); 

    BitBlt(CopyDC, 0, 0, scrWidth, scrHeight, ActiveDC, 0, 0, SRCCOPY); 

    GetObject(hBitmap, sizeof(BITMAP), &Bitmap); 

    int cClrBits = Bitmap.bmPlanes*Bitmap.bmBitsPixel; 

    memset(bi, 0, sizeof(BITMAPINFO)); 

    bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
    bi->bmiHeader.biWidth = Bitmap.bmWidth; 
    bi->bmiHeader.biHeight = Bitmap.bmHeight; 
    bi->bmiHeader.biPlanes = Bitmap.bmPlanes; 
    bi->bmiHeader.biBitCount = Bitmap.bmBitsPixel; 

    if(cClrBits<24) 
    { 
    bi->bmiHeader.biClrUsed = (1<<cClrBits); 
    } 

    bi->bmiHeader.biCompression = BI_RGB; 
    bi->bmiHeader.biSizeImage = ((bi->bmiHeader.biWidth * cClrBits +31) & ~31)/8*bi->bmiHeader.biHeight; 

    int i = GetDIBits(CopyDC, hBitmap, 0, scrHeight, buf, bi, DIB_RGB_COLORS); 

    printf("GetDIBits returned %i\n", i); 

    ReleaseDC(hActive, ActiveDC); 
    DeleteDC(CopyDC); 
} 

DWORD WINAPI SendImage(LPVOID param) //sends the bitmap data 
{ 
    BITMAPINFO bi; 
    BYTE* data = new BYTE[256*256*256]; 
    BYTE* buf = new BYTE[256*256*256]; 
    BYTE *packetsize1, *packetsize2; 
    int biSize = sizeof(BITMAPINFO); 
    int i, clocks, oldclocks=0; 

    while(true) 
    { 
    clocks=clock(); 

    if((clocks-oldclocks)*CLOCKS_PER_SEC<0.1) 
    { 
     continue; 
    } 

    oldclocks=clocks; 

    if(bConnected) 
    { 
     GetScreenData(&bi, buf); 

     i=0; 

     data[i++]=3; 
     packetsize1=&data[i++]; 
     packetsize2=&data[i++]; 

     memcpy(data+i, &bi, biSize); 

     i+=biSize; 

     memcpy(data+i, buf, bi.bmiHeader.biSizeImage); 

     printf("Sending image...\n"); 

     i+=bi.bmiHeader.biSizeImage; 

     *packetsize1=int(i/256); 
     *packetsize2=int(i%256); 

     send(s, (char*)data, i, 0); 
    } 
    } 
} 

그리고 여기에 수신 측이다 : 나는의가 무엇인지 확실하지 않았기 때문에

void DrawScreen(HDC hdc) //called from windows message WM_PAINT 
{ 
    HGDIOBJ hobj; 

    hobj = SelectObject(RemoteDC, hRemoteBitmap); 

    BitBlt(hdc, 0, 0, scrWidth, scrHeight, RemoteDC, 0, 0, SRCCOPY); 

    SelectObject(hdc, hobj); 
} 

DWORD WINAPI RecvData(LPVOID param) 
{ 
    BYTE* data = new BYTE[256*256*256]; 
    int packetsize, num; 
    int newWidth, newHeight; 
    int recvimgsize=0; 

    bool bAwaitingImage = false; 

    while(true) 
    { 
    if(bConnected) 
    { 
     num=recv(s, (char*)data, 3, 0); 

     if(num>0) 
     { 
     packetsize = data[1]*256+data[2]; 

     num=recv(s, (char*)(data+3), packetsize-3, 0); 
     } 

     if(num>0) 
     { 
     switch(data[0]) 
     { 
      case 2: //received information about window size (image size) 
      newWidth = data[3]*256+data[4]; 
      newHeight = data[5]*256+data[6]; 

      if(newHeight!=scrHeight || newWidth!=scrWidth) 
      { 
       scrWidth = newWidth; 
       scrHeight = newHeight; 

       RECT r; 

       GetWindowRect(hwnd, &r); 
       SetWindowPos(hwnd, NULL, r.left, r.top, scrWidth, scrHeight, 0); 

       HDC ThisDC = GetDC(hwnd); 

       DeleteDC(RemoteDC); 
       RemoteDC = CreateCompatibleDC(ThisDC); 

       DeleteObject(hRemoteBitmap); 
       hRemoteBitmap = CreateCompatibleBitmap(ThisDC, scrWidth, scrHeight); 

       SelectObject(RemoteDC, hRemoteBitmap); 

       ReleaseDC(hwnd, ThisDC); 
      } 
      break; 
      case 3: 
      { 
      BITMAPINFO bi; 
      HBITMAP hBitmap; 

      int biSize = sizeof(BITMAPINFO); 
      memcpy(&bi, data+3, biSize); 
      SetDIBits(RemoteDC, hRemoteBitmap, 0, scrHeight, data+biSize+3, &bi, DIB_RGB_COLORS); 

      InvalidateRect(hwnd, NULL, false); 

      break; 
      } 
     } 

     continue; 
     } 

     if(num==0) 
     { 
     //connection closed 
     bConnected=false; 
     }else{ 
     //error 
     bConnected=false; 
     } 
    } 
    } 
} 

내가 여기에 제시된 코드는 조금 긴 용도. 미리 감사드립니다.

+1

먼저 코드를 통해 전송하지 않고 디코딩 및 표시 코드를 확인 했습니까? –

+1

방금 ​​했어요 (어쨌든 전에는 그렇게 생각하지 않았습니다). 그것은 예상대로 작동합니다. 전송 자체에 문제가있어 ... –

+0

좋은 점은 문제의 큰 부분을 없애줍니다. 아무 것도 약속 할 수는 없지만 네트워킹 물건으로 나에게 무슨 일이 생기면 나 볼게. –

답변

0

패킷 크기를 저장하기에 충분한 양의 바이트를 할당했지만, 이제는 그 수를 늘린 것입니다. ;-)

0

게시 된 코드의 문제점은 전체 전송 데이터 길이에 대해 두 개의 BYTE ([data + 1] 및 [data + 2]) 만 할당되었다는 것입니다. 2 바이트는 최대 64K의 데이터를 처리하며 이미지는 그 이상으로 쉽게 넘어갑니다. i 값은 오버플로가 확인되지 않습니다.

코드 스 니펫을 다시 사용하려면 실제 길이를 유지할 수 있도록 비트를 추가해야합니다. 즉, 패킷 길이를 24 또는 32 비트 값으로 만들려면 추가 바이트가 있어야합니다.