Click here to Skip to main content
11,408,835 members (60,748 online)

C / C++ / MFC

 
QuestionRe: CoCreateInstance fail for 64 bit PinmvpRichard MacCutchan20-Feb-13 23:43 
AnswerRe: CoCreateInstance fail for 64 bit Pinmemberjohn563221-Feb-13 0:32 
GeneralRe: CoCreateInstance fail for 64 bit PinmvpRichard MacCutchan21-Feb-13 0:58 
GeneralRe: CoCreateInstance fail for 64 bit Pinmemberjohn563221-Feb-13 1:45 
GeneralRe: CoCreateInstance fail for 64 bit PinmvpRichard MacCutchan21-Feb-13 2:19 
GeneralRe: CoCreateInstance fail for 64 bit PinmemberJochen Arndt21-Feb-13 1:53 
GeneralRe: CoCreateInstance fail for 64 bit PinmemberChris Losinger22-Feb-13 5:14 
QuestionCursor from Bitmap Conundrum [modified] PinmemberBen Aldhouse20-Feb-13 22:36 
Hello. I have a cursor conundrum. I am developing a custom control and one feature I want this custom control to have is the ability to be able to rearrange its appearance by dragging and dropping one part of it to another. The way I decided I would do this would be to:

1) Convert the selected area into a bitmap
2) Use the bitmap from 1) as the cursor until the drop point is selected.
3) Redraw the control in the new arrangement.

I am not worried about step 3). That should be trivial - it won't involve anything I haven't achieved already in my code concerning bitmaps or device contexts. However, I have a conundrum concerning step 2). I have achieved what I want to achieve but only if I save the bitmap to a file first then reload it as a cursor! What I am looking for here is a way of obtaining the bitmap data and converting it directly into a cursor. Clearly my problem stems from having cobbled together samples of code from various sources without properly understanding what is going on -

So I call the image capuring function on clicking the mouse...
void CScrollBarEx::OnLButtonDown(UINT inFlags, CPoint inPoint) {
...
				CaptureAnImage(sliderVector[m_currentSlider-1].sliderRect);
...
}

and then you can see where I have edited out the code where I try and use the HBITMAP used to subsequently make a .bmp file to make the cursor - doing this always produces a black rectangle as the cursor. However- when I save that HBITMAP to .bmp file, then reload it into memory and use that to make a cursor - it works perfectly!

