- This topic has 21 replies, 2 voices, and was last updated 4 years, 2 months ago by HeDiBo.
-
AuthorPosts
-
August 24, 2020 at 1:50 pm #69327HeDiBoParticipant
Here are two gifs, showing a horrible painting problem in AC 15.14.
The problem manifests itself when on a TsDBNavigator the “Last Record” button is clicked.
The first GIF shows what happens when the button is clicked and the mouse is not moved.
The second GIF shows the same thing, but now the mouse is moved away from the “Last Record” button.
Watch and weep.Attachments:
You must be logged in to view attached files.August 24, 2020 at 8:54 pm #69343SupportKeymasterWhat happens after a button clicking? Some controls are resized?
August 25, 2020 at 10:14 am #69349HeDiBoParticipantA 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.
August 25, 2020 at 10:17 am #69350HeDiBoParticipantIf I set the Active property of the SkinManager to False, the problem disappears. So, it’s definitely an AC problem.
August 26, 2020 at 9:39 am #69353HeDiBoParticipantThis 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).August 26, 2020 at 9:55 am #69354HeDiBoParticipantIs 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.
August 26, 2020 at 1:05 pm #69355HeDiBoParticipantI 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.August 26, 2020 at 2:08 pm #69357HeDiBoParticipantThanks 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 4 years, 3 months ago by HeDiBo.
Attachments:
You must be logged in to view attached files.August 27, 2020 at 10:19 am #69362HeDiBoParticipantBecause 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 4 years, 3 months ago by HeDiBo.
August 27, 2020 at 11:23 am #69364HeDiBoParticipantIf 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.August 29, 2020 at 6:24 pm #69379SupportKeymasterAre you sure that you can’t give me a demo with such behaviour?
I think, you know better how to repeat it..August 30, 2020 at 9:19 am #69384HeDiBoParticipantSince 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.
August 30, 2020 at 10:27 am #69385HeDiBoParticipantI 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).
August 30, 2020 at 11:22 am #69386HeDiBoParticipantChanging 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.September 2, 2020 at 8:41 pm #69402SupportKeymasterDo 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..
September 3, 2020 at 9:26 am #69416HeDiBoParticipantI 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.
September 3, 2020 at 10:11 am #69417HeDiBoParticipantMaybe 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.September 7, 2020 at 1:20 pm #69434HeDiBoParticipantNo 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 4 years, 2 months ago by HeDiBo.
September 9, 2020 at 4:34 pm #69501SupportKeymasterI will uncomment this line soon.
September 9, 2020 at 6:29 pm #69516HeDiBoParticipantThat 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? -
AuthorPosts
- You must be logged in to reply to this topic.