Я пишу программу дистанционного управления с графическим интерфейсом. Вот часть кода сервера:Как скопировать такое растровое изображение в 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);
Как вы можете видеть, я использовал ссылку на дескриптор окна в аргументе функции вызова потока. Это тайно вызвало глупые ошибки. Никто не мог решить это без полного кода.
SelectObject возвращает дескриптор к ранее выбранному объекту. Вы должны выбрать этот объект обратно в DC, когда закончите. – rrirower