finally i have the static control transparent:

//creating the form:
hwnd = CreateWindowEx(0, classname, strCaption.c_str(),WS_OVERLAPPEDWINDOW | WS_TABSTOP,
                                  CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, parent, NULL, mod, this);

//sending a message for subclassing:
case WM_CTLCOLORSTATIC:
                {
                    return DefWindowProc(HandleWindow, msg, wParam, lParam);
                }
                break;

//heres how i create a static control with ownerdraw style:
hwnd = CreateWindowEx(
                0,
                TEXT("CSTATIC"),//these must be the same of  LabelClass.lpszClassName
                strCaption.c_str(), WS_TABSTOP|
                WS_CHILD | WS_VISIBLE | SS_NOTIFY | SS_OWNERDRAW | WS_TABSTOP,
                intLeft, intTop, intWidth, intHeight,
                parent,
                NULL,
                mod,
                (LPVOID)this);

//now here the static messages for draw it:
case WM_CTLCOLORSTATIC:
            {
                HDC hdcStatic = (HDC) wParam;
                SetTextColor(hdcStatic, RGB(0,0,0));
                SetBkMode (hdcStatic, TRANSPARENT);
                return (LRESULT)GetStockObject(NULL_BRUSH);
            }
            break;
            case WM_PAINT:
            {
                PAINTSTRUCT  ps;
                BeginPaint(inst->hwnd, &ps);//inst is the static object pointer
                if(inst->Paint==NULL)
                {
                    if(inst->blnTransparent!=true)
                        FillRect(ps.hdc,&ps.rcPaint, CreateSolidBrush(inst->clrBackColor));
                    if(inst->imgtest.haveimage())
                        DrawHICONtoHDC(ps.hdc, inst->imgtest,1,1);
                    SetBkMode(ps.hdc,TRANSPARENT);
                    char *text=(char*)inst->strCaption.c_str();
                    SetTextColor(ps.hdc,inst->clrTextColor );
                    DrawTextEx(ps.hdc,text,-1,&ps.rcPaint,DT_LEFT,NULL);
                    if(inst->blnBorder==true)
                        DrawEdge(ps.hdc, &ps.rcPaint,BDR_SUNKENINNER | BDR_RAISEDOUTER,BF_RECT);
                }

                EndPaint(inst->hwnd, &ps);
            }
            break;


//and now heres the code for make it transparent:
void setTransparent(bool transparent)
    {
        blnTransparent = transparent;
        LONG_PTR s;
        if(transparent==true)
        {
            blnTransparent=true;
            s=GetWindowLongPtr(hwnd,GWL_EXSTYLE);
            s|=WS_EX_TRANSPARENT;
            SetWindowLongPtr(hwnd,GWL_EXSTYLE,s);
        }
        else
        {
            s=GetWindowLongPtr(hwnd,GWL_EXSTYLE);
            s&=~WS_EX_TRANSPARENT;
            SetWindowLongPtr(hwnd,GWL_EXSTYLE,s);
            blnTransparent=false;

        }
        InvalidateRect(hwnd,NULL,FALSE);
    }

some code is from my header file. but i think that it's easy to follow.
readers: any problems please tell me.

but these label transparent have 1 problem:
(see the image)
(if i fill 1 color, that color is showed)
how can i clean the image before repaint?

Edited 1 Year Ago by cambalinho

Attachments label_transparent_error.png 1.2 KB

I don't understand the problem at all. What is working and what isn't working? The label seems to be drawn fine in that image..

Give more details on what is wrong with it.

that image is an animation. and the images are showed 1 above other. the correct is clean the last image and show the newone.

yah. now i know the STATIC control it's drawed to parent window. so using the same way of the window creation, i can create my own label ;)

No as in why are you using win32, you're suffering.

http://shoesrb.com/downloads/

Same lines of code to animate a bitmap/jpg/png

Shoes.app do
   s = stack width: 200, height: 200 do
        @yo= image "1.png"
        a=1
        animate(1) do |frame|
             a = a+1
             if a % 2 == 0
                s.clear { @yo= image "2.png" }
             else
                s.clear { @yo = image "1.png" }
             end
         end
     end
 end

You can find the drawing functions here.

http://shoesrb.com/manual/Art.html

Edited 1 Year Ago by iamthwee

i'm sorry.. what code is that? i'm in right sub-forum, i think

Yes you are I was just saying why put yourself through the grief of win32 programming. Head over to that page download the installer for windows.

Open up a file call it animate.rb, save then open.

And you will effectively get the same result as animating those two images you have.

i did that triumphost. but now i know why isn't working. the STATIC control is like a draw text, on form\window paint message.
so i will create another control, like button, and then maybe i can resolve it ;)

Try doing one of the following:

UpdateWindow(hwnd);
RedrawWindow
InvalidateRect
InvalidateRgn

