Paint problem in AC 15.14

Viewing 20 posts - 1 through 20 (of 21 total)
  • Author
    Posts
  • #69343
    Support
    Keymaster

      What happens after a button clicking? Some controls are resized?

      #69349
      HeDiBo
      Participant

        A whole panel with buttons appears at the bottom causing all other controls to move up or resize.

        There are more ways to make this panel appear. In the navigator I could press the Next Record button. If that would bring me to the last record also, the panel with buttons would appear also.

        The strange thing is, that only pressing the Last Record button produces the effect shown. I’m going to make a trace, to see what the difference between these two is.

        #69350
        HeDiBo
        Participant

          If I set the Active property of the SkinManager to False, the problem disappears. So, it’s definitely an AC problem.

          #69353
          HeDiBo
          Participant

            This is a very nasty problem to debug. As soon as I type Alt-Tab to Pause the running program in the IDE it has already disappeared.
            It happens in all windows configurations (Win 32 / 64 with or without debugging).

            #69354
            HeDiBo
            Participant

              Is there any way to start a log in code at a certain moment, to show the Windows messages being sent? It should not involve any user action: that would cancel the problem immediately.

              #69355
              HeDiBo
              Participant

                I managed to capture a list of Windows Messages starting right after the bottom panel was made visible.
                Remarkable are the countless WM_USER+41216 (0xA100) messages. There are two sets of them marked in the file.

                Attachments:
                You must be logged in to view attached files.
                #69357
                HeDiBo
                Participant

                  Thanks to Spy++ from the MS Visual Studio package, I was able to generate another trace, that shows quite clearly where the problem is.
                  There is an endless repetition of

                  <002618> 001F0650 S WM_SETCURSOR hwnd:007C0BA4 nHittest:HTCLIENT wMouseMsg:WM_MOUSEMOVE
                  <002619> 001F0650 R WM_SETCURSOR fHaltProcessing:False

                  which, I think, is an event that is not shown as completed. Therefore it repeats itself.

                  • This reply was modified 5 years, 6 months ago by HeDiBo.
                  Attachments:
                  You must be logged in to view attached files.
                  #69362
                  HeDiBo
                  Participant

                    Because clicking the Next Record button to reach the last record did not produce this bug, I added a TDBNavigator to the frame. It shares the OnClick event with the TsDBNavigator. Clicking the Last Record button on that navigator does not produce the error 😲

                    I already had the suspicion that it was the Last Record click itself that caused it. The Spy++ trace also goes in that direction.

                    Then I added a TsDBNavigator in stead. And now the problem does not occur. Which means it must be related to the specific place of the original TsDBNavigator. Notice that the original TsDBNavigator moves up to make room for the panel made visible. The difference between the Next Record and Last Record buttons is: the specific Hint shown!! And indeed, when I’m quick in clicking the Last Record, before the Hint would be shown, the problem does not occur.

                    What then is the significant difference between Next and Last record (apart from the slightly different text of their hints)?

                    If the navigator moves up to make room for the panel made visible, the buttons in the panel are shown each with their own hints. And sure enough, if I disable the hint for the button below the Last Record button, the problem goes away. But why does it go OK on the Next Record button? The hint that appears on the button below the Next Record button is a short one. The one below the Last Record button is a longer two line hint.

                    Bringing us to the cause of the problem: timing!! If the hint which appears immediately below the navigator button is long enough to cause a bit of time to paint, the click handling of the navigator button goes haywire.

                    It’s ironic to conclude that the bug of showing the hint without any pause to speak of, causes this bug (it’s still a bug) to appear.

                    • This reply was modified 5 years, 6 months ago by HeDiBo.
                    #69364
                    HeDiBo
                    Participant

                      If HandleDisabledCtrls is False, the problem disappears. That’s remarkable, because the button that comes into view is a TsSpeedButton, which will show the hint also if disabled.
                      That narrows the problem to AC’s specific code for hints on disabled controls.

                      #69379
                      Support
                      Keymaster

                        Are you sure that you can’t give me a demo with such behaviour?
                        I think, you know better how to repeat it..

                        #69384
                        HeDiBo
                        Participant

                          Since it is clearly a timing problem, even if I could reproduce this very complicated setup as a demo project, it would probably not repeat itself in your environment. It may even be unrepeatable in my own environment.

                          The endless repetition of WM_SETCURSOR in the SPY++ trace (they come during the idle time, when waiting for the controls to complete painting) means that a mouse message is not handled. This is the explanation of Microsoft about the WM_SETCURSOR message:

                          The DefWindowProc function passes the WM_SETCURSOR message to a parent window before processing. If the parent window returns TRUE, further processing is halted. Passing the message to a window’s parent window gives the parent window control over the cursor’s setting in a child window. The DefWindowProc function also uses this message to set the cursor to an arrow if it is not in the client area, or to the registered class cursor if it is in the client area. If the low-order word of the lParam parameter is HTERROR and the high-order word of lParam specifies that one of the mouse buttons is pressed, DefWindowProc calls the MessageBeep function.

                          As you can see: if not returning TRUE, the message keeps repeating.

                          #69385
                          HeDiBo
                          Participant

                            I found a way to prevent the bug. The bug stays I think, but it is not visible anymore.

                            In acAlphaHints is a procedure TacCustomHintWindow.ActivateHint. On roughly 1/3 of its code, I found:

                                Manager.KillTimer;
                            //    Application.ProcessMessages; // Patch for refresh of columns in cxGrid
                                if Manager.Active then
                                  Text := AHint
                                else
                                  Caption := AHint;

                            If I remove the comment (execute Application.ProcessMessages) the problem goes away. However it introduces a possible Access Violation on the Text := AHint statement. I could not repeat the error, because Application.ProcessMessages is very timing dependent. Also it’s an extremely dangerous statement, making it possible to send messages totally out of context.

                            My problem indeed has a cxGrid, that is repopulated and resized during the panel visibility change. This find may allow you to narrow down the cause (I could imagine it is in acLFPainter).

                            #69386
                            HeDiBo
                            Participant

                              Changing the code to:

                                  Manager.KillTimer;
                                  if Manager.Active then
                                    Text := AHint
                                  else
                                    Caption := AHint;
                              (****** DB ********)
                                  Application.ProcessMessages; // Patch for refresh of columns in cxGrid
                              (******************)

                              seems to circumvent the AV.
                              But as I said, Application.ProcessMessages may cause all kind of problems.

                              #69402
                              Support
                              Keymaster

                                Do you know which control doesn’t handle the WM_SETCURSOR message?

                                Really, using of the Application.ProcessMessages is dongerous in some situations, it’s a reason why this line has been commented. I need to repeat the issue somehow..

                                #69416
                                HeDiBo
                                Participant

                                  I wasn’t saying that Application.ProcessMessages should be done. I only enabled the statement at the right place (the commented one was in the wrong place) to find out what it was for. And to my surprise the problem disappeared.
                                  So, your comment (Patch for refresh of columns in cxGrid) was the one that made me think that the presence of a cxGrid on this Frame caused the problem. Can you recollect why you made this comment?
                                  The WM_SETCURSOR message is normally left unhandled. There must be another reason why it repeats.

                                  The SPY++ trace has this at the end of the endless WM_SETCURSOR messages:

                                  <002801> 001F0650 R WM_SETCURSOR fHaltProcessing:False
                                  <002802> 001F0650 S WM_SETCURSOR hwnd:002309EC nHittest:HTCLIENT wMouseMsg:WM_MOUSEMOVE
                                  <002803> 001F0650 R WM_SETCURSOR fHaltProcessing:False
                                  <002804> 001F0650 S WM_SETCURSOR hwnd:002309EC nHittest:HTCLIENT wMouseMsg:WM_MOUSEMOVE
                                  <002801> 001F0650 R WM_SETCURSOR fHaltProcessing:False
                                  <002802> 001F0650 S WM_SETCURSOR hwnd:002309EC nHittest:HTCLIENT wMouseMsg:WM_MOUSEMOVE
                                  <002803> 001F0650 R WM_SETCURSOR fHaltProcessing:False
                                  <002804> 001F0650 S WM_SETCURSOR hwnd:002309EC nHittest:HTCLIENT wMouseMsg:WM_MOUSEMOVE
                                  <002805> 001F0650 R WM_SETCURSOR fHaltProcessing:False
                                  <002806> 001F0650 S message:0xA100 [User-defined:WM_APP+8448] wParam:000A0000 lParam:00000000
                                  <002807> 001F0650 R message:0xA100 [User-defined:WM_APP+8448] lResult:00000000
                                  <002808> 001F0650 S message:0xA100 [User-defined:WM_APP+8448] wParam:000A0000 lParam:00000000
                                  <002809> 001F0650 R message:0xA100 [User-defined:WM_APP+8448] lResult:00000000
                                  <002810> 001F0650 S WM_SETCURSOR hwnd:000E0848 nHittest:HTCLIENT wMouseMsg:WM_MOUSEMOVE
                                  <002811> 001F0650 R WM_SETCURSOR fHaltProcessing:False
                                  <002812> 001F0650 S message:0xA100 [User-defined:WM_APP+8448] wParam:000A0000 lParam:00000000
                                  <002813> 001F0650 R message:0xA100 [User-defined:WM_APP+8448] lResult:00000000
                                  <002814> 001F0650 S message:0xA100 [User-defined:WM_APP+8448] wParam:000A0000 lParam:00000000
                                  <002815> 001F0650 R message:0xA100 [User-defined:WM_APP+8448] lResult:00000000
                                  <002816> 001F0650 S WM_SETCURSOR hwnd:000E0848 nHittest:HTCLIENT wMouseMsg:WM_MOUSEMOVE
                                  <002817> 001F0650 R WM_SETCURSOR fHaltProcessing:False
                                  <002818> 001F0650 S message:0xA100 [User-defined:WM_APP+8448] wParam:000A0000 lParam:00000000
                                  <002819> 001F0650 R message:0xA100 [User-defined:WM_APP+8448] lResult:00000000
                                  <002820> 001F0650 S message:0xA100 [User-defined:WM_APP+8448] wParam:000A0000 lParam:00000000
                                  <002821> 001F0650 R message:0xA100 [User-defined:WM_APP+8448] lResult:00000000
                                  <002822> 001F0650 S message:0xA100 [User-defined:WM_APP+8448] wParam:000A0000 lParam:00000000
                                  <002823> 001F0650 R message:0xA100 [User-defined:WM_APP+8448] lResult:00000000
                                  <002824> 001F0650 S message:0xA100 [User-defined:WM_APP+8448] wParam:000A0000 lParam:00000000
                                  <002825> 001F0650 R message:0xA100 [User-defined:WM_APP+8448] lResult:00000000
                                  <002826> 001F0650 S message:0xA100 [User-defined:WM_APP+8448] wParam:000A0000 lParam:00000000
                                  <002827> 001F0650 R message:0xA100 [User-defined:WM_APP+8448] lResult:00000000
                                  <002828> 001F0650 S message:0xA100 [User-defined:WM_APP+8448] wParam:000A0000 lParam:00000000
                                  <002829> 001F0650 R message:0xA100 [User-defined:WM_APP+8448] lResult:00000000
                                  <002830> 001F0650 S message:0xA100 [User-defined:WM_APP+8448] wParam:000A0000 lParam:00000000
                                  <002831> 001F0650 R message:0xA100 [User-defined:WM_APP+8448] lResult:00000000
                                  <002832> 001F0650 S WM_SETCURSOR hwnd:000E0848 nHittest:HTCLIENT wMouseMsg:WM_MOUSEMOVE
                                  <002833> 001F0650 R WM_SETCURSOR fHaltProcessing:False

                                  It must be a non-windows message. Do you recognize the WM_APP+8448 message ID?

                                  The TcxContainer class contains this:

                                  procedure TcxContainer.WMSetCursor(var Message: TWMSetCursor);
                                  begin
                                    with Message do
                                      if HasInnerControl and (CursorWnd = Handle) and
                                        (Smallint(HitTest) = HTCLIENT) and not PtInRect(ViewInfo.ClientRect, GetMouseCursorClientPos) then
                                      begin
                                        Windows.SetCursor(Screen.Cursors[crArrow]);
                                        Result := 1;
                                        Exit;
                                      end;
                                    inherited;
                                  end;

                                  That looks as a potential candidate. TcxContainer is the base class of TcxCustomEdit and every cell in a grid is essentially an edit field. The scroll may cause the grid cells to shift, making the test not PtInRect(ViewInfo.ClientRect permanently True. But it may also be my wild imagination.

                                  #69417
                                  HeDiBo
                                  Participant

                                    Maybe you noticed also, that the clicking of the Last Record button inserts a new column at the left hand side of the grid. I’m going to test if that’s what makes the bug surface.
                                    But don’t forget: if the Next Record button lands on the Last Record, the same operations take place. But the bug does not.
                                    And indeed, if I keep the first column visible, the bug does not surface.

                                    #69434
                                    HeDiBo
                                    Participant

                                      No change in AC 15.15 😒
                                      Why did you put the comment “Patch for refresh of columns in cxGrid” in the source? That’s exactly what happens here.

                                      • This reply was modified 5 years, 6 months ago by HeDiBo.
                                      #69501
                                      Support
                                      Keymaster

                                        I will uncomment this line soon.

                                        #69516
                                        HeDiBo
                                        Participant

                                          That is inadvisable. Application.ProcessMessages may have problematic side effects.
                                          There may be a safer place a bit more down in the code.
                                          Do you remember why you put it there? What problem with columns in CxGrid was it supposed to cure?

                                          #69542
                                          Support
                                          Keymaster

                                            This line has been added, because column headers has not been redrawn under hints in some cases.
                                            It was commented because I was searching a better way to solve a problem and I thought that problem is solved.

                                          Viewing 20 posts - 1 through 20 (of 21 total)
                                          • You must be logged in to reply to this topic.