CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 6 of 6
  1. #1
    Join Date
    Feb 2009
    Posts
    9

    Button with BW_OWNERDRAW make nonsens if i use a Timer Function

    Hi everybody,
    i have a program that has two buttons. The first button shows a part of the calculator (calc.exe small view) window and the other button has a bitmap on it and when i click on the button the bitmap is changing.
    Ive created both buttons with the BS_OWNERDRAW style and i use the DRWAWITEM function for their properties. Actually everything is ok when i start the program and all works fine. But after one or two minutes the bitmap on the bitmap-button is away and if i want to resize or move the mainwindow the hole desktop-background is redrawing.

    I guess the timer-function is the reason for this problem cause if i disable the timer-function the problem dont exist anymore. But i need a timer-function in my program cause the button who shows a part of the calculator (calc.exe small view) should always refreshed (at least every second) automaticly (without any click). I tried to find a solution for this error over google but until now i didnt get any hint to solve that problem. Maybe anybody knows what is wrong in my scrpit and let me know what is the cause for the problem and how can i change it. Thanks a lot for every help in advance! best regards, rommi
    Code:
    #include <windows.h>
    #include <stdio.h>
    #include <tchar.h>
     
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    LPCSTR lpszAppName          = "AppName";
    char szNewButtonClassName[] = "newbutton";
    HINSTANCE hInstance;
     
    HWND hWnd;
    HWND *btn                   = new HWND[100];
    HWND hwndcalc;
    HDC hdccalc;
    HDC CopyDC;
     
    const UINT Timer1           = 1;
    TCHAR title[2];
    HBITMAP bmpcalc;
     
    // ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
    // XXXXXX                                       Sub`s                                                           XXXXXXXX
    // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    int DrawItem(UINT wParam,LPARAM lParam)
    {
        LPDRAWITEMSTRUCT lpdis = (DRAWITEMSTRUCT*)lParam;
        HDC hdca = ((LPDRAWITEMSTRUCT)(lParam))->hDC;
        HDC hdcMem = CreateCompatibleDC(hdca);
        HBITMAP hBitmap;
     
        //XXX Buttons sunken und raise 
        DrawEdge(lpdis->hDC, &lpdis->rcItem,(lpdis->itemState & ODS_SELECTED ? EDGE_SUNKEN : EDGE_RAISED ), BF_RECT);
     
     
        if (((LPDRAWITEMSTRUCT)(lParam))->itemState & ODS_SELECTED){}
        else
        {
            switch(lpdis->CtlID)        //XXXX Abfrage Kontroll-ID
            {
                default:
     
                    if( lpdis->CtlID == 0)  // Button mit Bild
                    {
                        ZeroMemory(title, sizeof(title));
                        GetWindowText(btn[lpdis->CtlID], title, sizeof(title)/sizeof(title[0]));
                        if(_tcsstr(title, _T("F")))
                        {
                            hBitmap = (HBITMAP)LoadImage(0,"c:\\F.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
                            SelectObject (hdcMem, hBitmap);
                            BitBlt (hdca, 0, 0, 30, 30, hdcMem, 0, 0, SRCCOPY) ;
                        }
                        else if (_tcsstr(title, _T("X")))
                        {
                            hBitmap = (HBITMAP)LoadImage(0,"c:\\X.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
                            SelectObject (hdcMem, hBitmap);
                            BitBlt (hdca, 0, 0, 30, 30, hdcMem, 0, 0, SRCCOPY) ;
                        }
                    break;
                    }
                    else if( lpdis->CtlID == 1 )    // Button mit dem Calc-Ausschnitt
                    {
                        BitBlt (hdca,20,10,70,25,hdccalc,180, 40,SRCCOPY);  
                    }
     
                break;
            }
        }
    return 1;
    }
     
     
    void refresh()
    {
        InvalidateRect(hWnd, NULL, TRUE);
    }
     
    // ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
    // XXXXXX                                       Main                                                            XXXXXXXX
    // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow)
    {
        //XXXX für den Button mit dem Calculator-Ausschnitt
        hwndcalc = FindWindow( 0, "Rechner");
        hdccalc = GetWindowDC(hwndcalc);
        CopyDC = CreateCompatibleDC (hdccalc);
        bmpcalc = CreateCompatibleBitmap (hdccalc,70 ,25 );
        SelectObject (CopyDC, bmpcalc);
     
        //XXXX Button-Klasse (Doppel-Klick etc. modifiziert)
        WNDCLASS ClassNewButton;
        if( GetClassInfo(hInstance, "button",&ClassNewButton) )
        {
            ClassNewButton.hCursor = LoadCursor(NULL, IDC_HAND);
            ClassNewButton.lpszClassName = szNewButtonClassName;
            ClassNewButton.style &= ~((UINT)CS_DBLCLKS);// ****** turn off CS_DBLCLKS style
            RegisterClass(&ClassNewButton);
        }
     
        //XXXXX Main-Klasse
        MSG         msg;
        WNDCLASSEX  wc;
     
        wc.cbSize        =  sizeof(WNDCLASSEX);
        wc.style         =  CS_HREDRAW | CS_VREDRAW;
        wc.lpfnWndProc   =  WndProc;
        wc.cbClsExtra    =  0;
        wc.cbWndExtra    =  0;
        wc.hInstance     =  hInstance;
        wc.hCursor       =  LoadCursor(NULL,IDC_ARROW);
        wc.hIcon         =  LoadIcon(NULL, IDI_APPLICATION);
        wc.hbrBackground =  (HBRUSH)GetStockObject(WHITE_BRUSH);
        wc.lpszClassName =  lpszAppName;
        wc.lpszMenuName  =  lpszAppName;
        wc.hIconSm       =  LoadIcon(NULL, IDI_APPLICATION);
        if( RegisterClassEx(&wc) == 0) return 0;
     
        //XXXX Erstell das Haupt-Fenster
        hWnd = CreateWindowEx(WS_EX_COMPOSITED,lpszAppName,"Main",WS_OVERLAPPEDWINDOW,200,200,208,126,NULL,NULL,hInstance,NULL);
        ShowWindow(hWnd, iCmdShow);
        UpdateWindow(hWnd);
     
        //XXXX Erstell die Buttons
        btn[0] = CreateWindow(szNewButtonClassName,"F",WS_CHILD|WS_VISIBLE|BS_OWNERDRAW,0,0,100,100,hWnd,(HMENU)0,hInstance,NULL);
        btn[1] = CreateWindow(szNewButtonClassName,"C",WS_CHILD|WS_VISIBLE|BS_OWNERDRAW,100,0,100,100,hWnd,(HMENU)1,hInstance,NULL);
     
        while (GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        return msg.wParam;
    }
     
    // ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
    // XXXXXX                                       Callback Main                                                   XXXXXXXX
    // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    LRESULT CALLBACK WndProc(HWND hWnd, UINT umsg, WPARAM wParam, LPARAM lParam)
    {
        PAINTSTRUCT ps;
        switch (umsg)
        {
            //_________________________________________
            case WM_CREATE:
            {
                    SetTimer(hWnd, Timer1, 20, NULL);
            }return 0;
            //_________________________________________
            case WM_TIMER:
            {
                refresh();
            }break;
            //_________________________________________    
            case WM_DESTROY:
            {
                KillTimer(hWnd, Timer1);
                PostQuitMessage(0);
            }return 0;
            //_________________________________________
            case WM_DRAWITEM:
            {
                    DrawItem(wParam,lParam);
            }break;
            //_________________________________________
            case WM_COMMAND:
            {
                switch(LOWORD(wParam))
                {
                    default:
                    {
                        //XXX Statusabfrage des Buttons mit dem Bild
                        if( lParam == (LPARAM)btn[wParam])
                        {
                            ZeroMemory(title, sizeof(title));
                            GetWindowText(btn[wParam], title, sizeof(title)/sizeof(title[0]));
     
                            if(_tcsstr(title, _T("X"))){SetWindowText(btn[wParam],"F");}
                            else{SetWindowText(btn[wParam],"X");}
                        }
                    }break;
                }
            }
            //_________________________________________
            case WM_PAINT:
            {
                BeginPaint(hWnd, &ps);
                    // mach was
                EndPaint(hWnd, &ps);
     
            }break;
     
        }return DefWindowProc(hWnd, umsg, wParam, lParam);
    }

  2. #2
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,633

    Re: Button with BW_OWNERDRAW make nonsens if i use a Timer Function

    after one or two minutes the bitmap on the bitmap-button is away and if i want to resize or move the mainwindow the hole desktop-background is redrawing.
    It's worth to doublecheck for GDI resource leak.
    Best regards,
    Igor

  3. #3
    Join Date
    Aug 2000
    Location
    New York, NY, USA
    Posts
    5,656

    Re: Button with BW_OWNERDRAW make nonsens if i use a Timer Function

    Quote Originally Posted by Igor Vartanov View Post
    It's worth to doublecheck for GDI resource leak.
    ... or at least to single-check DrawItem() function - none of the GDI resources created there are deleted.
    Vlad - MS MVP [2007 - 2012] - www.FeinSoftware.com
    Convenience and productivity tools for Microsoft Visual Studio:
    FeinWindows - replacement windows manager for Visual Studio, and more...

  4. #4
    Join Date
    Feb 2009
    Posts
    9

    Re: Button with BW_OWNERDRAW make nonsens if i use a Timer Function

    Thanks for your reply! I knew that ive forgotten something Ok now i have made the declaration of hdca, hdcMem and hBitmap global and delete all Objekts again on the end of the DrawItem() function. Now its running well ( i hope..)

    Thanks a lot for your comments and hints!!
    till next, regards, rommi

  5. #5
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,633

    Re: Button with BW_OWNERDRAW make nonsens if i use a Timer Function

    BTW, there's no need to load images each time you draw. See my bmpbtn sample I gave you before in some other thread.
    Best regards,
    Igor

  6. #6
    Join Date
    Feb 2009
    Posts
    9

    Re: Button with BW_OWNERDRAW make nonsens if i use a Timer Function

    @Igor thanks for the additional hint! regards,rommi

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