Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C++ Win32
Hello everyone!

I would like to start by saying thanks to everyone who takes some time to view this thread and try to help.
 
I have made a static control with following code in WM_CREATE:
 
HWND hStatic1 = CreateWindowEx( NULL, "STATIC", "", WS_CHILD | WS_VISIBLE | SS_ICON | SS_WHITERECT, 250,70, 50, 50, hwnd, NULL, GetModuleHandle(NULL), NULL);
 
The background of the control is working as described in MSDN reference, so I thought that all I needed to do is to add the following code after the above statement:
 
SendMessage( hStatic1, STM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hIcon);
 
However, the icon is not loaded. Yet, if i remove SS_WHITERECT from window creation, the icon loads properly, but static controls background doesn't behave as I want it to.
 
So my question is:
 
How do I keep the benefits offered by SS_WHITERECT, and at the same time am able to load icon so it can be shown?
 
Although I am inexperienced, I still have a strong feeling that this will not be possible without working with regions and rectangles.
 
If so, I will accept those types of solutions as well.
 
I just want to have a static control with icon in its center and its background behaving as if it has style SS_WHITERECT.
 
I work in MS Visual Studio Express 2008, on Windows XP, in C++, using WIN32 API. If any other information is required ( source code or something similar ), please ask for it, I will more than gladly supply it.
Posted 5-May-13 16:07pm
Edited 5-May-13 16:08pm
v2
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

The styles for static controls are divided into two sections: The lower bits up to 0x1F (SS_TYPEMASK) are an enumeration defining the type of the control while the upper bits define styles. Have a look at the SS_* definitions in WinUser.h. If you combine SS_ICON (0x03) and SS_WHITERECT (0x06) you will get 0x07 which is SS_BLACKFRAME.
 
To achieve the wanted behaviour, use SS_ICON | SS_CENTERIMAGE and set the background color of the control to white. Note also that you must use the STM_SETICON message to display a transparent icon rather than STM_SETIMAGE.
  Permalink  
v2
Comments
Nenad Smiljkovic at 6-May-13 9:25am
   
You said that I should set background of the control to white, does that mean that I should do it in WM_CTLCOLORSTATIC ?
Jochen Arndt at 6-May-13 10:19am
   
Yes, that should do the job. But I'm not quite sure what to return from that handler (I'm using MFC). But executing SetBkColor((HDC)wParam, 0xFFFFFF) there should set the color.
Nenad Smiljkovic at 6-May-13 10:39am
   
It makes the background color white, instead transparent.
 
Hopefully this piece of code can help you reveal the problem:
 
/************************************************************/
// static brush, declared outside switch(), in main window procedure
 
static HBRUSH hStaticBrush = CreateSolidBrush( RGB(255, 255, 255) );
 
case WM_CREATE:
{
HWND hStatic1 = CreateWindowEx( ... , SS_ICON | SS_CENTERIMAGE, ...);
SendMessage( ... , STM_SETICON, ...);
break;
}
case WM_CTLCOLORSTATIC:
{
HDC hdcStatic = (HDC)wParam;
SetBkColor( hdcStatic, RGB( 255, 255, 255) );
return (LRESULT)hStaticBrush;
}
/*************************************************************/
 
Additional information:
 
I have tried to return NULL_BRUSH, but it didn't help either.
Jochen Arndt at 6-May-13 10:53am
   
I thought that was what you wanted (like with SS_WHITERECT): A white background.
The background itself can't be transparent. The icon should be drawn transparent. Therefore, icons contain a bitmask bitmap to define which parts should be drawn and which not.
Nenad Smiljkovic at 6-May-13 11:18am
   
The background of my window is a bitmap image.
When I set style SS_WHITERECT the static control is drawn with black frame, without icon, but its background is the same as the part of the bitmap static control's rectangle occupies.
That was my point:
To draw icon in static control, but its background is the same as the part of the bitmap it is placed at.
I am sorry if I was vague and hope that this clarified things now.
To help further, it should have the same effect as result of the DrawIcon() function : on the background of the main window, which is bitmap, an icon is drawn without its background color.
I hope that this comment clarified what I need.
Again I apologize if I was vague.
Jochen Arndt at 6-May-13 11:49am
   
It's still not absolutely clear but I assume that you want a transparent image (icon) where the background of the parent window shines through (a transparent static control). I think this can't be done this way. The MSDN for CStatic::SetIcon() states:
 
"The icon will be automatically drawn in the static control. By default, it will be drawn in the upper-left corner and the static control will be resized to the size of the icon."
 
And with SS_CENTERIMAGE:
 
"Use to center in the static control. If the image is larger than the static control, it will be clipped. If it is smaller than the static control, the empty space around the image will be filled with the background color of the static control."
 
This is for MFC CStatic::SetIcon() but the function just sends the STM_SETICON message. So it is also true for STM_SETICON.
 
You may try to handle the WM_ERASBKGND message returning TRUE to avoid filling the background. But I'm not sure if this works always.
 
Finally, it may be simpler to draw the frame and the icon manually on the parent window.
 
If the control is used multiple times, this can be also done using an owner drawn static control (style type SS_OWNERDRAW) drawing from within the WM_DRAWITEM handler. But this requires also handling WM_ERASBKGND.
Nenad Smiljkovic at 6-May-13 12:04pm
   
