Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/125.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ [MFC/C+;+;]发送CBitmap';s位在套接字上,并在接收器端重新构造它_C++_Mfc_Asyncsocket - Fatal编程技术网

C++ [MFC/C+;+;]发送CBitmap';s位在套接字上,并在接收器端重新构造它

C++ [MFC/C+;+;]发送CBitmap';s位在套接字上,并在接收器端重新构造它,c++,mfc,asyncsocket,C++,Mfc,Asyncsocket,我是MFC的新手,尝试通过一个基于VS2008的MFC对话项目来学习它。以下是我所做的档案: 首先,我成功地将文件夹中的图片列表显示到列表框控件中。之后,我还处理了listbox每一行上的click事件,以加载图片并将其显示到右侧的picture控件(键入位图)。为了便于理解,您可以看到下图: 这是代码。注意m_ListCtrl和static_picture是列表框和图片控件的变量: void CMyClientDlg::OnLbnSelchangeList1(){ CString imag

我是MFC的新手,尝试通过一个基于VS2008的MFC对话项目来学习它。以下是我所做的档案:

首先,我成功地将文件夹中的图片列表显示到列表框控件中。之后,我还处理了listbox每一行上的click事件,以加载图片并将其显示到右侧的picture控件(键入位图)。为了便于理解,您可以看到下图:

这是代码。注意
m_ListCtrl
static_picture
是列表框和图片控件的变量:

