Click here to Skip to main content
15,892,643 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi, I need to get bytes from HICON handle to send it from server(C++) to client(C#) but I do not know how.

i need to send the byte with
send(socket,(CHAR*)&Byte_to_send,sizeof(Byte_to_send);

Byte_to_send should be the bytes associated to HICON of each windows application, and

I've got it in this way:
HICON icon = (HICON)GetClassLong(hWnd, GCL_HICON);

What I have tried:

SIDE C++ SERVER:
HICON icon = (HICON)GetClassLong(hWnd, GCL_HICON);

ICONINFO oIconInfo;
if(::GetIconInfo(icon, &oIconInfo)==true){
cout <<"Success!"<<endl;
send(newConnection,(CHAR*)&oIconInfo,sizeof(oIconInfo),NULL);
}else{
cout <<"Failure!"<<endl;
}


Now I have to convert the stream of byte read from my client(this is made in c#) that I have received from my c++ server, and convert the array of bytes to an Image.
So I have tried to do this:

SIDE C# CLIENT:
byte[] buffer = new byte[1500];
sck.Receive(buffer);
TypeConverter tc = TypeDescriptor.GetConverter(typeof(Bitmap));
Bitmap bitmap1 = (Bitmap)tc.ConvertFrom(buffer);
imageList1.Images.Add(bitmap1);


When I try this, I receive an error at this line:
Bitmap bitmap1 = (Bitmap)tc.ConvertFrom(buffer);

This is the message error that I have received:
Unhandled exception of the 'System.ArgumentException' type System.Drawing.dll
Additional information: Invalid parameter.

I have also tried:
MemoryStream ms = new MemoryStream(buffer);
Bitmap bmp;
bmp = new Bitmap(ms);

and this other:
ImageConverter ic = new ImageConverter();
System.Drawing.Image img = (System.Drawing.Image)ic.ConvertFrom(buffer);
Bitmap bitmap1 = new Bitmap(img);

but I have received the same error message.
Posted
Updated 5-Apr-17 23:43pm

1 solution

The C++ portion is not implementing what I have suggested at Get bytes from HICON to sending via socket from server to client[^]. The ICONINFO structure does not contain the image data but only a bitmap handle. You have to send the image information and data.

Untested from scratch:
ICONINFO oIconInfo;
if (::GetIconInfo(icon, &oIconInfo))
{
    // EDIT: Modified code to create a DIB
    HBITMAP hDib = oIconInfo.hbmColor;

    // Get bitmap info for colour mask
    DIBSECTION ds;
    int nSizeDS = ::GetObject(hDib, sizeof(ds), &ds);
    // EDIT: is not a DIB: Create one
    if (sizeof(ds) != nSizeDS)
    {
        hDib = (HBITMAP)::CopyImage(oIconInfo.hbmColor, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
        nSizeDS = ::GetObject(hDib, sizeof(ds), &ds);
    }
    // Send the DIBSECTION
    send(newConnection, &ds, sizeof(ds), NULL);
    // Send raw bitmap data
    send(newConnection, ds.dsBm.bmBits, ds.dsBmih.biSizeImage, NULL);
    // EDIT: Release bitmap when a DIB copy has been created
    if (hDib && hDib != oIconInfo.hbmColor)
        ::DeleteObject(hDib);
}

On the C# receiving site receive the DIBSECTION structure first. Then receive the raw data into an buffer of size ds.dsBmih.biSizeImage. Finally create the bitmap using the Bitmap Constructor (Int32, Int32, Int32, PixelFormat, IntPtr) (System.Drawing)[^].
The parameters are:
width = ds.dsBm.bmWidth or ds.dsBmih.biWidth
height = ds.dsBm.bmHeight or ds.dsBmih.biHeight
stride = ds.dsBm.bmWidthBytes;
format = depends on ds.dsBm.bmBitsPixel; usually Format24bppRgb
scan0 = the raw data buffer
 
Share this answer
 
v2
Comments
Member 12891988 6-Apr-17 6:03am    
Thanks a lot Jochen I will try.
Member 12891988 6-Apr-17 6:25am    
When I try that piece of code,the if (sizeof(ds) == nSizeDS) condition, isn't ever verified.
How about using the two send without this if (sizeof(ds) == nSizeDS) ?
In this case without the if condition works, but I'm afraid this should be wrong.
Jochen Arndt 6-Apr-17 6:31am    
Then it is not a DIB.
I will edit my answer and add a solution.
Member 12891988 6-Apr-17 6:49am    
You think this should be correct?
I have substituted that condition with tihs if:
if(!nSizeDS){//failure}
else{//is a DIB}

here there the complete part of code:

ICONINFO oIconInfo;
if (::GetIconInfo(icon, &oIconInfo))
{
// Get bitmap info for colour mask
DIBSECTION ds;
int nSizeDS = ::GetObject(oIconInfo.hbmColor, sizeof(ds), &ds);
if(!nSizeDS){
cout <<"Failure!"<<endl;
}else{
// is a DIB
cout <<"Success!"<<endl;
// Send the DIBSECTION
send(newConnection, (CHAR*)&ds, sizeof(ds), NULL);
// Send raw bitmap
send(newConnection, (CHAR*)ds.dsBm.bmBits, ds.dsBmih.biSizeImage, NULL);
}
}
Jochen Arndt 6-Apr-17 7:06am    
Yes, it is correct.
Passing a buffer large enough to hold a DIBSECTION and passing the appropriate size is a method to detect if a bitmap is a DIB or DDB. When it is a DDB, the buffer is filled with a BITMAP structure and the return value is sizeof(BITMAP).

Then a DIB has to be created because only with that the ds.dsBm.bmBits member pointing to the raw data is valid.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900