Reputation:
So I have a working HBITMAP which can be set to the clipboard using SetClipboardData
. What I'm trying to do is send the HBITMAP to another application (without writing anything to disk) which will receive it and be able set it to the clipboard just as the original application could do. I know that you can't just send the handle so I used GetObject
and GetDIBits
and sent the collected data across. I've looked at all the other people's stackoverflow questions about sending hbitmaps over a network but none of the answers given have worked for me.
UPDATE: Code still not working after updated.
This is now what it shows as when I paste the clipboard into mspaint
Here's what my code looks like now:
Client:
#include <WinSock2.h>
#include <Windows.h>
#include <stdio.h>
#pragma comment(lib, "Ws2_32.lib")
#define Port 6000
SOCKET Socket, Sub;
WSADATA Winsock;
sockaddr_in Addr;
sockaddr_in IncomingAddress;
int AddressLen = sizeof(IncomingAddress);
BOOL send_function(BYTE* dib, int dib_size) {
WSAStartup(MAKEWORD(2, 2), &Winsock); // Start Winsock
if (LOBYTE(Winsock.wVersion) != 2 || HIBYTE(Winsock.wVersion) != 2) // Check version
{
WSACleanup();
return 0;
}
Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
ZeroMemory(&Addr, sizeof(Addr));
Addr.sin_family = AF_INET;
Addr.sin_port = htons(Port);
bind(Socket, (sockaddr*)&Addr, sizeof(Addr));
if (listen(Socket, 1) == SOCKET_ERROR)
{
printf("listening error\n");
}
else
{
printf("listening ok\n");
}
if (Sub = accept(Socket, (sockaddr*)&IncomingAddress, &AddressLen))
{
char* ClientIP = inet_ntoa(IncomingAddress.sin_addr);
int ClientPort = ntohs(IncomingAddress.sin_port);
printf("Client conncted!\n");
printf("IP: %s:%d\n", ClientIP, ClientPort);
printf("Sending data .. \n");
char bufsize[10];
sprintf(bufsize, "%d", dib_size);
send(Sub, (char*)bufsize, 10, 0);
send(Sub, (char*)dib, dib_size, 0);
closesocket(Sub);
closesocket(Socket);
WSACleanup();
}
}
int main()
{
HWND hwnd = GetWindow(GetForegroundWindow(), GW_HWNDLAST);
RECT rc;
GetWindowRect(hwnd, &rc);
HDC hdcScreen = GetDC(NULL);
HDC hdc = CreateCompatibleDC(hdcScreen);
HBITMAP hbmp = CreateCompatibleBitmap(hdcScreen,
rc.right - rc.left, rc.bottom - rc.top);
SelectObject(hdc, hbmp);
//Print to memory hdc
PrintWindow(hwnd, hdc, NULL);
auto hcopy = (HBITMAP)CopyImage(hbmp, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
BITMAP bm;
GetObject(hcopy, sizeof(bm), &bm);
BITMAPINFOHEADER bi = { sizeof(bi) };
bi.biWidth = bm.bmWidth;
bi.biHeight = bm.bmHeight;
bi.biBitCount = bm.bmBitsPixel;
bi.biPlanes = bm.bmPlanes;
bi.biSizeImage = bm.bmWidthBytes * bm.bmHeight;
int dib_size = sizeof(bi) + bi.biSizeImage;
BYTE* dib = new BYTE[dib_size];
memcpy(dib, &bi, sizeof(bi));
memcpy(dib + sizeof(bi), bm.bmBits, bi.biSizeImage);
send_function(dib, dib_size);
//cleanup
DeleteObject(hcopy);
delete[]dib;
getchar();
return 0;
}
Server:
#include <WinSock2.h>
#include <Windows.h>
#include <stdio.h>
#pragma comment(lib, "Ws2_32.lib")
SOCKET Socket;
WSADATA Winsock;
sockaddr_in Addr;
int Addrlen = sizeof(Addr);
void receive_function(BYTE* dib, int dib_size)
{
BITMAPINFOHEADER* bi = (BITMAPINFOHEADER*)dib;
BYTE* bits = dib + sizeof(bi);
HBITMAP hbitmap = CreateBitmap(bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount, bits);
OpenClipboard(NULL);
EmptyClipboard();
SetClipboardData(CF_BITMAP, hbitmap);
CloseClipboard();
printf("Clipboard set!");
getchar();
}
int main()
{
WSAStartup(MAKEWORD(2, 2), &Winsock); // Start Winsock
if (LOBYTE(Winsock.wVersion) != 2 || HIBYTE(Winsock.wVersion) != 2) // Check version
{
WSACleanup();
return 0;
}
Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
ZeroMemory(&Addr, sizeof(Addr)); // clear the struct
Addr.sin_family = AF_INET; // set the address family
Addr.sin_addr.s_addr = inet_addr("127.0.0.1");
Addr.sin_port = htons(6000); // set the port
if (connect(Socket, (sockaddr*)&Addr, sizeof(Addr)) < 0)
{
printf("Connection failed !\n");
getchar();
return 0;
}
printf("Connection successful !\n");
printf("Receiving data .. \n");
int dib_size = 0;
char Filesize[10];
if (recv(Socket, Filesize, 10, 0)) // File size
{
dib_size = atoi(Filesize);
}
printf("File size: %d\n", dib_size);
BYTE* dib = new BYTE[dib_size];
if (recv(Socket, (char*)dib, dib_size, 0))
{
receive_function(dib, dib_size);
}
getchar();
return 0;
}
Any and all help appreciated!
Upvotes: -3
Views: 571
Reputation: 6299
Please use LoadImage to load BMP image.
Because the code you provided in your question is to get the background of the desktop, and the GIF picture you provided is a local image file loaded with api(GIF is too vague and I can't identify which API you are using).
After my test, there should be an error occurred while yoou loading the bmp image.
Modified code:
Server:
#include <WinSock2.h>
#include <Windows.h>
#include <stdio.h>
#include <gdiplus.h>
using namespace Gdiplus;
#pragma comment (lib,"Gdiplus.lib")
#pragma comment(lib, "Ws2_32.lib")
#pragma warning(disable: 4996)
SOCKET Socket;
WSADATA Winsock;
sockaddr_in Addr;
int Addrlen = sizeof(Addr);
HBITMAP hbitmap;
int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
UINT num = 0; // number of image encoders
UINT size = 0; // size of the image encoder array in bytes
ImageCodecInfo* pImageCodecInfo = NULL;
GetImageEncodersSize(&num, &size);
if (size == 0)
return -1; // Failure
pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
if (pImageCodecInfo == NULL)
return -1; // Failure
GetImageEncoders(num, size, pImageCodecInfo);
for (UINT j = 0; j < num; ++j)
{
if (wcscmp(pImageCodecInfo[j].MimeType, format) == 0)
{
*pClsid = pImageCodecInfo[j].Clsid;
free(pImageCodecInfo);
return 0; // Success
}
}
free(pImageCodecInfo);
return -1; // Failure
}
void receive_function(BYTE* dib, int dib_size)
{
BITMAPINFOHEADER* bi = (BITMAPINFOHEADER*)dib;
BYTE* bits = dib + sizeof(bi);
hbitmap = CreateBitmap(bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount, bits);
/*OpenClipboard(NULL);
EmptyClipboard();
SetClipboardData(CF_BITMAP, hbitmap);
CloseClipboard();
printf("Clipboard set!");*/
// getchar();
}
int main()
{
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
WSAStartup(MAKEWORD(2, 2), &Winsock); // Start Winsock
if (LOBYTE(Winsock.wVersion) != 2 || HIBYTE(Winsock.wVersion) != 2) // Check version
{
WSACleanup();
return 0;
}
Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
ZeroMemory(&Addr, sizeof(Addr)); // clear the struct
Addr.sin_family = AF_INET; // set the address family
Addr.sin_addr.s_addr = inet_addr("127.0.0.1");
Addr.sin_port = htons(6000); // set the port
if (connect(Socket, (sockaddr*)&Addr, sizeof(Addr)) < 0)
{
printf("Connection failed !\n");
getchar();
return 0;
}
printf("Connection successful !\n");
printf("Receiving data .. \n");
int dib_size = 0;
char Filesize[10];
if (recv(Socket, Filesize, 10, 0)) // File size
{
dib_size = atoi(Filesize);
}
printf("File size: %d\n", dib_size);
BYTE* dib = new BYTE[dib_size];
if (recv(Socket, (char*)dib, dib_size, 0))
{
receive_function(dib, dib_size);
}
CLSID myClsId;
int retVal = GetEncoderClsid(L"image/bmp", &myClsId);
Bitmap *image = new Bitmap(hbitmap, NULL);
image->Save(L"output.bmp", &myClsId, NULL);
delete image;
GdiplusShutdown(gdiplusToken);
getchar();
return 0;
}
Updated:
With the bitmap pixels, note that the captured data has reversed order with the normal bitmap data, so we have to convert it to the correct.
Modeified client code:
#include <WinSock2.h>
#include <Windows.h>
#include <stdio.h>
#pragma comment(lib, "Ws2_32.lib")
#pragma warning(disable: 4996)
#define Port 6000
SOCKET Socket, Sub;
WSADATA Winsock;
sockaddr_in Addr;
sockaddr_in IncomingAddress;
int AddressLen = sizeof(IncomingAddress);
BOOL send_function(BYTE* dib, int dib_size) {
WSAStartup(MAKEWORD(2, 2), &Winsock); // Start Winsock
if (LOBYTE(Winsock.wVersion) != 2 || HIBYTE(Winsock.wVersion) != 2) // Check version
{
WSACleanup();
return 0;
}
Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
ZeroMemory(&Addr, sizeof(Addr));
Addr.sin_family = AF_INET;
Addr.sin_port = htons(Port);
bind(Socket, (sockaddr*)&Addr, sizeof(Addr));
if (listen(Socket, 1) == SOCKET_ERROR)
{
printf("listening error\n");
}
else
{
printf("listening ok\n");
}
if (Sub = accept(Socket, (sockaddr*)&IncomingAddress, &AddressLen))
{
char* ClientIP = inet_ntoa(IncomingAddress.sin_addr);
int ClientPort = ntohs(IncomingAddress.sin_port);
printf("Client conncted!\n");
printf("IP: %s:%d\n", ClientIP, ClientPort);
printf("Sending data .. \n");
char bufsize[10];
sprintf(bufsize, "%d", dib_size);
send(Sub, (char*)bufsize, 10, 0);
send(Sub, (char*)dib, dib_size, 0);
closesocket(Sub);
closesocket(Socket);
WSACleanup();
}
}
int main()
{
HBITMAP Bitmap = (HBITMAP)LoadImage(NULL,
"C:\\Users\\strives\\Desktop\\timg.bmp", // file containing bitmap
IMAGE_BITMAP, // type = bitmap
0, 0, // original size
LR_LOADFROMFILE);
auto hcopy = (HBITMAP)CopyImage(Bitmap, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
BITMAP bm;
GetObject(hcopy, sizeof(bm), &bm);
BITMAPINFOHEADER bi = { sizeof(bi) };
bi.biWidth = bm.bmWidth;
bi.biHeight = bm.bmHeight;
bi.biBitCount = bm.bmBitsPixel;
bi.biPlanes = bm.bmPlanes;
bi.biSizeImage = bm.bmWidthBytes * bm.bmHeight;
//convert
LONG lineSize = bi.biWidth * bi.biBitCount / 8;
BYTE* pLineData = new BYTE[lineSize];
BYTE* pStart;
BYTE* pEnd;
BYTE* pData = (BYTE*)bm.bmBits;
LONG lineStart = 0;
LONG lineEnd = bi.biHeight - 1;
while (lineStart < lineEnd)
{
pStart = pData + (lineStart * lineSize);
pEnd = pData + (lineEnd * lineSize);
// Swap the top with the bottom
memcpy(pLineData, pStart, lineSize);
memcpy(pStart, pEnd, lineSize);
memcpy(pEnd, pLineData, lineSize);
// Adjust the line index
lineStart++;
lineEnd--;
}
int dib_size = sizeof(bi) + bi.biSizeImage;
memcpy(pData, &bi, sizeof(bi));
send_function(pData, dib_size);
//cleanup
DeleteObject(hcopy);
delete pLineData;
getchar();
return 0;
}
Upvotes: 0
Reputation: 136
You can save a HBITMAP into memory same as stored in File..
make GDI+ Bitmap using Bitmap::FromHBITMAP()
.
Using CreateStreamOnHGlobal
, you can create stream on memory..
and using GDI+ Bitmap::Save()
, you can write a bitmap file into memory..
send it to socket..
On the other side of socket, memory to Stream and to Bitmap.
Search MSDN. You can find example...
Upvotes: 1