Member 12891988 Ответов: 1

Массив Grt байт из HICON для отправки клиенту C# и печати на listview


Привет, мне нужно получить байты из дескриптора HICON, чтобы отправить его с сервера(C++) на клиент (C#), но я не знаю, как это сделать.

мне нужно отправить байт с
send(socket, (CHAR*)&Byte_to_send, sizeof(Byte_to_send);

Byte_to_send должен быть байтами, связанными с HICON каждого приложения windows, и

Я получил его таким образом:
Hicon icon = (HICON)GetClassLong(hWnd, GCL_HICON);

Что я уже пробовал:

БОКОВОЙ СЕРВЕР C++ :
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;
}


Теперь мне нужно преобразовать поток байтов, считанных с моего клиента (это сделано на c#), который я получил с моего сервера c++, и преобразовать массив байтов в изображение.
Поэтому я попытался сделать это:

БОКОВОЙ КЛИЕНТ C# :
byte[] buffer = new byte[1500];
sck.Receive(buffer);
TypeConverter tc = TypeDescriptor.GetConverter(typeof(Bitmap));
Bitmap bitmap1 = (Bitmap)tc.ConvertFrom(buffer);
imageList1.Images.Add(bitmap1);


Когда я пытаюсь это сделать, я получаю ошибку в этой строке:
Bitmap bitmap1 = (Bitmap)tc.ConvertFrom(buffer);

Это сообщение об ошибке, которое я получил:
Unhandled exception of the 'System.ArgumentException' type System.Drawing.dll
Additional information: Invalid parameter.

Я тоже пробовал:
MemoryStream ms = new MemoryStream(buffer);
Bitmap bmp;
bmp = new Bitmap(ms);

а этот другой:
ImageConverter ic = new ImageConverter();
System.Drawing.Image img = (System.Drawing.Image)ic.ConvertFrom(buffer);
Bitmap bitmap1 = new Bitmap(img);

но я получил то же самое сообщение об ошибке.

1 Ответов

Рейтинг:
0

Jochen Arndt

Часть C++ не реализует то, что я предложил в Получить байты от HICON для отправки через сокет от сервера к клиенту[^]. Этот ICONINFO структура не содержит данных изображения, а только дескриптор растрового изображения. Вы должны отправить информацию об изображении и данные.

Непроверенный с нуля:

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

На принимающем сайте C# получите DIBSECTION сначала структура. Затем получите необработанные данные в буфер определенного размера ds.dsBmih.biSizeImage. Наконец, создайте растровое изображение с помощью Конструктор Растровых Изображений (Int32, Int32, Int32, PixelFormat, IntPtr) (System.Рисование)[^].
Параметры таковы:
width = ds.dsBm.bmWidth или ds.dsBmih.biWidth
height = ds.dsBm.bmHeight или ds.dsBmih.biHeight
stride = ds.dsBm.bmWidthBytes;
format = зависит от ds.dsBm.bmBitsPixel; обычно Format24bppRgb
scan0 = буфер необработанных данных


Member 12891988

Большое спасибо, Йохен, я постараюсь.

Member 12891988

Когда я пробую этот фрагмент кода, условие if (sizeof(ds) == nSizeDS) никогда не проверяется.
Как насчет использования двух send без этого if (sizeof(ds) = = nSizeDS)?
В этом случае без условия if работает, но я боюсь, что это должно быть неправильно.

Jochen Arndt

Тогда это не Диб.
Я отредактирую свой ответ и добавлю решение.

Member 12891988

Вы думаете, это должно быть правильно?
Я заменил это условие на tihs, если:
if (! nSizeDS) {//сбой}
else {//- это DIB}

вот там полная часть кода:

ICONINFO oIconInfo;
if (:: GetIconInfo (icon, & oIconInfo))
{
// Получить растровую информацию для цветовой маски
DIBSECTION ds;
инт nSizeDS = ::функция getobject(oIconInfo., оператор sizeof(ДС), &ампер hbmColor;ДС);
если (! nSizeDS){
cout <<"неудача!" < & lt;endl;
}еще{
// это Диб
cout <<"успех!" < & lt;endl;
// Отправить DIBSECTION
send(newConnection, (CHAR*)& ds, sizeof(ds), NULL);
// Отправить необработанное растровое изображение
отправить(newConnection, к (char*)ДС.dsBm.bmBits, ДС.dsBmih.bisizeimage С, нуль);
}
}

Jochen Arndt

Да, это правильно.
Передача буфера достаточно большого, чтобы вместить DIBSECTION а передача соответствующего размера - это метод определения того, является ли растровое изображение DIB или DDB. Когда это фабрика, буфер заполняется BITMAP структура и возвращаемое значение sizeof(BITMAP).

Тогда DIB должен быть создан, потому что только с этим ds.dsBm.bmBits элемент, указывающий на необработанные данные, является допустимым.

Member 12891988

И последнее, сторона с#,
Я обычно получаю данные с помощью этого:
Byte [] buffer = новый байт[1500];
int iRx = sck.Приемный буфер);
char[] chars = new char[iRx];
Системы.Текст.Система декодера д =.Текст.Кодирование.Кодировке utf8.GetDecoder();
int charLen = d. GetChars(buffer, 0, iRx, chars, 0);
Система.Строка szData = новая система.Строка (символы);

а потом я печатаю в listview вот так:

мыши listview1.Предметы.Добавить (szData)));

-----------------------------------------
Но если мне нужно создать значок, Я должен использовать DIBSECTION ds для создания изображения/значка;

ширина = ДС.dsBm.bmWidth;
высота = ДС.dsBm.bmHeight;
шаг = ДС.dsBm.bmWidthBytes;
Еккл...
Но как я могу преобразовать полученный байт в DIBSECTION ds?
Так что, если я преобразовать массив байтов в ДС и ДС могут использовать, чтобы создать значок.

Jochen Arndt

Я не эксперт по C# (больше C/C++).

Один из вариантов-создать структуру C# для DIBSECTION с помощью [StructLayout(LayoutKind.Последовательный, Пакет=1)].

Затем создайте байтовый массив с размером структуры и получите его в этот буфер. Наконец, приведите массив к структуре.

Member 12891988

спасибо