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

    Graphics glitches in Win32 main window Skinning while updating STATIC controls

    Graphics glitches in Win32 main window Skinning while updating few STATIC controls periodically.

    I am in desperate need of a solution or a pointer to what may be wrong.
    I am skinning an app as follows:

    **In WM_CREATE**

    DestroyCaption( hwnd,wWidth,wHeight );
    // update window style
    SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
    SetLayeredWindowAttributes(hwnd, g_ColourKey, 0, LWA_COLORKEY);

    And painting the bitmap in the **WM_PAINT** message :

    case WM_PAINT:
    {
    PAINTSTRUCT ps;

    HDC hdc = BeginPaint(hwnd, &ps);

    PaintWindow( hwnd, hdc, wWidth, wHeight );

    EndPaint(hwnd, &ps);
    }
    break;
    ...
    ...


    void PaintWindow( HWND hwnd, HDC hdc, int wWidth, int wHeight )
    {
    HDC dcSkin = CreateCompatibleDC( hdc );

    SelectObject( dcSkin, hSkinBmp );
    BitBlt( hdc, 0, 0, wWidth, wHeight, dcSkin, 0, 0, SRCCOPY );

    DeleteDC( dcSkin );

    SetTextColor( hdc, text_format.textcolor );
    SetBkMode( hdc,TRANSPARENT );
    HFONT hOldFont = (HFONT)SelectObject( hdc, text_format.hfont );

    TextOut( hdc, text_format.x, text_format.y, text_format.data.c_str(), strlen( text_format.data.c_str() ) );

    SelectObject( hdc, hOldFont );
    }

    Everything was working perfectly till I decided to update few **STATIC** controls' text with SetWindowText during an event which occurs in a different thread periodically, approximately once per second, the text on the STATIC controls gets updated only in every 10th iteration of this event. I am using SendMessage() to send WM_USER message to the main window which in turn updates the STATIC controls.

    Now the skin of the window just goes away after a minute or so of running the app and there only remains grey rectangle, the buttons which have custom skins set with **BM_SETIMAGE** doesn't get affected by this error.

    Now I am totally out of ideas on what would be going wrong. What you think I should be taking care of while doing something like this ?

    **If I stop the update of the STATIC controls in the WM_USER handler, the graphic problem goes away.**

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

    Re: Graphics glitches in Win32 main window Skinning while updating STATIC controls

    Quote Originally Posted by Lisa.Neeb View Post
    Everything was working perfectly till I decided to update few **STATIC** controls' text with SetWindowText during an event which occurs in a different thread periodically, approximately once per second, the text on the STATIC controls gets updated only in every 10th iteration of this event. I am using SendMessage() to send WM_USER message to the main window which in turn updates the STATIC controls.
    You provide no details on how your main window really "updates the STATIC controls". Besides, considering the fact that SendMessage blocks GUI thread when called from other thread I would say that some other way needed for notifying GUI thread. First I would try to switch to PostMessage. Another thing is WM_USER which message is not recommended to use, and WM_APP must be used instead.

    And I can see no reason to blit bitmap separately from texting out. The text may be output to memory dc alright, and the only action affecting paint dc would be the final blit.

    Now the skin of the window just goes away after a minute or so of running the app and there only remains grey rectangle, the buttons which have custom skins set with **BM_SETIMAGE** doesn't get affected by this error.
    That grey rectangle gives me an impression of you exhausting GDI handles by not properly releasing GDI resources. Not obligatory this is related to your static updates.

    **If I stop the update of the STATIC controls in the WM_USER handler, the graphic problem goes away.**
    Best regards,
    Igor

  3. #3
    Join Date
    Mar 2011
    Posts
    7

    Re: Graphics glitches in Win32 main window Skinning while updating STATIC controls

    I must say, out of all the forums I have asked yours is the most educated answer

    Quote Originally Posted by Igor Vartanov View Post
    You provide no details on how your main window really "updates the STATIC controls".
    I was Setting the text of the controls with SetWindowText(), then I changed it to SendMessage( WM_SETTEXT ) and this change did affect the problem, In the short run that I was able to test the app it didn't reproduce the graphic error.

    Quote Originally Posted by Igor Vartanov View Post
    Besides, considering the fact that SendMessage blocks GUI thread when called from other thread I would say that some other way needed for notifying GUI thread. First I would try to switch to PostMessage
    I was using PostMessage but on an another forum people suggested that I should use SendMessage then I don't have to worry about synchronization. But I guess since I am sending pointers to global string through WM_USER and even if the values of these string change it won't affect the outcome, I am safe ??

    Quote Originally Posted by Igor Vartanov View Post
    Another thing is WM_USER which message is not recommended to use, and WM_APP must be used instead.
    Wasn't even aware about WM_APP(am new to this stuff), can you please explain why I should use WM_APP instead ?

    Quote Originally Posted by Igor Vartanov View Post
    And I can see no reason to blit bitmap separately from texting out. The text may be output to memory dc alright, and the only action affecting paint dc would be the final blit.
    Point taken.

    Quote Originally Posted by Igor Vartanov View Post
    That grey rectangle gives me an impression of you exhausting GDI handles by not properly releasing GDI resources. Not obligatory this is related to your static updates.
    Hmm. possibly the best explanation of the problem cause I have found till, seems logical, I will check if there are GDI leaks.

  4. #4
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,620

    Re: Graphics glitches in Win32 main window Skinning while updating STATIC controls

    Quote Originally Posted by Lisa.Neeb View Post
    I was Setting the text of the controls with SetWindowText(), then I changed it to SendMessage( WM_SETTEXT ) and this change did affect the problem, In the short run that I was able to test the app it didn't reproduce the graphic error.
    As I can see from your code, the text is provided via text_format structure. So why would you use native SetWindowText call?

    In case you provide the text this way, the only thing you need to update the static window is InvalidateRect(hwndStatic, NULL, TRUE).

    Besides, there's no need to do that in main thread, as entire Windows API is thread safe, and therefore you can InvalidateRect or SetWindowText immediately in context of your worker thread alright. Of course in case of InvalidateRect+WM_PAINT your text reading/writing must have a protection against simultaneous access, by means of critical section, for example.


    I was using PostMessage but on an another forum people suggested that I should use SendMessage then I don't have to worry about synchronization. But I guess since I am sending pointers to global string through WM_USER and even if the values of these string change it won't affect the outcome, I am safe ??
    Yes, you're right, posting messages doesn't get along with pointers. But I cannot see any reason so far for passing pointers to notify your main thread to update static texts. (see above)


    Wasn't even aware about WM_APP(am new to this stuff), can you please explain why I should use WM_APP instead ?
    WM_USER came from Windows 3.x ages. Windows 95/NT provide new style common controls like list view, header bar, tool bar, etc., that internally use WM_USER. So to avoid any conflicts applications must use WM_APP and upper values for their custom messages.
    Last edited by Igor Vartanov; December 12th, 2012 at 03:20 AM.
    Best regards,
    Igor

  5. #5
    Join Date
    Mar 2011
    Posts
    7

    Re: Graphics glitches in Win32 main window Skinning while updating STATIC controls

    Quote Originally Posted by Igor Vartanov View Post
    As I can see from your code, the text is provided via text_format structure. So why would you use native SetWindowText call?

    In case you provide the text this way, the only thing you need to update the static window is InvalidateRect(hwndStatic, NULL, TRUE).

    Besides, there's no need to do that in main thread, as entire Windows API is thread safe, and therefore you can InvalidateRect or SetWindowText immediately in context of your worker thread alright. Of course in case of InvalidateRect+WM_PAINT your text reading/writing must have a protection against simultaneous access, by means of critical section, for example.
    The WM_PAINT handler is for the main window, its not for STATIC control. I was advised to never update window from another thread, so I changed it such a way that whenever the static control in needed to be updated with anew text the main window is sent a message(WM_APP) and in that message handler the new text is set. Prior to that I was simple updating the static controls from worker thread.


    Quote Originally Posted by Igor Vartanov View Post
    Yes, you're right, posting messages doesn't get along with pointers. But I cannot see any reason so far for passing pointers to notify your main thread to update static texts. (see above)


    WM_USER came from Windows 3.x ages. Windows 95/NT provide new style common controls like list view, header bar, tool bar, etc., that internally use WM_USER. So to avoid any conflicts applications must use WM_APP and upper values for their custom messages.
    Thanks

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

    Re: Graphics glitches in Win32 main window Skinning while updating STATIC controls

    Quote Originally Posted by Lisa.Neeb View Post
    I was advised to never update window from another thread
    Okay, now you've been advised the opposite. The awkward moment.

    Prior to that I was simple updating the static controls from worker thread.
    And you were right. As I already said, Win32 API is fully thread safe, and the reason to do some detour to this natively supported behavior must be really, really grounded.

    I could imagine the following scenario for updates of this kind done from main thread:
    • The text data exchange done via some storage (variable, structure, map, whatever) accessible from both threads
    • Writer locks the storage, writes data, unlocks the storage and posts a notification message to main thread
    • Main thread pumps its message queue, finally gets the notification message, locks the storage, reads data to a local buffer, unlocks the storage, updates static control text with the text copy in local bufer

    The whole sense of this complex exchange is the only: nobody locks anybody's thread while updating GUI controls. In the light of this your approach makes no sense: SendMessage locks worker thread and intrudes into normal message pumping. As for me it's much better to let Windows decide how to do the task most effective way.
    Last edited by Igor Vartanov; December 16th, 2012 at 04:29 AM.
    Best regards,
    Igor

Tags for this Thread

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