Window and Taskbar becomes unresponsive

This is a discussion on Window and Taskbar becomes unresponsive within the Windows Programming forums, part of the Platform Specific Boards category; I have made a RPC server that displays that status of what the client is doing with the application. The ...

  1. #1
    Registered User
    Join Date
    Dec 2009
    Posts
    6

    Window and Taskbar becomes unresponsive

    I have made a RPC server that displays that status of what the client is doing with the application. The RPC server is a simple windows app that draw the text with DrawText along with the task bar icon display a 'busy status' that show a spinning icon to indicate that the client is doing something.

    After awhile the windows app will just stop being responsive and the taskbar icon will disappear. The menu bar will also become unusable. I'm not sure what's going on since there are no memory leaks.

    Is the issue would be that there is too many WM_PAINT occurring? The client send a text to the server and it can call "UpdateStatus" to tell the server that it need to display the information in the windows app. The server will call "InvalidateRect(m_hWnd, NULL, TRUE);" since the server doesn't know exactly how much string need to be redrawn on the window so I just invalidate all of the window so that the WM_PAINT will get sent to my windows callback and then I just call my "CServer::Paint()".

    Code:
    void CServer::Paint(void)
    {
        RECT        rt;
        HDC         hdc;
        LOGFONT     lf;
        PAINTSTRUCT ps;
        wstring     wstr;
    
        wstr = GetStatus();
    
        hdc = BeginPaint(m_hWnd, &ps);
    
        SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));
    
        GetClientRect(m_hWnd, &rt);
    
        DrawText(hdc, wstr.c_str(), wstr.length(), &rt, DT_LEFT);
    
        DeleteObject(SelectObject(hdc, CreateFontIndirect(&lf)));
    
        EndPaint(m_hWnd, &ps);
    
        return;
    }

  2. #2
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,856
    You are leaking GDIs.

    In Taskmanager, select 'View', then 'Select Columns'. Check 'GDI Objects' and run your app, look for a leak (comment out the paint).

    The reason is that you have to return the DC back to the default state and you can not delete STOCK GDI objects (though usually nothing bad happens).

    Also CreateFontIndirect() is probably failing to create a font based on an uninitialzed structure.

    SelectObject() 'pushes' out the current/default object and you should 'catch' it and put it back when you clean up.

    Code:
    //not at a complier so my not be 100% bug free
    
    //change the font, but catch default
    HFONT *hOriginalFont = (HFONT*)SelectObject(hdc, SomeFont); 
    
    //draw
    
    //clean up font
    SelectObject(hdc, hOriginalFont); //put the DC back teh way we got it
    DeleteObject(SomeFont);//delete any GDI we got from a CreateXXX()
    
    //If we used GetDC() call ReleaseDC()
    The DC will also probably already contain the default GUI font (the paint DC has the windows current brush, pen, font etc)
    Have a look at FillRect() to clear previous text.
    I would also be worried if GetStatus() is a long process.

    It might be better to have some pump looking for status changes. This is because paint has to be as fast as possible and can be called repeatedly by the OS. (Drag a msgbox over your app and see if it 'shears')

    Code:
    wstr = GetStatus();
    if(wstr != m_wstrCurrentStatus)//see if status changed
    {
         //set member string
         m_wstrCurrentStatus = wstr;
         //send a paint msg
         InvalidateRect(m_hWnd, NULL, FALSE);
         //send direct to callback for faster response
         UpdateWindow(m_hWnd);
    }
    in paint just use m_wstrCurrentStatus in Drawtext() (instead of calling GetStatus() )
    Last edited by novacain; 12-13-2009 at 03:06 AM.
    "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
    Dec 2009
    Posts
    6
    It was DeleteObject(SelectObject(hdc, CreateFontIndirect(&lf))); that was leaking the GDIs, never thought of checking that before. And also you mentioned that lf was not initialized and that line should have been removed since I was doing other things and decided not to use lf.

    Now my window is running much better.

    As for the SelectObject, is it okay that I remember the font handle as in

    Code:
    if (m_hOriginalFont == NULL) {
        m_hOriginalFont = (HFONT*)SelectObject(hdc, SomeFont); 
    }
    And never delete it until the application is exiting?

  4. #4
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,856
    No, not in this case.

    You do not keep/get the same HDC each paint msg.

    BeginPaint() returns the HDC, EndPaint() cleans up the GDI, including releaseing/deleting the HDC.

    If you had called CreateCompatibleDC() and saved the HDC (for the same time as the font) as a member, then yes.

    I suggest you move towards the 'pump' I suggested (paint msg handler contains as little code as possible).
    When any of your app is covered by another window a paint msg will be called from the OS, so GetStatus() will be called, many times per second (and not just when you want it to). Windows has some protection against this (paint msgs are merged in the msg queue) but you will see 'shearing' if GetStatus() takes more than a few millisec.

    That pattern will save you headaches in the future.
    Last edited by novacain; 12-13-2009 at 10:33 PM.
    "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
    Dec 2009
    Posts
    6
    I moved the GetStatus to the CServer::RunStatusUpdate thread that was forcing the WM_PAINT. CServer::Paint() should be faster.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. WM_CAPTION causing CreateWindowEx() to fail.
    By Necrofear in forum Windows Programming
    Replies: 8
    Last Post: 04-06-2007, 08:23 AM
  2. Getting all window handles on taskbar
    By Yuri in forum Windows Programming
    Replies: 1
    Last Post: 06-17-2006, 04:31 PM
  3. Making dialog box the only window
    By PJYelton in forum Windows Programming
    Replies: 2
    Last Post: 09-06-2005, 12:02 PM
  4. Create window without taskbar icon?
    By SMurf in forum Windows Programming
    Replies: 2
    Last Post: 02-04-2002, 02:05 AM
  5. Winamp Vis if anyone can help
    By Unregistered in forum Windows Programming
    Replies: 6
    Last Post: 01-26-2002, 11:43 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21