CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 9 of 9
  1. #1
    Join Date
    Mar 2001
    Location
    Colorado
    Posts
    241

    HBITMAP to HGLOBAL

    Hello all, I am working with third party software that stores bitmap handles as HGLOBAL's. So I am trying to figure out how to convert HBITMAP to HGLOBAL. Here is what I tried to no avail.


    HBITMAP hBmp = (HBITMAP)m_bmp; // m_bmp is a CBitmap
    HGLOBAL hBitmap = ::GlobalAlloc(GPTR, nBmpSize);

    hBitmap = (HGLOBAL)hBmp;


    When the third party software tries to use hBitmap, the software crashes. Can someone please tell me how to convert an HBITMAP to HGLOBAL.

    Thanks in advance,

    Wade

  2. #2
    Join Date
    May 1999
    Location
    ALABAMA, USA
    Posts
    9,917
    HGLOBAL and HBITMAP are both handles. Just cast one type to another:

    HGLOBAL hBmp = (HGLOBAL)m_bmp
    There are only 10 types of people in the world:
    Those who understand binary and those who do not.

  3. #3
    Join Date
    Mar 2001
    Location
    Colorado
    Posts
    241
    Thanks John,

    I tried that and it doesn't work.

    In the third party software, this is how they use the handle I give them.

    char* ptr = (char*)::GlobalLock(hBitmap);

    hBitmap is the HGLOBAL that I gave them, and after this line of code, ptr = NULL;

    Is there anything else I need to do?

    Thanks again,
    Wade

  4. #4
    Join Date
    May 1999
    Location
    ALABAMA, USA
    Posts
    9,917
    I thought third party program is just using HGLOBAL differently to just store values.

    Are you loading bitmap from resource? What is hBitmap? How are you assign value to it? Why char?
    Wht this third party program does?
    Last edited by JohnCz; August 20th, 2004 at 03:31 PM.
    There are only 10 types of people in the world:
    Those who understand binary and those who do not.

  5. #5
    Join Date
    Mar 2001
    Location
    Colorado
    Posts
    241
    I apologize, I kind of made that sound confusing. We use two different third party software packages. One of them was written for us by some Russian subcontractors, and is basically a database application. This database application is storing a an image in a database using HGLOBAL and storing it as a long binary. The other third party software is off the shelf image software called CGear which allows us open and manipulate all types of images (jpeg, bmp, emf.....).

    So I am using CGear to open image files, and convert them to HBITMAPS using one of their API's. Now I need to get this HBITMAP into an HGLOBAL so it can be stored in the database.

    I hope that makes sense. I apologize for all the menutia.

    Thanks for your help,

    Wade

  6. #6
    Join Date
    May 2002
    Posts
    1,435
    Note that an HGLOBAL cannot be stored in a database and then recalled. That may be the source of your confusion. HGLOBAL is really just a handle to global memory - an image of which is probably what is being stored in the database. There is no standard format of storing bitmap data. However, I would guess that it is similar to a bitmap file which includes a BITMAPFILEHEADER structure BITMAPINFOHEADER structure, a BITMAPINFO header, possibly a color table, and finally the actual data. What I would do if I were in your position is read the block of data from the database and then map a BITMAPFILEHEADER structure to the start of the data and see if the layout makes sense. If it does, then there is probably a real good chance that the data is in a bitmap file format. If it is then you will need to extract the various components mentioned above to create a bitmap handle using either Win 32 or MFC. Also note that unless you verify that this is, in fact, the way the binary data is being stored in the database you will be unable to do the inverse procedure - create a global memory block to store. I assume that you do not have sufficient documentation for the database structures. I have done this typ of thing quite often and if you would like to post a binary file of the long binary data block read from the database I would be happy to take a quick look and see if I can determine its structure.

  7. #7
    Join Date
    May 1999
    Location
    ALABAMA, USA
    Posts
    9,917
    That probably means you have to provide BITMAPINFO structure that contains BITMAPINFOHEADER structure and an array of RGBQUAD for writing file.

    Having HBITMAP, after allocating memory (GlobalAlloc) structure is filled with bitmap information that you can get from using HBITMAP anf HGLOBAL is used to retrieve pointer to this structure (GlobalLock) and write a file.

    I am sure you will be able to find some examples looking up MSDN and Internet.
    There are only 10 types of people in the world:
    Those who understand binary and those who do not.

  8. #8
    Join Date
    Mar 2001
    Location
    Colorado
    Posts
    241
    Hello 0xC0000005,

    Thanks for the reply. Here is some sample code that they are using to store the HGLOBAL in the database.
    Code:
    try
    	{
    		bool bResult = true;
    		
    		CString strNm;
    		CString szName;
    		CString szNotes;
    		long nHeight = 0;
    		long nWidth = 0;
    		long nStitchCount = 0;
    		long nColorCount = 0;
    		time_t dtLastUpdate = -1;
    		unsigned long lBMPView = 0;
    
    		long nBMPView = 0;
    		HGLOBAL hBMPView = NULL;
    
    		CDDesignInfo	info;// = CDDesignInfo::CreateObject();
    
    		CString strExt, strPath;
    		strPath = szFilePath;
    		int nPos = strPath.ReverseFind('.');
    		if(nPos > -1)
    		{
    			strExt = strPath.Right(strPath.GetLength() - nPos - 1);
    			CString strPath1 = strPath.Left(nPos);
    
    			int nPos1 = strPath1.ReverseFind('\\');
    			if(nPos1 > -1)
    			{
    				strNm = strPath1.Right(strPath1.GetLength() - nPos1 - 1);
    			}
    		}
    
    		if(IsGraphic(strExt))
    		{
    			USES_CONVERSION; // for _lopen and T2A
    			CGear cg;
    			HFILE hf = _lopen(T2A(strPath), OF_READ | OF_SHARE_DENY_NONE );
    
    			if (0 == cg.LoadImage(hf, 1, 0L))
    
    			// Get the image's original dimensions.
    			cg.GetImageDimensions(&nWidth, &nHeight);
    
    			_lclose(hf);
    
    			// Get the modified date of the file.
    			CFile file;
    			CFileStatus fileStatus;
    			file.GetStatus(strPath, fileStatus);
    			
    			CTime tmMod = fileStatus.m_mtime;
    			time_t time = tmMod.GetTime();
    
    			dtLastUpdate = time;
    			szName = strNm;
    
    			bResult = TRUE;
    		}
    		else
    		{
    
    			if (!info.Open(szFilePath))
    			{
    				ErrorMsg(IDS_ERROR_OPENIMAGE);
    				bResult = false;
    			}
    			else
    			{
    				CString	str;
    
    				if (bResult)
    				{
    					info.GetDesignName(&str);
    
    					if (str.IsEmpty())
    					{
    						bResult = false;
    					}
    					else
    					{
    						szName = str;
    					}
    				}
    
    				if (bResult)
    				{
    					str = info.GetDesignNote();
    
    					if (str.IsEmpty())
    					{
    	//					bResult = false;
    						;
    					}
    					else
    					{
    						if(str.GetLength() > 253)
    							szNotes = str.Left(253);
    						else 
    							szNotes = str;
    					}
    				}
    
    				if (bResult)
    				{
    					nHeight = info.GetDesignHeight();
    					if (nHeight == 0) 
    						bResult = false;
    				}
    
    				if (bResult)
    				{
    					nWidth = info.GetDesignWidth();
    					if (nWidth == 0) 
    						bResult = false;
    				}
    
    				if (bResult)
    				{
    					nStitchCount = info.GetStitchCount();
    					if (nStitchCount == -1) 
    						bResult = false;
    				}
    				
    				if (bResult)
    				{
    					nColorCount = info.GetColorCount();
    					if (nColorCount == 0) 
    						bResult = false;
    				}
    
    				if (bResult)
    				{
    					dtLastUpdate = info.GetLastModifyDate();
    					if (dtLastUpdate == -1) 
    						bResult = false;
    				}
    
    				if (bResult)
    				{
    					nBMPView = info.GetBitmapSize(148, 130);
    					
    					if (nBMPView == 0)
    					{
    						bResult = false;
    					}
    					else
    					{
    						hBMPView = ::GlobalAlloc(GPTR, nBMPView);
    						
    						if (hBMPView == NULL)
    						{
    							bResult = false;
    						}
    						else
    						{
    							BYTE* ptr = (BYTE *)::GlobalLock(hBMPView);
    							long nReal = info.GetBitmap(148, 130, ptr, nBMPView);
    
    							if(nReal > nBMPView)
    							{
    								bResult = false;
    							}
    		
    							::GlobalUnlock(hBMPView);
    							::GlobalFree(hBMPView);
    
    							hBMPView = ::GlobalAlloc(GPTR, nReal);
    							
    							if (hBMPView == NULL)
    							{
    								bResult = false;
    							}
    							else
    							{
    								BYTE* ptr =(BYTE *) ::GlobalLock(hBMPView);
    
    								if(info.GetBitmap(148, 130, ptr, nBMPView)!=nReal)
    								{
    									bResult = false;
    								}
    
    								nBMPView = nReal;
    			
    								::GlobalUnlock(hBMPView);
    							}
    						}
    					}
    				}
    
    				info.Close();
    			}
    		}
    
    
    		if (bResult)
    		{
    			CDDesignSet	rstData(thepDataBase);
    			rstData.Open();
    
    			//	Add new Record 
    			if(!rstData.CanAppend())
    			{
    				bResult = false;
    			}
    			else
    			{
    				CString Query = "FILE_PATH = '"; 
    				Query += szFilePath;
    				Query += "' AND ITEM_ID = ";
    				TCHAR buffer[10];
    				Query += _ltot(nTreeElementID,buffer,10);
    				BOOL Exists = rstData.FindFirst(Query);
    
    				if (Exists)
    					AfxMessageBox(IDS_ERROR_DESIGN_EXISTS);
    				else
    				{
    					rstData.AddNew();
    					
    					rstData.m_ITEM_ID      = nTreeElementID;
    					rstData.m_NAME         = szName;
    					rstData.m_FILE_PATH    = szFilePath;
    					rstData.m_HEIGHT       = nHeight;
    					rstData.m_WIDTH        = nWidth;
    					rstData.m_NOTES        = szNotes;
    					rstData.m_STITCH_COUNT = nStitchCount;
    					rstData.m_COLOR_COUNT  = nColorCount;
    					rstData.m_LAST_UPDATE  = COleDateTime(dtLastUpdate);
    
    					rstData.m_BMP_VIEW.m_dwDataLength = nBMPView;
    					rstData.m_BMP_VIEW.m_hData = hBMPView;
    
    					rstData.SetFieldDirty(&rstData.m_BMP_VIEW);
    					rstData.SetFieldNull(&rstData.m_BMP_VIEW, false);
    					
    					// this data was stored in rstData and will be 
    					// free by rstData 
    					hBMPView = NULL;
    					nBMPView = 0;
    
    					rstData.Update();
    				}
    			}
    		}
    
    		if (hBMPView != NULL)
    		{
    			GlobalFree(hBMPView);
    		}
    
    		return (bResult);
    	}
    	catch(CDaoException *pEx)
    	{
    		ErrorMsg(IDS_ERROR_ADD_DESIGN_RECORD,pEx);
    
    		return false;
    	}
    	catch(CMemoryException *pEx)
    	{
    		ErrorMsg(IDS_ERROR_MEMORY,pEx);
    
    		return false;
    	}
    
    	return false;
    Sorry for the formatting, but you can see they are actually storing the HGLOBAL hBmpView in the database. When I look at the database in Access, it shows the field type as a long binary.

    Any ideas how I can get an HBITMAP into an HGLOBAL?

    Thanks again for the response.

    Wade

  9. #9
    Join Date
    May 2002
    Posts
    1,435
    Let me try to understand this problem again. Are you saying that CDesignInfo::GetBitmap() provides you with some bitmap data that can be stored and recalled, but when you try to create your own bitmaps and store them then it fails?

    While at first glance it does appear that the HGLOBAL is being stored in the database I don't believe that it is. First of all, it is impossible for a memory handle to be persistent at the scope of database storage. The only way this would be even imaginable is if the database were meant to store temporary data only while the progam was active.

    Note comments in the source code: "this data was stored in rstData and will be free by rstData." It is obvious to me that what happens when rstData.Update() is called is that the data is loaded into a local pointer and then stored in the database -after which the global handle is freed. It is not actually storing the handle.

    Your problem seems to be not one of converting HBITMAP to HGLOBAL but of understaning the format of the data that is returned from CDesignInfo::GetBitmap() and stored in the global memory block. I insist that it is NOT an HBITMAP because HBITMAP is a Windows proprietary object whose actual format is not documented. It is not even possible to know the size of an HBITMAP object and if it is all self-contained or if it references other documented or undocumented structures. It can only be accessed and worked with through the standard Win32 API functions.

    The structure of rstData also looks proprietary to me. You don't have the source code for the classes CDesignSet and CDesignInfo - ist that right? You only have the header files? It looks to me like the key to understanding the layout is in the source code for CDesignInfo::GetBitmap() and CDesignSet::Update(). In other words, what is in the memory block returned by CDesignInfo::GetBitmap() and how is it stored in the database?

    When you load a design set back from the database does it give you a valid handle in rstData.m_BMP_VIEW.m_hData? That would indicate to me that CDesignSet is allocating it after loading in the data - note storing and loading the handle as you suspect.

    I am only guessing here, but after seeing the source code I would guess that the the HGLOBAL is actually storing the raw bit data. Have you tried extracting the raw bit data from your bitmap and placing that into the HGLOBAL memory block? I would bet that you would have a better chance at success that way. A little detective work may give you an idea if that’s the correct solution. How much data is in the memory block that is returned from CDesignInfo::GetBitmap() and does it correspond with the other parameters - i.e. width, height and bit-depth.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured