c++ - 将 HICON/HCURSOR 复制到字节数组

标签 c++ sockets visual-c++ bitmapimage mouse-cursor

我们有什么办法可以将 HICONHCURSOR 转换为字节数组吗?我用谷歌搜索了所有方法,但没有找到一个通用的解决方案,下面我尝试转换HICON 颜色和掩码 BITMAP 到字节数组,并通过套接字发送它并使用 CreateIconIndirect API 创建我的图标,但如果我能够发送 直接 >HICON 就好了。

int ProcessMouse()
{

   BYTE m_hbmMaskBits[70000];
   BYTE m_hbmColorBits[70000];

   CURSORINFO CursorInfo;
   CursorInfo.cbSize = sizeof(CursorInfo);
   GetCursorInfo(&CursorInfo);

   ICONINFO iconInfo;
   if (!GetIconInfo(CursorInfo.hCursor, &iconInfo)) 
   {  
       MessageBox(NULL, _T("CreateCursor Failed"),_T("message"),MB_OK|MB_SYSTEMMODAL);          
   }
            bool isColorShape   = (iconInfo.hbmColor != NULL);
            bool isMaskShape    = (iconInfo.hbmMask != NULL);

            LONG cbSize = 0; int nWidth = 0; int nHeight = 0; int actualHeight = 0; int bmPlanes = 0;
            int bmBitsPixel = 0; int xHotspot = 0; int yHotspot = 0; int widthBytes = 0;
            // Return width,height,actualheight,bmplanes,bmbitspixel,hotsopt of cursor.
            if(!CopyIconInfo(   CursorInfo.hCursor,
                                        nWidth,
                                        nHeight,
                                        actualHeight,
                                        bmPlanes,
                                        bmBitsPixel,
                                        xHotspot,
                                        yHotspot,
                                        widthBytes  ))
            {                               
                return 0;
            }       

            std::vector<BYTE> bColor;
            std::vector<BYTE> bMask;

            int sz_hbmColor         = 0;
            int sz_hbmMask          = 0;        
            _tempWidth              = nWidth;
            _tempHeight             = nHeight;

            //If HCURSOR have both color and mask go with regular approach.
            if(isColorShape) 
            {
                                   //Convert iconInfo.hbmColor HBITMAP to Byte array.
                bColor              = HBIMAPtoBYTE(iconInfo.hbmColor,sz_hbmColor);  
                                   //Convert iconInfo.hbmMask HBITMAP to Byte array.            
                bMask               = HBIMAPtoBYTE(iconInfo.hbmMask,sz_hbmMask);
            }
            // If HCURSOR have only mask data go with new approach(split mask bitmap to color and mask).
            else if(isMaskShape) 
            {
                std::vector<BYTE> bSrcBitmap;
                int sz_hbmBitmap    = 0;    
                                   //Convert iconInfo.hbmMask HBITMAP to Byte array.        
                bSrcBitmap          = HBIMAPtoBYTE(iconInfo.hbmMask,sz_hbmBitmap);
                sz_hbmColor         = sz_hbmBitmap/2;
                sz_hbmMask          = sz_hbmBitmap/2;

                bMask.resize(bMask.size() + sz_hbmBitmap/2);
                memcpy(&bMask[bSrcBitmap.size() - sz_hbmBitmap], &bSrcBitmap[0], sz_hbmBitmap/2 * sizeof(BYTE));

                bColor.resize(bColor.size() + sz_hbmBitmap/2);
                memcpy(&bColor[bSrcBitmap.size() - sz_hbmBitmap], &bSrcBitmap[sz_hbmBitmap/2], sz_hbmBitmap/2 * sizeof(BYTE));

                //Clear at end.
                bSrcBitmap.clear();

            }

            try{
            err = memcpy_s((m_hbmMaskBits), sz_hbmMask, &(bMask[0]), sz_hbmMask );
            err = memcpy_s((m_hbmColorBits),sz_hbmColor,&(bColor[0]),sz_hbmColor);

            //Clear at end.
            bMask.clear();
            bColor.clear();

            return 1;

        }catch(...) {
            if(err) {                   
                MessageBox(NULL, _T("memcopy failed at mask or color copy"),_T("message"),MB_OK|MB_SYSTEMMODAL);    
            }
        }
}

我尝试了以下方式,但它不支持少数单色光标。

                PICTDESC pd = {sizeof(pd), PICTYPE_ICON};
                pd.icon.hicon = CursorInfo.hCursor;
                CComPtr<IPicture> pPict = NULL;
                CComPtr<IStream>  pStrm = NULL;
                BOOL res = FALSE;

                res = SUCCEEDED( ::CreateStreamOnHGlobal(NULL, TRUE, &pStrm) );
                res = SUCCEEDED( ::OleCreatePictureIndirect(&pd, IID_IPicture, TRUE, (void**)&pPict) );
                res = SUCCEEDED( pPict->SaveAsFile( pStrm, TRUE, &cbSize ) );

                if( res )
                {
                    // rewind stream to the beginning
                    LARGE_INTEGER li = {0};
                    pStrm->Seek(li, STREAM_SEEK_SET, NULL);

                    // write to file
                    DWORD dwWritten = 0, dwRead = 0, dwDone = 0;
                    while( dwDone < cbSize )
                    {
                        if( SUCCEEDED(pStrm->Read(bCursorBuff, sizeof(bCursorBuff), &dwRead)) )
                        {
                            dwDone += dwRead;
                        }
                    }
                    _ASSERTE(dwDone == cbSize);
                }
                //End of Cursor image
                pStrm.Release();
                pPict.Release();            

最佳答案

HICON 和 HCURSOR 是系统句柄,因此它们仅适用于当前计算机。

通过网络只能发送实际数据(位图字节)。然后该机器可以为其创建自己的句柄。

使用 HBITMAP 字节是正确的方法。您可以在这里找到一些详细信息: How to convert HICON to HBITMAP in VC++?

您可以使用 GetDIBits() 获取原始 HBITMAP 位。更多信息:C++/Win32: How to get the alpha channel from an HBITMAP?

关于c++ - 将 HICON/HCURSOR 复制到字节数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57688782/

相关文章:

c++ - 包含基元和对象的成员 union 如何在 C++ 中初始化?

c++ - 套接字发生了什么,当另一端关闭它时?

linux - 识别套接字客户端中的远程断开连接

c - 在c中处理文件和结构

c++ - 如何改变MFC PropertySheet的字体

c++ - 当调用带有文字值的函数时,内存中会发生什么?

c++ - void* 作为未知变量类型

sockets - Yahoo 和 Hotmail 不会回复 HELO/EHLO 到我的 SMTP 服务器

c++ - 使自定义 Directshow 过滤器接受参数

c++ - 访问单例 C++ 的段错误