Well, there is other way.
I can use DrawIcon(..) function, and it draws icon perfectly ( icon has transparent background).
The reason I wanted static control with that icon was to process the STN_DBLCLK message.
My client wanted double click on a picture to create certain event, and that is the problem for me, since icons do not send messages.
This could be a good substitute for static control if there is a way to simulate icon sending STN_DBLCLK message.
Any thoughts?
Jochen Arndt at 6-May-13 14:18pm
   
The only idea I have is using owner draw.
Nenad Smiljkovic at 6-May-13 14:39pm
   
I am interested in that solution.
I need to draw and properly size icon in the static control, and background must be transparent.
So my question for you is following:
Can you show me how to do it?
If not, can you provide some books or tutorials?
Thank you.
Jochen Arndt at 7-May-13 3:03am
   
There is no magic and the most drawing parts has been already done by you:
- Use SS_OWNERDRAW when creating the control
- Handle WM_DRAWITEM
- Optional calculate size and position for icon using GetClientRect
- Draw the icon using DrawIcon[Ex]
- Use DrawEdge to draw the frame
- Handle WM_ERASEBKGND
- Let the parent window update the region below the control
- Get client rect and convert to screen coords
- Convert rect to client coords of parent window
- Call InvalidateRect(hParent, &rect)
- Call UpdateWindow(hParent) to force painting
- Return nonzero (so the background is not filled)
 
It may be enough to handle WM_ERASEBKGND without using owner drawing. I have not done this so far, but I think it should work. The idea is simple: Let the parent redraw the area below the static control and do nothing when the background of the static control should be redrawn. However, this may result in some flickering.
Nenad Smiljkovic at 7-May-13 11:25am
   
Your way is a bit scary for me, since I am inexperienced in WIN32,but I have found a way to owner draw it with TransparentBlt( ... ) and it works!
Still, I would like to thank you for suggesting me to owner draw it, and for providing me such a detailed solution!
Vielle danke! :))
 
IMPORTANT UPDATE:
*******************************
 
YUOR CODE WORKS IF BACKGROUND IS NOT A BITMAP!
 
Thus, I will accept your solution.
 
However,I do not know how to handle WM_CTLCOLORSTATIC so it can work even if the background is a bitmap.
 
Can you help?
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

I have solved it!
 
First, I must say BIG "thank you" to member Jochen Arndt for suggesting me to owner draw the control, and providing detailed suggestions in his comment.
 
UPDATE #1:
************************************************************
 
Jochen Arndt's solution works perfect if the background of a window is not a bitmap.
 
I haven't found a way to apply it when bitmap is window's background.
 
Any help on this one is greatly appreciated,since I believe his solution is better ( and I would prefer to solve my problem this way!).
 
************************************************************
 
I have converted icon that I needed to load as static control's background into bitmap online, and drew it with function TransparentBlt( ... ).
 
For people with same, or similar problems, here is the code snippet:
 
// needed for TransparentBlt( ... ), see MSDN documentation!

#pragma comment( lib, "Msimg32.lib")
 
// static variable in main window procedure that stores the bitmap

static HBITMAP hbSymbol = LoadBitmap( GetModuleHandle(NULL), 
		MAKEINTRESOURCE(IDB_BITMAP2) );
 
// create owner drawn static control

case WM_CREATE:
     {
        // The parametar (HMENU)2000 below sets ID for this control

	HWND hStatic1 = CreateWindowEx( NULL, "STATIC", "", WS_CHILD | WS_VISIBLE | SS_NOTIFY | SS_OWNERDRAW, 450,150, 25, 25, hwnd, (HMENU)2000, GetModuleHandle(NULL), NULL);
     }
     break;
 
// owner draw it

case WM_DRAWITEM:
     {
        switch( (UINT)wParam)
	{
	    case 2000:
	    {
		BITMAP bp;
                
                LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT)lParam;
 
		HDC hMemDC = CreateCompatibleDC( lpDIS->hDC);
 
		GetObject( hbSimbol, sizeof(bp), &bp);
 
		SelectObject(hMemDC, hbSimbol);
 
                // background used for my mask was RGB(255,0,255)

		TransparentBlt( lpDIS->hDC, lpDIS->rcItem.top,
                   lpDIS->rcItem.left, 
                   lpDIS->rcItem.right - lpDIS->rcItem.left, 
		   lpDIS->rcItem.bottom - lpDIS->rcItem.top, 
                   hMemDC, 0, 0, bp.bmWidth, bp.bmHeight, 
                   RGB( 255, 0, 255) );
 
		DeleteDC(hMemDC);
            }
            break;
            default:
                break;
	}
     }
     break;
 
// cleanup

case WM_CLOSE:
 
     DeleteObject(hbSimbol);
 
     DestroyWindow(hwnd);
		
     break;
 
case WM_DESTROY:
 
     DeleteObject(hbSimbol);
 
     PostQuitMessage(0);
		
     break;
  Permalink  
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



Advertise | Privacy | Mobile
Web02 | 2.8.1411022.1 | Last Updated 7 May 2013
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100