Thread: how add an image with a text?

  1. #1
    Registered User
    Join Date
    Aug 2013
    Posts
    451

    how add an image with a text?

    i have these code for add an image to a control(STATIC). but i have some problems
    Code:
    void setImage(string FileName)
        {
            //handle the image
            HBITMAP hImage =(HBITMAP)LoadImage(NULL,FileName.c_str(),IMAGE_BITMAP,20,20,LR_LOADFROMFILE);
            //add it to control
            SendMessage(this->hwnd,
                STM_SETIMAGE,//it's the sendmessage 'command'
                (WPARAM)IMAGE_BITMAP,//type\format of image
                reinterpret_cast<LPARAM>(hImage));//the HBITMAP image
        }
    (i must add, in these handle, the SS_BITMAP style)
    the image is showed, but the text isn't.
    i'm reading the msdn documentation:

    "SS_BITMAP: A bitmap is to be displayed in the static control. The text is the name of a bitmap (not a filename) defined elsewhere in the resource file. The style ignores the nWidth and nHeight parameters; the control automatically sizes itself to accommodate the bitmap."

    the 2nd sentence:
    "The text is the name of a bitmap (not a filename) defined elsewhere in the resource file."
    i'm confused what these means.. i'm portuguese.
    can anyone tell me in other words, please?

  2. #2
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    >>The text is the name of a bitmap (not a filename) defined elsewhere in the resource file

    The 'resource file' is usually called 'resource.h'. It contains definitions / defines for resources used in your program.

    In the case of bitmaps this will be a # defined name for the bitmap.
    Bitmaps in the resource file can either be loaded from file at run time or stored as part of the exe when it is built.
    The # defined name will either link a file name (with path) or a map section of the exe where the actual bitmap is stored (ie the memory address / offset).

    >>the image is showed, but the text isn't.

    Have you looked at the 'owner draw' style? [SS_OWNERDRAW]
    This will allow you to create a custom handler to redraw a specific control when the OS tells you it is required.
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  3. #3
    Registered User
    Join Date
    Aug 2013
    Posts
    451
    Quote Originally Posted by novacain View Post
    >>The text is the name of a bitmap (not a filename) defined elsewhere in the resource file

    The 'resource file' is usually called 'resource.h'. It contains definitions / defines for resources used in your program.

    In the case of bitmaps this will be a # defined name for the bitmap.
    Bitmaps in the resource file can either be loaded from file at run time or stored as part of the exe when it is built.
    The # defined name will either link a file name (with path) or a map section of the exe where the actual bitmap is stored (ie the memory address / offset).

    >>the image is showed, but the text isn't.

    Have you looked at the 'owner draw' style? [SS_OWNERDRAW]
    This will allow you to create a custom handler to redraw a specific control when the OS tells you it is required.
    what is the diference between the WM_PAINT and WM_OWNERDRAW messages?
    can i build my own standard STATIC using WM_OWNERDRAW and the user, if needs, can use WM_PAINT for rebuild it?

  4. #4
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    Quote Originally Posted by joaquim View Post
    what is the diference between the WM_PAINT and WM_OWNERDRAW messages?
    WM_PAINT msgs are generated when the client area of an app needs to be re-drawn.
    Paint msgs can be generated by your app or by external events (ie another window passing over your app).

    You generate a WM_PAINT inside your app by calling;
    InvalidateRect() which generates the paint msg to the required callback.
    UpdateWindow() usually follows InvalidateRect() as it sends the paint msg directly to the callback (instead of the paint msg going to the OS msg queue). This makes the painting faster and smoother.

    Controls do not generate paint msgs.

    The OS handles redrawing controls and the coder has no control over the drawing, unless you specify OWNERDRAW and handle the WM_DRAWITEM msg.

    Quote Originally Posted by joaquim View Post
    can i build my own standard STATIC using WM_OWNERDRAW and the user, if needs, can use WM_PAINT for rebuild it?
    It is all done in the WM_DRAWITEM handler.

    If you need to redraw the control after some user input / event / etc then you can use SendMessage() to generate a WM_DRAWITEM msg (just as you use InvalidateRect() + UpdateWindow() to generate a WM_PAINT).

    In your case you need to do something like this;

    [note written from memory, not compiled or any error handling added and so should not be used...]

    Code:
    //made static to retain value between msgs
    
    static HBITMAP hImage = null;
    static HDC hdcMem = null, hbmpOld = null; 
    
    
    case WM_INITDIALOG: //or WM_CREATE depending on if a window or a dialog
    {
    	//load the bitmap (do it here to save time while drawing)
    	hImage =(HBITMAP)LoadImage(NULL,FileName.c_str(),IMAGE_BITMAP,20,20,LR_LOADFROMFILE);
    
    	//create memory DC to hold image
    	HDC hdc = GetDC(GetDlgItem(hWnd, ID_OWNER_DRAWN_STATIC)); //get controls DC
    	hdcMem = CreateCompatibleDC(hdc); //create a DC the same as it
    	hbmpOld = (HBITMAP) SelectObject(hdcMem, hImage); //select the image into the memory DC
    
    	//if the text on the image does not change during run time, draw it here
    
    	//clean up
    	ReleaseDC(hdc);
    
    	return TRUE;
    	
    }
    case WM_DESTROY: //when the app closes
    {
    	//clean up image
    	//put the memory DC back to default
    	SelectObject(hdcMem, hbmpOld); 
    	//and delete the GDIs we created
    	DeleteDC(hdcMem);
    	DeleteObject(hImage);
    
    	return TRUE;
    }
    case WM_DRAWITEM:
    {
    	LPDRAWITEMSTRUCT pDrawItem = (LPDRAWITEMSTRUCT)lParam;
    	//check it is the static we want to draw
        	if (pDrawItem >hwndItem == GetDlgItem(hWnd, ID_OWNER_DRAWN_STATIC) )
        	{
    		//draw the image, assumes image and control are the same size
    		BitBlt(pDrawItem->hDC,
    			pDrawItem->rcItem.left, pDrawItem->rcItem.top, 
                            pDrawItem->rcItem.right - pDrawItem->rcItem.left, 
    			pDrawItem->rcItem.bottom - pDrawItem->rcItem.top, 
    			hdcMem, 0, 0, SRCCOPY);
    		
    		//get the text to draw on the image (assume it is in 'TextToDraw' string variable)
    
    		//draw text
    		//NOTE we draw to the controls DC (not the memory DC) so we can change the text as required 
    		//and not have remnants of the last text showing
    
    		//if the text does not change then it should be draw on the memory DC in the WM_CREATE (move the lines)
    
    		TextOut(pDrawItem->hDC, pDrawItem->rcItem.left, pDrawItem->rcItem.top, TextToDraw.c_str(), TextToDraw.Length() );
    		
    		//we did not create any GDIs so no cleanup required
    
    		//tell OS we processed this msg
    		return TRUE;
    	}
    	return FALSE; //we did not process this msg
    }
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  5. #5
    Registered User
    Join Date
    Aug 2013
    Posts
    451
    Quote Originally Posted by novacain View Post
    WM_PAINT msgs are generated when the client area of an app needs to be re-drawn.
    Paint msgs can be generated by your app or by external events (ie another window passing over your app).

    You generate a WM_PAINT inside your app by calling;
    InvalidateRect() which generates the paint msg to the required callback.
    UpdateWindow() usually follows InvalidateRect() as it sends the paint msg directly to the callback (instead of the paint msg going to the OS msg queue). This makes the painting faster and smoother.

    Controls do not generate paint msgs.

    The OS handles redrawing controls and the coder has no control over the drawing, unless you specify OWNERDRAW and handle the WM_DRAWITEM msg.



    It is all done in the WM_DRAWITEM handler.

    If you need to redraw the control after some user input / event / etc then you can use SendMessage() to generate a WM_DRAWITEM msg (just as you use InvalidateRect() + UpdateWindow() to generate a WM_PAINT).

    In your case you need to do something like this;

    [note written from memory, not compiled or any error handling added and so should not be used...]

    Code:
    //made static to retain value between msgs
    
    static HBITMAP hImage = null;
    static HDC hdcMem = null, hbmpOld = null; 
    
    
    case WM_INITDIALOG: //or WM_CREATE depending on if a window or a dialog
    {
        //load the bitmap (do it here to save time while drawing)
        hImage =(HBITMAP)LoadImage(NULL,FileName.c_str(),IMAGE_BITMAP,20,20,LR_LOADFROMFILE);
    
        //create memory DC to hold image
        HDC hdc = GetDC(GetDlgItem(hWnd, ID_OWNER_DRAWN_STATIC)); //get controls DC
        hdcMem = CreateCompatibleDC(hdc); //create a DC the same as it
        hbmpOld = (HBITMAP) SelectObject(hdcMem, hImage); //select the image into the memory DC
    
        //if the text on the image does not change during run time, draw it here
    
        //clean up
        ReleaseDC(hdc);
    
        return TRUE;
        
    }
    case WM_DESTROY: //when the app closes
    {
        //clean up image
        //put the memory DC back to default
        SelectObject(hdcMem, hbmpOld); 
        //and delete the GDIs we created
        DeleteDC(hdcMem);
        DeleteObject(hImage);
    
        return TRUE;
    }
    case WM_DRAWITEM:
    {
        LPDRAWITEMSTRUCT pDrawItem = (LPDRAWITEMSTRUCT)lParam;
        //check it is the static we want to draw
            if (pDrawItem >hwndItem == GetDlgItem(hWnd, ID_OWNER_DRAWN_STATIC) )
            {
            //draw the image, assumes image and control are the same size
            BitBlt(pDrawItem->hDC,
                pDrawItem->rcItem.left, pDrawItem->rcItem.top, 
                            pDrawItem->rcItem.right - pDrawItem->rcItem.left, 
                pDrawItem->rcItem.bottom - pDrawItem->rcItem.top, 
                hdcMem, 0, 0, SRCCOPY);
            
            //get the text to draw on the image (assume it is in 'TextToDraw' string variable)
    
            //draw text
            //NOTE we draw to the controls DC (not the memory DC) so we can change the text as required 
            //and not have remnants of the last text showing
    
            //if the text does not change then it should be draw on the memory DC in the WM_CREATE (move the lines)
    
            TextOut(pDrawItem->hDC, pDrawItem->rcItem.left, pDrawItem->rcItem.top, TextToDraw.c_str(), TextToDraw.Length() );
            
            //we did not create any GDIs so no cleanup required
    
            //tell OS we processed this msg
            return TRUE;
        }
        return FALSE; //we did not process this msg
    }
    thanks... i have 2 questions:
    1 - imagine that i need do the transparent\opacy: so i must call the WM_DRAWITEM using SendMessage() for do the changes, right?
    2 - how use the SendMessage()? is SendMessage(hwndControl,WM_DRAWITEM,0,0)... is these correct?

  6. #6
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    Quote Originally Posted by joaquim View Post
    1 - imagine that i need do the transparent\opacy: so i must call the WM_DRAWITEM using SendMessage() for do the changes, right?
    Not sure what you mean, could you post s screen shot?

    If you want the control to be invisible / disappear then use ShowWindow()

    Quote Originally Posted by joaquim View Post
    2 - how use the SendMessage()? is SendMessage(hwndControl,WM_DRAWITEM,0,0)... is these correct?
    Try calling InvalidateRect(hParentWindow , GetClientRect( GetDlgItem(hParentWindow , ID_OWNER_DRAWN_STATIC)) and see if the system will automatically generate a WM_DRAWITEM (been a few years since I coded in WIN32).

    If that does not work you will need to fill in a DRAWITEMSTRUCT and pass it in the SendMessage() call.

    [note not compiled or tested and probably won't work...]

    Code:
    DRAWITEMSTRUCT  DrawItem = {0};
    DrawItem.CtlType = ODT_STATIC;
    DrawItem.CtlID = ID_OWNER_DRAWN_STATIC;
    DrawItem.ItemID = -1;
    DrawItem.itemAction = ODA_DRAWENTIRE;
    DrawItem.hwndItem = GetDlgItem(hParentWindow , ID_OWNER_DRAWN_STATIC);
    DrawItem.hDC = GetDC(GetDlgItem(hParentWindow , ID_OWNER_DRAWN_STATIC));
    DrawItem.rcItem = GetClientRect(GetDlgItem(hParentWindow , ID_OWNER_DRAWN_STATIC));
    
    //send the parent / owner window a drawitem msg
    SendMessage(hParentWindow , WM_DRAWITEM, 0, (LAPARAM)&DrawItem);
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  7. #7
    Registered User
    Join Date
    Aug 2013
    Posts
    451
    Quote Originally Posted by novacain View Post
    Not sure what you mean, could you post s screen shot?

    If you want the control to be invisible / disappear then use ShowWindow()



    Try calling InvalidateRect(hParentWindow , GetClientRect( GetDlgItem(hParentWindow , ID_OWNER_DRAWN_STATIC)) and see if the system will automatically generate a WM_DRAWITEM (been a few years since I coded in WIN32).

    If that does not work you will need to fill in a DRAWITEMSTRUCT and pass it in the SendMessage() call.

    [note not compiled or tested and probably won't work...]

    Code:
    DRAWITEMSTRUCT  DrawItem = {0};
    DrawItem.CtlType = ODT_STATIC;
    DrawItem.CtlID = ID_OWNER_DRAWN_STATIC;
    DrawItem.ItemID = -1;
    DrawItem.itemAction = ODA_DRAWENTIRE;
    DrawItem.hwndItem = GetDlgItem(hParentWindow , ID_OWNER_DRAWN_STATIC);
    DrawItem.hDC = GetDC(GetDlgItem(hParentWindow , ID_OWNER_DRAWN_STATIC));
    DrawItem.rcItem = GetClientRect(GetDlgItem(hParentWindow , ID_OWNER_DRAWN_STATIC));
    
    //send the parent / owner window a drawitem msg
    SendMessage(hParentWindow , WM_DRAWITEM, 0, (LAPARAM)&DrawItem);
    i'm having more sucess with WM_PAINT message(maybe because ir more easy for me)

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 1
    Last Post: 03-21-2012, 11:20 AM
  2. Replies: 1
    Last Post: 04-25-2011, 12:02 PM
  3. Replies: 6
    Last Post: 07-16-2010, 10:35 AM
  4. C program for text to image
    By karthiks551985 in forum C Programming
    Replies: 7
    Last Post: 10-10-2008, 09:36 AM
  5. Reading text in an Image format
    By loko in forum C Programming
    Replies: 0
    Last Post: 09-29-2005, 06:38 PM