int CScrollBarEx::CaptureAnImage(RECT sliderRect)
{
    //HDC hdcScreen;
    HDC hdcWindow;
    HDC hdcMemDC = NULL;
    HBITMAP hbmScreen = NULL;
    BITMAP bmpScreen;
 
	HBITMAP m_hAndMask;
	HBITMAP m_hXorMask;
 

    // Retrieve the handle to a display device context for the client 
    // area of the window. 
    //hdcScreen =  (GetDC())->GetSafeHdc();
    hdcWindow = (GetDC())->GetSafeHdc();
 
    // Create a compatible DC which is used in a BitBlt from the window DC
    hdcMemDC = CreateCompatibleDC(hdcWindow); 
 

    if(!hdcMemDC)
    {
       // MessageBox(hWnd, L"CreateCompatibleDC has failed",L"Failed", MB_OK);
        goto done;
    }
 
    // Get the client area for size calculation
    RECT rcClient;
    GetClientRect(&rcClient);
 
    
	/*
	//This is the best stretch mode
    SetStretchBltMode(hdcWindow,HALFTONE);
 
    //The source DC is the entire screen and the destination DC is the current window (HWND)
    if(!StretchBlt(hdcWindow, 
               sliderRect.left ,sliderRect.top, 
               sliderRect.right, sliderRect.bottom, 
               hdcWindow, 
               0,0,
               GetSystemMetrics (SM_CXSCREEN),
               GetSystemMetrics (SM_CYSCREEN),
               SRCCOPY))
    {
        //MessageBox(hWnd, L"StretchBlt has failed",L"Failed", MB_OK);
        goto done;
    }
    */
	
 
    // Create a compatible bitmap from the Window DC
		//hbmScreen = CreateCompatibleBitmap(hdcWindow, rcClient.right-rcClient.left, rcClient.bottom-rcClient.top);
	
	    //hbmScreen = CreateCompatibleBitmap(hdcWindow, sliderRect.right, sliderRect.bottom-sliderRect.top);
		
	    hbmScreen = CreateCompatibleBitmap(hdcWindow, sliderRect.right-sliderRect.left, sliderRect.bottom-sliderRect.top);
 
    
    if(!hbmScreen)
    {
        //MessageBox(hWnd, L"CreateCompatibleBitmap Failed",L"Failed", MB_OK);
        goto done;
    }
 
	// Select the compatible bitmap into the compatible memory DC.
    SelectObject(hdcMemDC,hbmScreen);
 
    // Bit block transfer into our compatible memory DC.
    if(!BitBlt(hdcMemDC, 
               0,0,
               sliderRect.right-sliderRect.left, sliderRect.bottom-sliderRect.top, 
               hdcWindow, 
               sliderRect.left,sliderRect.top,
               SRCCOPY))
    {
        //MessageBox(hWnd, L"BitBlt has failed", L"Failed", MB_OK);
        goto done;
    }
 
	
	// Get the BITMAP from the HBITMAP
    GetObject(hbmScreen,sizeof(BITMAP),&bmpScreen);
 
	
    BITMAPFILEHEADER   bmfHeader;    
    BITMAPINFOHEADER   bi;
     
	
	bi.biSize = sizeof(BITMAPINFOHEADER);    
    bi.biWidth = bmpScreen.bmWidth;    
    bi.biHeight = bmpScreen.bmHeight;  
    bi.biPlanes = 1;    
    bi.biBitCount = 32;    
    bi.biCompression = BI_RGB;    
    bi.biSizeImage = 0;  
    bi.biXPelsPerMeter = 0;    
    bi.biYPelsPerMeter = 0;    
    bi.biClrUsed = 0;    
    bi.biClrImportant = 0;
 
    DWORD dwBmpSize = ((bmpScreen.bmWidth * bi.biBitCount + 31) / 32) * 4 * bmpScreen.bmHeight;
 
	// Starting with 32-bit Windows, GlobalAlloc and LocalAlloc are implemented as wrapper functions that 
    // call HeapAlloc using a handle to the process's default heap. Therefore, GlobalAlloc and LocalAlloc 
    // have greater overhead than HeapAlloc.
    HANDLE hDIB = GlobalAlloc(GHND,dwBmpSize); 
    char *lpbitmap = (char *)GlobalLock(hDIB);    
  
	// Gets the "bits" from the bitmap and copies them into a buffer 
    // which is pointed to by lpbitmap.
    GetDIBits(hdcWindow, hbmScreen, 0,
        (UINT)bmpScreen.bmHeight,
        lpbitmap,
        (BITMAPINFO *)&bi, DIB_RGB_COLORS);	
 
    // A file is created, this is where we will save the screen capture.
    HANDLE hFile = CreateFile(L"capture.bmp",
        GENERIC_WRITE,
        0,
        NULL,
        CREATE_ALWAYS,
        FILE_ATTRIBUTE_NORMAL, NULL);   
    
    // Add the size of the headers to the size of the bitmap to get the total file size
    DWORD dwSizeofDIB = dwBmpSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
 
    //Offset to where the actual bitmap bits start.
    bmfHeader.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER); 
    
    //Size of the file
    bmfHeader.bfSize = dwSizeofDIB; 
    
    //bfType must always be BM for Bitmaps
    bmfHeader.bfType = 0x4D42; //BM   
 
    DWORD dwBytesWritten = 0;
    WriteFile(hFile, (LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL);
    WriteFile(hFile, (LPSTR)&bi, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL);
    WriteFile(hFile, (LPSTR)lpbitmap, dwBmpSize, &dwBytesWritten, NULL);
    
    //Unlock and Free the DIB from the heap
    GlobalUnlock(hDIB);    
    GlobalFree(hDIB);
 

	//Close the handle for the file that was created
    CloseHandle(hFile);
	
	/*
	//20130216
	//Turn the cursor into a bitmap
	//HANDLE hNewBMP = CopyImage(hbmScreen,IMAGE_BITMAP,0,0,LR_COPYRETURNORG);
	m_hXorMask	  =  NULL;
	m_hAndMask	  =  NULL;
	//CColorCursor::GetMaskBitmaps(hbmScreen,RGB(0,0,0),m_hAndMask,m_hXorMask);
	m_hCursor = CColorCursor::CreateCursorFromBitmap(hbmScreen,RGB(0,0,0),0,0);
	//m_hCursor = CColorCursor::CreateCursorFromBitmap(hNewBMP,RGB(0,0,0),0,0);
	*/
 

	/*
	//Use Jiju George's bitmap drawing function
	HBITMAP aBMP = GetCursorBitmap();
	m_hCursor = CColorCursor::CreateCursorFromBitmap(aBMP,RGB(0,0,0),0,0);
	*/
 
	//Load up the file that was created earlier in the function into a bitmap
	//   then use that as the cursor.
	HBITMAP   hBMP; 
	HPALETTE palette;
	LoadBitmapFromBMPFile(L"capture.bmp", &hBMP, &palette);
	m_hCursor = CColorCursor::CreateCursorFromBitmap(hBMP,RGB(0,0,0),0,0);
	
	::SetCursor(m_hCursor); 
    
    //Clean up
done:
    DeleteObject(hbmScreen);
    DeleteObject(hdcMemDC);
    //ReleaseDC(hdcScreen);
    //ReleaseDC(hdcWindow);
    //DeleteObject(hdcScreen);
    DeleteObject(hdcWindow);
 

    return 0;
}
 