One of these HAS to work. If nothing works, you are 100% doing something wrong.

now works fine..thanks for all ;)

RECT d;
                GetClientRect(hwnd,&d);
                RedrawWindow(hwnd,&d,nullptr,RDW_ERASE);

triumphost: please can you tell me the diference between that 4 functions?
(include the TRUE\FALSE of the Invalidate)

UpdateWindow redraws the client area of the window IF AND ONLY IF the internal region is not empty. That means that a redraw is not guaranteed or forced and the window is only redrawn if the API deems it necessary. It does so by sending a WM_PAINT message to the window. It does NOT guarantee that the background is erased!

InvalidateRect redraws a portion of the window specified by the rectangle but it does so by sending WM_ERASEBKGND message instead. It will only update the region specified by the rect only if there are no other messages in the queue and it does so by sending a WM_PAINT message. This is equivalent to telling the window to repaint only a specific portion as long as WM_ERASEBKGND is handled properly. If the message is handled by the user, no erasing may be done because the user has manually erased the window when handling that message.
This function will ONLY work (take effect) when the next WM_PAINT message is sent. If the window isn't "moved" then the message is not sent and you will NOT see the results.. WM_PAINT is not always sent to the window! It is only sent if the window moves or state changes.

That means that in order for this to take effect immediately you must call MoveWindow OR SetWindowPos. SetWindowPos is usually the one that you need to use.

InvalidateRgn does the same thing as InvalidateRect and the same restrictions apply, however instead of specifying a rect, you specify an already created region. For this to take immediate effect, you must also call one of the functions specified above (ie: SetWindowPos).

RedrawWindow forces an update of the client portion of the window NO MATTER WHAT. It's equivalent to calling InvalidateRect and specifying the client area followed by SetWindowPos. Please note that when you use RDW_ERASE, you must also specify: RDW_INVALIDATE.

That means you must use:

RedrawWindow(hwnd, &d, nullptr, RDW_ERASE | RDW_INVALIDATE); instead of what you have above.

ALL of the above functions will work to redraw/update your window. It just matters if you know how to use them and when to use them. It's no surprise that RedrawWindow is easier to use and works for you. The others would work as well provided that you make it take effect immediately as described above. Also note that it's faster to only redraw a portion of the client area (unless you need the entire thing redrawn).

Edited 1 Year Ago by triumphost

i can use my image for Double Buffering easy. and only, in the end, i change the new image:

//the animation timer:
animation.timerprocedure=[this]()
           {
                static int a;
                a=a+1;
                if(a==imgtest.FramesCount)
                    a=0;
                imgtest.SelectFrame=a;
                RECT d;
                GetClientRect(hwnd,&d);
                RedrawWindow(hwnd,&d,nullptr,RDW_ERASE| RDW_INVALIDATE);
           };
//drawing the static control:
case WM_ERASEBKGND:
            {
                return TRUE;
            }
            break;
            case WM_CTLCOLORSTATIC:
            {
                return (LRESULT)GetStockObject(NULL_BRUSH);
            }
            break;
            case WM_DRAWITEM:
            {

                DRAWITEMSTRUCT *test=(DRAWITEMSTRUCT*) lParam;
                image imglabel(test->rcItem.right-test->rcItem.left,test->rcItem.bottom-test->rcItem.top);
                if(inst->blnTransparent!=true)
                    FillRect(test->hDC,&test->rcItem, CreateSolidBrush(inst->clrBackColor));
                else
                    FillRect(test->hDC,&test->rcItem,(HBRUSH) GetStockObject(NULL_BRUSH));
                FillRect(imglabel,&test->rcItem,CreateSolidBrush(inst->clrBackColor));
                if(inst->imgtest.haveimage())
                    DrawHICONtoHDC(imglabel, inst->imgtest,1,1);
                SetBkMode(imglabel,TRANSPARENT);
                char *text=(char*)inst->strCaption.c_str();
                SetTextColor(imglabel,inst->clrTextColor );
                DrawTextEx(imglabel,text,-1,&test->rcItem,DT_LEFT,NULL);
                if(inst->blnBorder==true)
                    DrawEdge(imglabel, &test->rcItem,BDR_SUNKENINNER | BDR_RAISEDOUTER,BF_RECT);
                imglabel.Backcolor=inst->clrBackColor;
                TransparentBlt(test->hDC,0,0,test->rcItem.right,test->rcItem.bottom,imglabel,0,0,test->rcItem.right,test->rcItem.bottom, inst->clrBackColor);//draw the image to static
            }
            break;

so how can i avoid the flicker?
i use the double buffer

i avoid some flicker, but not all:

RedrawWindow(hwnd,&d,nullptr,RDW_UPDATENOW);

i can't use the WS_CLIPCHILDREEN on parent, or the RedrawWindow() don't clean the control. but i accept sugestions

This article has been dead for over six months. Start a new discussion instead.