void CMyClientDlg::OnLbnSelchangeList1(){

CString imagePath;
m_ListCtrl.GetText(m_ListCtrl.GetCurSel(),imagePath);

CImage picture;
picture.Load(imagePath);

if (!picture.IsNull())
{
    float screenWidth = 200, screenHeight = 200;
    float imageWidth = picture.GetWidth();
    float imageHeight = picture.GetHeight();

    //scaling:
    float pictureRatio = imageWidth/ imageHeight;
    float newImageWidth;
    float newImageHeight;
    int aligmentX = 0;
    int aligmentY = 0;
    if (pictureRatio <= 1)
    {
        newImageWidth = imageWidth*(screenHeight/imageHeight);
        newImageHeight = screenHeight;
        aligmentX = (screenWidth-newImageWidth)/2;
    }
    else
    {
        newImageWidth = screenWidth;
        newImageHeight = imageHeight*(screenWidth/imageWidth);
        aligmentY = (screenHeight - newImageHeight)/2;
    }
    //end scaling.
    CDC *screenDC = GetDC();
    CDC mDC;
    mDC.CreateCompatibleDC(screenDC);

    CBitmap bitMap;
    bitMap.CreateCompatibleBitmap(screenDC, screenWidth, screenHeight);
    CBitmap *pob = mDC.SelectObject(&bitMap);
    mDC.SetStretchBltMode(HALFTONE);
    picture.StretchBlt(mDC.m_hDC, aligmentX, aligmentY, newImageWidth, newImageHeight, 0, 0, imageWidth, imageHeight, SRCCOPY);
    mDC.SelectObject(pob);

    /*.......code to convert bitmap to BYTE* ........*/
    /*.......code to send BYTE* over socket........*/       

    //display the bit map
    static_picture.SetBitmap((HBITMAP)bitMap.Detach());

    //clean up
    ReleaseDC(screenDC);
}   
然后通过套接字发送该数组:

UpdateData(TRUE);
char *socketBuffer = reinterpret_cast<char*>(bmpBuffer);
send(m_ClientSocket, socketBuffer, sizeof(socketBuffer), 0);
//clean up after send
GlobalFree((HGLOBAL)bmpBuffer);
UpdateData(真);
char*socketBuffer=reinterpret_cast(bmpBuffer);
发送(m_ClientSocket,socketBuffer,sizeof(socketBuffer),0);
//发送后清理
GlobalFree((HGLOBAL)bmpBuffer);
在另一个对话框上。注意:我已将位图的尺寸硬编码为160000,只是为了简化问题:

void CMyServer2Dlg::OnReceive(){    
char *socketBuffer = new char [1025];
int iLen; 
iLen = recv(m_sConnected, socketBuffer, 1025, NULL);
if(iLen==SOCKET_ERROR)
{
    AfxMessageBox("Could not Receive");
}
else
{
    BYTE* bmpBuffer = reinterpret_cast<BYTE*>(socketBuffer);

    //re-construct the bitmap
    CBitmap clone;
    CDC *screenDC = GetDC();
    CDC mDC;
    mDC.CreateCompatibleDC(screenDC);

    clone.CreateCompatibleBitmap(screenDC, 200, 200);
    clone.SetBitmapBits(160000,bmpBuffer);

    //Picture control(type bitmap) has variable "static_picture"
    static_picture.SetBitmap((HBITMAP)clone.Detach());

    UpdateData(FALSE);
    ReleaseDC(screenDC);
    GlobalFree((HGLOBAL)bmpBuffer);
}
delete socketBuffer;
void CMyServer2Dlg::OnReceive(){
char*socketBuffer=新字符[1025];
内伊伦;
iLen=recv(m_已连接,socketBuffer,1025,NULL);
如果(iLen==SOCKET\u错误)
{
AfxMessageBox(“无法接收”);
}
其他的
{
字节*bmpBuffer=重新解释强制转换(socketBuffer);
//重新构造位图
CBitmap克隆;
CDC*screenDC=GetDC();
疾病预防控制中心;
mDC.CreateCompatibleDC(screenDC);
CreateCompatibleBitmap(screenDC,200200);
克隆.SetBitmapBits(160000,bmpBuffer);
//图片控件(位图类型)具有变量“静态图片”
static_picture.SetBitmap((HBITMAP)clone.Detach());
更新数据(假);
ReleaseDC(screenDC);
GlobalFree((HGLOBAL)bmpBuffer);
}
删除socketBuffer;

而且,它根本不起作用……请告诉我我把它弄糟了在哪里?很抱歉发了这么长的帖子……

我认为最可能的原因是你的接收器没有获得图片的所有数据。我建议你在发送时将位图的大小放入包中,以便接收器获得正确的大小

下面是一些示例代码。请注意,它们只是为了展示想法,您可能需要进行一些调试以确保它们正常工作

步骤1:打包位图的大小。我想这里的大小小于64K,因此使用int。如果大小可能大于64K,则可能需要使用INT64

int bmpDemension = bmpProperties.bmWidthBytes*bmpProperties.bmHeight;
int bufferSize = bmpDemension + sizeof(int);
BYTE* bmpBuffer=(BYTE*)GlobalAlloc(GPTR, bufferSize );
bitMap.GetBitmapBits(bmpDemension,bmpBuffer + sizeof(int));
memcpy(bmpBuffer, &bmpDemension, sizeof(int)); // put the size into the head of package.
第二步:发出去 请注意,我在这里使用bufferSize,因为sizeof(bmpBuffer)返回指针大小,即4,而不是空间大小

UpdateData(TRUE);
char *socketBuffer = reinterpret_cast<char*>(bmpBuffer);
send(m_ClientSocket, socketBuffer, bufferSize , 0);
 //clean up after send
GlobalFree((HGLOBAL)bmpBuffer);

同样,这些代码只是为了演示这个想法。

在研究解决方案时使用+1(是的,我认为GetBitmapBits和SetBitmapBits是正确的函数)。但是,“不工作”是什么意思?谢谢你的回复。在接收端,它只显示200x200黑色,而不是我在发送端单击的图像。我还尝试在发送端重新构建位图进行测试,它工作正常。如果错误,请更正我。你的接收缓冲区是1025,位图大小是160000。缓冲区足够大吗?还有,甚至虽然您要求一次接收1025个字节,但您可能无法全部接收到它们-您可能需要多次致电recv以获取所有字节。是否有理由不将位图作为位图文件发送/接收?感谢您的帮助!我将尝试您的建议并告诉您结果。这很有效!您非常棒。不过,我们需要清除错误每次绘制图像后都会出现socketBuffer,因为客户端可能会单击另一个图像并导致崩溃。无论如何,非常感谢您的帮助,我不敢相信我在开始时错过了指针大小这样基本的东西…很好学。是的,关于清理的事情,您是对的。很容易忘记。欢迎您顺便问一下:Dbtw,有什么方法可以避免循环?因为这会严重影响性能。如果客户端点击太快,服务器端可能会挂起。Windows/Visual Studio上的
int
是4个字节。它最多可以表示2^31-1的值。64k-1将是无符号16位数据类型的最大可表示值(例如
unsigned short
)。指针可以是4或8个字节。除此之外,您的大小计算是错误的。它完全忽略了每像素位值以及扫描线填充。此解决方案需要大量运气才能工作。
UpdateData(TRUE);
char *socketBuffer = reinterpret_cast<char*>(bmpBuffer);
send(m_ClientSocket, socketBuffer, bufferSize , 0);
 //clean up after send
GlobalFree((HGLOBAL)bmpBuffer);
void CMyServer2Dlg::OnReceive(){    
char socketBuffer[1025];
int iLen; 
iLen = recv(m_sConnected, socketBuffer, sizeof(int), NULL); //read the bigmap size
if(iLen==SOCKET_ERROR)
{
AfxMessageBox("Could not Receive");
}
else
{
int dimension = *((int *) socketBuffer);
char * bitmapBuffer = new char[dimension];
int readSize = dimension;
char * pBuffer = bitmapBuffer;
while (readSize > 0)
{
    int sizeToRead = readSize > sizeof(socketBuffer) ? sizeof(socketBuffer) : readSize;
    iLen = recv(m_sConnected, socketBuffer, sizeToRead , NULL);
    memcpy(pBuffer, socketBuffer, iLen);
    pBuffer += iLen;
    readSize -= iLen;
}
// when the loop done, you shall have all data in bitmapBuffer.
....    
// I leave the remaining code to you.