and

//////////////////////////////////////////////////////////////////////
//  CreateCursorFromBitmap 
//  Function to create a cursor from HBITMAP. 
//  Pass bitmaps having standard cursor sizes like 16*16, 32*32...
//////////////////////////////////////////////////////////////////////
HCURSOR CColorCursor::CreateCursorFromBitmap(HBITMAP hSourceBitmap,
											 COLORREF clrTransparent,
											 DWORD   xHotspot,DWORD   yHotspot)
{
	HCURSOR hRetCursor = NULL;
 
	do
	{
		if(NULL == hSourceBitmap)
		{
			break;
		}
 
		//Create the AND and XOR masks for the bitmap
		HBITMAP hAndMask = NULL;
		HBITMAP hXorMask = NULL;
		GetMaskBitmaps(hSourceBitmap,clrTransparent,hAndMask,hXorMask);
		if(NULL == hAndMask || NULL == hXorMask)
		{
			break;
		}
 
		//Create the cursor using the masks and the hotspot values provided
		ICONINFO iconinfo = {0};
		iconinfo.fIcon		= FALSE;
		iconinfo.xHotspot	= xHotspot;
		iconinfo.yHotspot	= yHotspot;
		iconinfo.hbmMask	= hAndMask;
		iconinfo.hbmColor	= hXorMask;
 
		hRetCursor = ::CreateIconIndirect(&iconinfo);
 
	}
	while(0);
 
	return hRetCursor;
}

I have used code from the following sources...


HOWTO: How To Use LoadImage() to Read a BMP File
at http://support.microsoft.com/kb/158898

and

Creating a color cursor from a bitmap
at Creating a color cursor from a bitmap

In the last article the author warns against making a cursor outside of the standard cursor sizes but this doesn't explain why the code works when loading a cursor from file but not when using the bitmap directly!

modified 21-Feb-13 4:05am.

QuestionHow Print multiple copies with printdlg in MFC Pinmemberhaha_c20-Feb-13 22:06 
AnswerRe: How Print multiple copies with printdlg in MFC PinmvpRichard MacCutchan20-Feb-13 22:13 
GeneralRe: How Print multiple copies with printdlg in MFC Pinmemberhaha_c20-Feb-13 22:54 
GeneralRe: How Print multiple copies with printdlg in MFC PinmvpRichard MacCutchan20-Feb-13 23:39 
GeneralRe: How Print multiple copies with printdlg in MFC Pinmemberhaha_c21-Feb-13 0:31 
QuestionLoad an image dynamically in win32 using VC++ Pinmembertoms from newdelhi20-Feb-13 21:05 
AnswerRe: Load an image dynamically in win32 using VC++ Pingroup_AnsHUMAN_ 20-Feb-13 21:56 
AnswerRe: Load an image dynamically in win32 using VC++ PinmvpRichard MacCutchan20-Feb-13 23:32 
GeneralRe: Load an image dynamically in win32 using VC++ Pinmembertoms from newdelhi21-Feb-13 1:27 
GeneralRe: Load an image dynamically in win32 using VC++ PinmvpRichard MacCutchan21-Feb-13 2:14 
AnswerRe: Load an image dynamically in win32 using VC++ PinmemberMax_Power_Up26-Feb-13 6:10 
QuestionWhy does so many companies use directUI to show GUI ? Pingroupyu-jian20-Feb-13 16:09 
QuestionCFileDialog in Dll Project PinmemberLeeUnSong20-Feb-13 15:38 
AnswerRe: CFileDialog in Dll Project PinmvpRichard MacCutchan20-Feb-13 22:10 
GeneralRe: CFileDialog in Dll Project PinmemberLeeUnSong21-Feb-13 1:31 
GeneralRe: CFileDialog in Dll Project PinmvpRichard MacCutchan21-Feb-13 2:16 
QuestionFormatting Output [modified] PinmemberSarah Trattner20-Feb-13 13:02 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.


Advertise | Privacy | Mobile
Web03 | 2.8.150414.5 | Last Updated 24 Apr 2015
Copyright © CodeProject, 1999-2015
All Rights Reserved. Terms of Service
Layout: fixed | fluid