Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2013-01

Visual "uglyness" when creating TSynEdit @ runtime in my app

29 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Bart

Hi,

I have a text editor (LazEdit on Lazarus CCR) which uses a TPageControl to act like a Tabbed Document Interface (much like Lazarus SE).

Upon creating a new Tab it basically does:
- Add a new TTabSheet to the PageControl
- Create an instance of a TSynEdit
- Set TSynEdit.Parent to the newly created TTabSheet
- Set TSynEdit.Align := alClient

This works as expected.
However there is one visual anomaly: when you create a new Tab, for a brief moment you can see the TSynEdit, unaligned, with Width and Height set to it's defaults (like you would drop it on a Form in Lazarus).

Long time ago, in Delphi, I solved this by doing:

  Try
    LockWindowUpdate(TheHandle);
    ...
   //Create the TSynEdit, align it etc.
  Finally
    LockWindowUpdate(0);

This delayed any painting up to the point the TSynEdit was aligned. However, this is a Windows only fix.

The relevant code is at:
https://lazarus-ccr.svn.sourceforge.net/svnroot/lazarus-ccr/applications/lazedit/editorpagecontrol.pp (function TEditorPageControl.AddPage: TEditor; appr. at line 994)

Does anyone have a suggestion how to fix this in a cross-platform manner?

Bart

Reply by email

luiz americo pereira camara
to Bart

I do the following in my tab like control, and no glitches:

          Control := ControlClass.Create(Parent);
          Control.Visible := False;
          Control.Align := alClient;
          Control.Parent := Parent;
          Control.Visible := True;

2013/1/4 Bart :

Show quoted text 44 lines
Hi, I have a text editor (LazEdit on Lazarus CCR) which uses a TPageControl to act like a Tabbed Document Interface (much like Lazarus SE). Upon creating a new Tab it basically does: - Add a new TTabSheet to the PageControl - Create an instance of a TSynEdit - Set TSynEdit.Parent to the newly created TTabSheet - Set TSynEdit.Align := alClient This works as expected. However there is one visual anomaly: when you create a new Tab, for a brief moment you can see the TSynEdit, unaligned, with Width and Height set to it's defaults (like you would drop it on a Form in Lazarus). Long time ago, in Delphi, I solved this by doing: Try LockWindowUpdate(TheHandle); ... //Create the TSynEdit, align it etc. Finally LockWindowUpdate(0); This delayed any painting up to the point the TSynEdit was aligned. However, this is a Windows only fix. The relevant code is at: https://lazarus-ccr.svn.sourceforge.net/svnroot/lazarus-ccr/applications/lazedit/editorpagecontrol.pp (function TEditorPageControl.AddPage: TEditor; appr. at line 994) Does anyone have a suggestion how to fix this in a cross-platform manner? Bart -- _______________________________________________ Lazarus mailing list http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus

Reply by email

Mattias Gaertner
to Bart: I have a text editor (LazEdit on Lazarus CCR) which uses a TPageControl to act like a…
Show quoted text 36 lines
Hi, I have a text editor (LazEdit on Lazarus CCR) which uses a TPageControl to act like a Tabbed Document Interface (much like Lazarus SE). Upon creating a new Tab it basically does: - Add a new TTabSheet to the PageControl - Create an instance of a TSynEdit - Set TSynEdit.Parent to the newly created TTabSheet - Set TSynEdit.Align := alClient This works as expected. However there is one visual anomaly: when you create a new Tab, for a brief moment you can see the TSynEdit, unaligned, with Width and Height set to it's defaults (like you would drop it on a Form in Lazarus). Long time ago, in Delphi, I solved this by doing: Try LockWindowUpdate(TheHandle); ... //Create the TSynEdit, align it etc. Finally LockWindowUpdate(0); This delayed any painting up to the point the TSynEdit was aligned. However, this is a Windows only fix. The relevant code is at: https://lazarus-ccr.svn.sourceforge.net/svnroot/lazarus-ccr/applications/lazedit/editorpagecontrol.pp (function TEditorPageControl.AddPage: TEditor; appr. at line 994) Does anyone have a suggestion how to fix this in a cross-platform manner?

It sounds like a bug in the LCL Win32 interface.
I don't have win32 here to test.
There should be no Paint events during your code. Are there? What size has the SynEdit after setting Align to alClient and what is the ClientRect of the tabsheet?

About workarounds:
Set the Parent as last property or enclose the code in
  BeginAutoSizing;
  EndAutoSizing;

Mattias

Reply by email

Bart
to Mattias Gaertner
Mattias Gaertner wrote
It sounds like a bug in the LCL Win32 interface. I don't have win32 here to test. There should be no Paint events during your code. Are there?

How do I test this?

What size has the SynEdit after setting Align to alClient and what is the ClientRect of the tabsheet?

TS is the TabSheet that is the parent of E
TS has been created and it's property PageControl is set to the PageControl in question
At this stage:

TS.ClientRect = l=0,t=0,r=0,b=0
Before setting E.Align := alClient: E.Bounds = l=0,t=0,r=200,b=150
After  setting E.Align := alClient: E.Bounds = l=0,t=0,r=200,b=150
About workarounds: Set the Parent as last property

I remember doing that in the Delphi app and it made no difference, but I'll try it in Lazarus.

or enclose the code in BeginAutoSizing; EndAutoSizing;

I'll give that a try too.

Bart

Reply by email

Mattias Gaertner
to Bart
Show quoted text 7 lines
On 1/4/13, Mattias Gaertner wrote: > It sounds like a bug in the LCL Win32 interface. > I don't have win32 here to test. > There should be no Paint events during your code. Are there? How do I test this?

Set the OnPaint event of the synedit and add a debugln.

Show quoted text 9 lines
> What size has the SynEdit after setting Align to alClient and what is > the ClientRect of the tabsheet? TS is the TabSheet that is the parent of E TS has been created and it's property PageControl is set to the PageControl in question At this stage: TS.ClientRect = l=0,t=0,r=0,b=0
Well, that's not much space. Please add a
debugln(TS.AutoSizeDelayedReport);
Show quoted text 15 lines
Before setting E.Align := alClient: E.Bounds = l=0,t=0,r=200,b=150 After setting E.Align := alClient: E.Bounds = l=0,t=0,r=200,b=150 > > About workarounds: > Set the Parent as last property I remember doing that in the Delphi app and it made no difference, but I'll try it in Lazarus. > or enclose the code in > BeginAutoSizing; > EndAutoSizing; I'll give that a try too.

Mattias

Reply by email

Martin
to Mattias Gaertner
Mattias Gaertner wrote 12 lines
On Sat, 5 Jan 2013 00:47:38 +0100 Bart wrote: > On 1/4/13, Mattias Gaertner wrote: > >> It sounds like a bug in the LCL Win32 interface. >> I don't have win32 here to test. >> There should be no Paint events during your code. Are there? > How do I test this? Set the OnPaint event of the synedit and add a debugln.

Just for reference, I did some tests on Win Vista 32 bit

   s:=PageControl1.AddTabSheet;
   l := TSynEdit.Create(self);
   l.Align := alClient;
   l.Parent := s;
   PageControl1.ActivePage := s;

ActivePage will trigger painting, but it first aligns the SynEdit, so I get a correct display.

   s:=PageControl1.AddTabSheet;
   PageControl1.ActivePage := s;
   l := TSynEdit.Create(self);
   l.Align := alClient;
   l.Parent := s;

- again ActivePage causes painting, but synEdit is not existent yet-
- l.Parent := s; causes SynEdit to be correctly resized. Also paints the SynEdit's Scrollbars (does not call synEdit paint, only scrollbars / Scrollbars cover client area)

and therefore finally

   s:=PageControl1.AddTabSheet;
   PageControl1.ActivePage := s;  // paint tabsheet
   l := TSynEdit.Create(self);
   l.Parent := s;                               // paint scrollbars, not
yet aligned
   l.Align := alClient;                      // paint scrollbars
(again), this time aligned. Since synedit itself does not yet paint, the
previous painted scrollbars remain a visible image

Reply by email

Mattias Gaertner
to Martin
Show quoted text 24 lines
On 05/01/2013 01:06, Mattias Gaertner wrote: > On Sat, 5 Jan 2013 00:47:38 +0100 > Bart wrote: > >> On 1/4/13, Mattias Gaertner wrote: >> >>> It sounds like a bug in the LCL Win32 interface. >>> I don't have win32 here to test. >>> There should be no Paint events during your code. Are there? >> How do I test this? > Set the OnPaint event of the synedit and add a debugln. > > Just for reference, I did some tests on Win Vista 32 bit s:=PageControl1.AddTabSheet; l := TSynEdit.Create(self); l.Align := alClient; l.Parent := s; PageControl1.ActivePage := s; ActivePage will trigger painting, but it first aligns the SynEdit, so I get a correct display.

Does "trigger" means immediate paint or a normal queued message? There should be no immediate paints. Except those explicitly forced by the user code.

Show quoted text 21 lines
s:=PageControl1.AddTabSheet; PageControl1.ActivePage := s; l := TSynEdit.Create(self); l.Align := alClient; l.Parent := s; - again ActivePage causes painting, but synEdit is not existent yet- - l.Parent := s; causes SynEdit to be correctly resized. Also paints the SynEdit's Scrollbars (does not call synEdit paint, only scrollbars / Scrollbars cover client area) and therefore finally s:=PageControl1.AddTabSheet; PageControl1.ActivePage := s; // paint tabsheet l := TSynEdit.Create(self); l.Parent := s; // paint scrollbars, not yet aligned l.Align := alClient; // paint scrollbars (again), this time aligned. Since synedit itself does not yet paint, the previous painted scrollbars remain a visible image

It seems the Win32 intf triggers immediate paints. Maybe some win32 developer can explain why.

Mattias

Reply by email

Martin
to Mattias Gaertner
Mattias Gaertner wrote 13 lines
Just for reference, I did some tests on Win Vista 32 bit s:=PageControl1.AddTabSheet; l := TSynEdit.Create(self); l.Align := alClient; l.Parent := s; PageControl1.ActivePage := s; ActivePage will trigger painting, but it first aligns the SynEdit, so I get a correct display. Does "trigger" means immediate paint or a normal queued message? There should be no immediate paints. Except those explicitly forced by the user code.

immediately. Step in the debugger, and see it happen

Reply by email

luiz americo pereira camara
to Mattias Gaertner: On Sat, 05 Jan 2013 08:32:54 +0000 Does "trigger" means immediate paint or a normal…

2013/1/5 Mattias Gaertner :

Show quoted text 16 lines
On Sat, 05 Jan 2013 08:32:54 +0000 Martin wrote: > and therefore finally > > s:=PageControl1.AddTabSheet; > PageControl1.ActivePage := s; // paint tabsheet > l := TSynEdit.Create(self); > l.Parent := s; // paint scrollbars, not > yet aligned > l.Align := alClient; // paint scrollbars > (again), this time aligned. Since synedit itself does not yet paint, the > previous painted scrollbars remain a visible image It seems the Win32 intf triggers immediate paints. Maybe some win32 developer can explain why.

I could not reproduce here.

Using Windows 7 + Lazarus rev 39373 + fpc 2.6.1

MyCode:
  s:=PageControl1.AddTabSheet;
  PageControl1.ActivePage := s;
  l := TSynEdit.Create(self);
  DebugLn('BeforeParent');
  l.Parent := s;
  DebugLn('AfterParent');
  l.Align := alClient;
  DebugLn('AfterClient');

The output:
BeforeParent
AfterParent
AfterClient
SynEditPaint

I also put breakpoint and paint is not called

Luiz

Reply by email

luiz americo pereira camara
to luiz americo pereira camara

2013/1/5 luiz americo pereira camara :

Show quoted text 17 lines
2013/1/5 Mattias Gaertner : > On Sat, 05 Jan 2013 08:32:54 +0000 > Martin wrote: >> and therefore finally >> >> s:=PageControl1.AddTabSheet; >> PageControl1.ActivePage := s; // paint tabsheet >> l := TSynEdit.Create(self); >> l.Parent := s; // paint scrollbars, not >> yet aligned >> l.Align := alClient; // paint scrollbars >> (again), this time aligned. Since synedit itself does not yet paint, the >> previous painted scrollbars remain a visible image > > It seems the Win32 intf triggers immediate paints. > Maybe some win32 developer can explain why. >

I've found a suspect.

SetParent triggers the handle creation
TSynEdt.CreateWnd calls SizeOrFontChanged that calls UpdateScrollBars Here, since PaintLock 0 the scrollbar change is postponed

Martin/Bart, can you check if you pass the check for PaintLock in UpdateScrollBars?

Alternatively comment the call to SizeOrFontChanged in CreateWnd and see what happens

Luiz

Reply by email

luiz americo pereira camara
to luiz americo pereira camara

2013/1/5 luiz americo pereira camara :

Show quoted text 31 lines
2013/1/5 luiz americo pereira camara : > 2013/1/5 Mattias Gaertner : >> On Sat, 05 Jan 2013 08:32:54 +0000 >> Martin wrote: >>> and therefore finally >>> >>> s:=PageControl1.AddTabSheet; >>> PageControl1.ActivePage := s; // paint tabsheet >>> l := TSynEdit.Create(self); >>> l.Parent := s; // paint scrollbars, not >>> yet aligned >>> l.Align := alClient; // paint scrollbars >>> (again), this time aligned. Since synedit itself does not yet paint, the >>> previous painted scrollbars remain a visible image >> >> It seems the Win32 intf triggers immediate paints. >> Maybe some win32 developer can explain why. >> I've found a suspect. SetParent triggers the handle creation TSynEdt.CreateWnd calls SizeOrFontChanged that calls UpdateScrollBars Here, since PaintLock 0 the scrollbar change is postponed Martin/Bart, can you check if you pass the check for PaintLock in UpdateScrollBars? Alternatively comment the call to SizeOrFontChanged in CreateWnd and see what happens

More info:

SynEdit.CreateHandle -> DoDecPaintLock -> UpdateScrollBars -> ShowScrollBar (LCL) -> ShowScrollBar (Win32) -> Windows.RedrawWindow

Luiz

Reply by email

Martin
to luiz americo pereira camara
luiz americo pereira camara wrote 35 lines
2013/1/5 luiz americo pereira camara : > 2013/1/5 luiz americo pereira camara : >> 2013/1/5 Mattias Gaertner : >>> On Sat, 05 Jan 2013 08:32:54 +0000 >>> Martin wrote: >>>> and therefore finally >>>> >>>> s:=PageControl1.AddTabSheet; >>>> PageControl1.ActivePage := s; // paint tabsheet >>>> l := TSynEdit.Create(self); >>>> l.Parent := s; // paint scrollbars, not >>>> yet aligned >>>> l.Align := alClient; // paint scrollbars >>>> (again), this time aligned. Since synedit itself does not yet paint, the >>>> previous painted scrollbars remain a visible image >>> It seems the Win32 intf triggers immediate paints. >>> Maybe some win32 developer can explain why. >>> > I've found a suspect. > > SetParent triggers the handle creation > TSynEdt.CreateWnd calls SizeOrFontChanged that calls UpdateScrollBars > Here, since PaintLock 0 the scrollbar change is postponed > > Martin/Bart, can you check if you pass the check for PaintLock in > UpdateScrollBars? > > Alternatively comment the call to SizeOrFontChanged in CreateWnd and > see what happens > More info: SynEdit.CreateHandle -> DoDecPaintLock -> UpdateScrollBars -> ShowScrollBar (LCL) -> ShowScrollBar (Win32) -> Windows.RedrawWindow

I don't think it can be avoided.

I can detect the situation of course, but preventing that call, might lead to wrong display results.

Example
s := TSynEdit.Create
// Set ALign, size, text, all options.
s.Parent := form;

The last line makes the synedit visible. SynEdit must at some time tell the WidgetSet that scrollbars should be visible (assuming they should).

SynEdit can not trust that there will be a resize. The final size may be equal to the initial size. So it can not wait for the resize. (Assuming that after the first resize it would have the right/final size, and that therefore doing the "ShowScrollBar" in Resize would not cause as much as a disturbance. (It would still paint the scrollbars early, leading to a period of time showing only the scrollbars, but not yet the Edit).

Reply by email

Martin
to Mattias Gaertner
Mattias Gaertner wrote 11 lines
On Sat, 5 Jan 2013 07:36:01 -0300 luiz americo pereira camara wrote: > [...] > I've found a suspect. > > SetParent triggers the handle creation > TSynEdt.CreateWnd calls SizeOrFontChanged that calls UpdateScrollBars > Here, since PaintLock 0 the scrollbar change is postponed UpdateScrollBars should not trigger an immediate repaint.

Someone might check WDD?
Though it would be good to at least have an option.

Btw this is not the only one. At least TStatusBar does immediate repaints too.

And I guess in the case of Statusbar apps might relay on this (showing the state of a long running task. Not sure if any one out there abuses TScrollbar for such indication purposes.

Reply by email

luiz americo pereira camara
to Martin: I don't think it can be avoided. I can detect the situation of course, but preventing…

2013/1/5 Martin :

Show quoted text 24 lines
On 05/01/2013 10:54, luiz americo pereira camara wrote: > > 2013/1/5 luiz americo pereira camara : >> I've found a suspect. >> >> SetParent triggers the handle creation >> TSynEdt.CreateWnd calls SizeOrFontChanged that calls UpdateScrollBars >> Here, since PaintLock 0 the scrollbar change is postponed >> >> Martin/Bart, can you check if you pass the check for PaintLock in >> UpdateScrollBars? >> >> Alternatively comment the call to SizeOrFontChanged in CreateWnd and >> see what happens >> > More info: > > SynEdit.CreateHandle -> DoDecPaintLock -> UpdateScrollBars -> > ShowScrollBar (LCL) -> ShowScrollBar (Win32) -> Windows.RedrawWindow > I don't think it can be avoided. I can detect the situation of course, but preventing that call, might lead to wrong display results.

OK.

What OS are you using.

Here with windows 7 no Paint previous mail

Can you check (comment ShowScrollBar) if the paint you are seeing is really from ShowScrollBar?

After that we can look what to do

Luiz

Reply by email

Martin
to luiz americo pereira camara
luiz americo pereira camara wrote 10 lines
What OS are you using. Here with windows 7 no Paint previous mail Can you check (comment ShowScrollBar) if the paint you are seeing is really from ShowScrollBar? After that we can look what to do

If I single step, it is not painted by that line.

It happens here

       Perform(CM_SHOWINGCHANGED, 0, 0); // see TWinControl.CMShowingChanged

in B:\lazarus_latest_2\lcl\include\wincontrol.inc 4295

procedure TWinControl.UpdateShowing;
   procedure ChangeShowing(bShow: Boolean);
   begin
     if FShowing = bShow then Exit;
     FShowing := bShow;
     try
       {$IFDEF VerboseShowing}
       DebugLn(['ChangeShowing ',DbgSName(Self),' new FShowing=',FShowing]);
       {$ENDIF}
       Perform(CM_SHOWINGCHANGED, 0, 0); // see TWinControl.CMShowingChanged
     finally
       if FShowing(wcfHandleVisible in FWinControlFlags) then
       begin
         FShowing := wcfHandleVisible in FWinControlFlags;
         DebugLn(['TWinControl.UpdateShowing.ChangeShowing failed for
',DbgSName(Self),', Showing reset to ',FShowing]);
       end;
     end;
   end;

#0 CHANGESHOWING(0x2fcf1dc, true) at include\wincontrol.inc:4308 #1 UPDATESHOWING(0x219838) at include\wincontrol.inc:4356 #2 UPDATESHOWINGRECURSIVE(0x2fcf290, 0x219838, false) at include\wincontrol.inc:3466
#3 UPDATESHOWINGRECURSIVE(0x2fcf290, 0x2193b8, true) at include\wincontrol.inc:3463
#4 DOALLAUTOSIZE(0x2193b8) at include\wincontrol.inc:3520 #5 ENABLEAUTOSIZING(0x2193b8) at include\control.inc:5433 #6 ENABLEAUTOSIZING(0x219838) at include\control.inc:5431 #7 SETPARENT(0x219838, 0x2193b8) at include\control.inc:4076 #8 TFORM1__BUTTON1CLICK(0x21b858, <error reading variable>) at unit1.pas:38 #9 CLICK(0x21b858) at include\control.inc:2718
#10 STDCTRLS$_$TBUTTONCONTROL_$__$$_CLICK at :0
#11 STDCTRLS$_$TCUSTOMBUTTON_$__$$_CLICK at :0
#12 STDCTRLS$_$TBUTTON_$__$$_CLICK at :0
#13 STDCTRLS$_$TBUTTONCONTROL_$__$$_WMDEFAULTCLICKED$TMESSAGE at :0 #14 DISPATCH(0x21b858, 0) at ..\inc\objpas.inc:602 #15 WNDPROC(0x21b858, {MSG = 66567, WPARAM = 0, LPARAM = 0, RESULT = 0, WPARAMLO = 0, WPARAMHI = 0, LPARAMLO = 0, LPARAMHI = 0, RESULTLO = 0, RESULTHI = 0}) at include\control.inc:2111
#16 WNDPROC(0x21b858, {MSG = 66567, WPARAM = 0, LPARAM = 0, RESULT = 0, WPARAMLO = 0, WPARAMHI = 0, LPARAMLO = 0, LPARAMHI = 0, RESULTLO = 0, RESULTHI = 0}) at include\wincontrol.inc:5323
#17 DELIVERMESSAGE(0x21b858, 0) at lclmessageglue.pas:117 #18 WINDOWPROC(6359808, 273, 47192, 1116996) at win32\win32callback.inc:2476 #19 CUSTOMFORMWNDPROC(6359808, 273, 47192, 1116996) at win32\win32wsforms.pp:375
#20 USER32!GetWindowMinimizeRect at :0
#21 $FORMS$_Ld101 at :0
#22 ?? at :0
#23 ?? at :0
#24 ?? at :0
#25 USER32!GetWindowMinimizeRect at :0
#26 WIN32WSFORMS_$$_ADJUSTFORMBOUNDS$TCUSTOMFORM$RECT at :0 #27 USER32!CallNextHookEx at :0
#28 USER32!SendNotifyMessageA at :0
#29 DllInstall at :0
#30 DllInstall at :0
#31 DllInstall at :0
#32 USER32!GetWindowMinimizeRect at :0
#33 ?? at :0
#34 USER32!GetWindowMinimizeRect at :0
#35 DSA_Destroy at :0
#36 USER32!CancelShutdown at :0
#37 USER32!CancelShutdown at :0
#38 CALLDEFAULTWINDOWPROC(1116996, 514, 0, 65547) at win32\win32callback.inc:106
#39 WINDOWPROC(1116996, 514, 0, 65547) at win32\win32callback.inc:2284 #40 BUTTONWNDPROC(1116996, 514, 0, 65547) at win32\win32wsstdctrls.pp:1590 #41 USER32!GetWindowMinimizeRect at :0
#42 ?? at :0
#43 USER32!GetWindowMinimizeRect at :0
#44
WIN32WSSTDCTRLS$_$TWIN32WSBUTTONCONTROL_$__$$_GETPREFERREDSIZE$TWINCONTROL$LONGINT$LONGINT$BOOLEAN at :0
#45 USER32!GetMonitorInfoA at :0
#46 USER32!DisplayExitWindowsWarnings at :0
#47 APPPROCESSMESSAGES(0x233fb8) at win32\win32object.inc:367 #48 HANDLEMESSAGE(0x1dc178) at include\application.inc:1274 #49 RUNLOOP(0x1dc178) at include\application.inc:1407 #50 INTERFACEBASE$_$TWIDGETSET_$__$$_APPRUN$TAPPLICATIONMAINLOOP at :0 #51 RUN(0x1dc178) at include\application.inc:1395
#52 main at C:\Users\martin\AppData\Local\Temp\project1.lpr:19

Reply by email

luiz americo pereira camara
to Martin

2013/1/5 Martin :

Show quoted text 18 lines
On 05/01/2013 11:19, luiz americo pereira camara wrote: > > > What OS are you using. > > Here with windows 7 no Paint previous mail > > Can you check (comment ShowScrollBar) if the paint you are seeing is > really from ShowScrollBar? > > After that we can look what to do > If I single step, it is not painted by that line. It happens here Perform(CM_SHOWINGCHANGED, 0, 0); // see TWinControl.CMShowingChanged

This ends with TWin32WSWinControl.ShowHide that calls SetWindowPos which should not trigger a immediate wm_paint

What OS are you using?

Did you tried commenting the code inside TWin32WidgetSet.ShowScrollBar?

Luiz

Reply by email

Martin
to luiz americo pereira camara: 2013/1/5 Martin : This ends with TWin32WSWinControl.ShowHide that calls SetWindowPos…
luiz americo pereira camara wrote 10 lines
If I single step, it is not painted by that line. It happens here Perform(CM_SHOWINGCHANGED, 0, 0); // see TWinControl.CMShowingChanged This ends with TWin32WSWinControl.ShowHide that calls SetWindowPos which should not trigger a immediate wm_paint What OS are you using?

Win Vista 32 bit

Did you tried commenting the code inside TWin32WidgetSet.ShowScrollBar?

No, I single stepped, and checked, when the paint happened.

Reply by email

luiz americo pereira camara
to Martin: Win Vista 32 bit No, I single stepped, and checked, when the paint happened.

2013/1/5 Martin :

Show quoted text 23 lines
On 05/01/2013 11:43, luiz americo pereira camara wrote: > > If I single step, it is not painted by that line. > > It happens here > > Perform(CM_SHOWINGCHANGED, 0, 0); // see > TWinControl.CMShowingChanged > > This ends with TWin32WSWinControl.ShowHide that calls SetWindowPos > which should not trigger a immediate wm_paint > > What OS are you using? Win Vista 32 bit > > Did you tried commenting the code inside TWin32WidgetSet.ShowScrollBar? > No, I single stepped, and checked, when the paint happened.

Due to LCL/Win message nature, not always the backtrace correspond to the code that actually triggered the event.

At this time, i'm not sure what exactly is triggering the paint message you are seeing.

Sometimes the only way to know is by trial and error.

If commenting the code inside TWin32WidgetSet.ShowScrollBar avoids the paint, we will know that the problem is there, so we can try to fix, otherwise we will look elsewhere

BTW:

I just double checked and here no WM_PAINT message is triggered

Maybe is related to windows below windows 7

Luiz

Reply by email

Martin
to luiz americo pereira camara
luiz americo pereira camara wrote 38 lines
2013/1/5 Martin : > On 05/01/2013 11:43, luiz americo pereira camara wrote: >> If I single step, it is not painted by that line. >> >> It happens here >> >> Perform(CM_SHOWINGCHANGED, 0, 0); // see >> TWinControl.CMShowingChanged >> >> This ends with TWin32WSWinControl.ShowHide that calls SetWindowPos >> which should not trigger a immediate wm_paint >> >> What OS are you using? > > Win Vista 32 bit > >> Did you tried commenting the code inside TWin32WidgetSet.ShowScrollBar? >> > No, I single stepped, and checked, when the paint happened. > Due to LCL/Win message nature, not always the backtrace correspond to the code that actually triggered the event. At this time, i'm not sure what exactly is triggering the paint message you are seeing. Sometimes the only way to know is by trial and error. If commenting the code inside TWin32WidgetSet.ShowScrollBar avoids the paint, we will know that the problem is there, so we can try to fix, otherwise we will look elsewhere BTW: I just double checked and here no WM_PAINT message is triggered Maybe is related to windows below windows 7

I traced it further, using the assembler.
B:\lazarus_latest_2\lcl\interfaces\win32\win32wscontrols.pp 600

class procedure TWin32WSWinControl.ShowHide(const AWinControl: TWinControl);
const
   VisibilityToFlag: array[Boolean] of UINT = (SWP_HIDEWINDOW,
SWP_SHOWWINDOW);
begin
   Windows.SetWindowPos(AWinControl.Handle, 0, 0, 0, 0, 0,
     SWP_NOSIZE or SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE or
VisibilityToFlag[AWinControl.HandleObjectShouldBeVisible])
end;

00571381 e89a08e9ff call 0x401c20
<_$dll$user32$SetWindowPos>

Of course, that may call WindowProc, and do other stuff....

So I set a break at:

B:\lazarus_latest_2\lcl\interfaces\win32\win32callback.inc line 1055
first line in
function WindowProc(Window: HWnd; Msg: UInt; WParam: Windows.WParam;
     LParam: Windows.LParam): LResult; stdcall;

And during the above I received

Msg
70 WM_WINDOWPOSCHANGING (for SynEdit)
133 WM_NCPAINT (that does it in CallDefaultWindowProc) (also for SynEdit) 20
71

I single stepped the first (WM_WINDOWPOSCHANGING) but I dont know if anything happens when it too calls CallDefaultWindowProc. Didn't see any obvious calls to trigger paint.

Reply by email

Martin
to luiz americo pereira camara: 2013/1/5 Martin : OK. What OS are you using. Here with windows 7 no Paint previous mail…
luiz americo pereira camara wrote 33 lines
2013/1/5 Martin : > On 05/01/2013 10:54, luiz americo pereira camara wrote: >> 2013/1/5 luiz americo pereira camara : >>> I've found a suspect. >>> >>> SetParent triggers the handle creation >>> TSynEdt.CreateWnd calls SizeOrFontChanged that calls UpdateScrollBars >>> Here, since PaintLock 0 the scrollbar change is postponed >>> >>> Martin/Bart, can you check if you pass the check for PaintLock in >>> UpdateScrollBars? >>> >>> Alternatively comment the call to SizeOrFontChanged in CreateWnd and >>> see what happens >>> >> More info: >> >> SynEdit.CreateHandle -> DoDecPaintLock -> UpdateScrollBars -> >> ShowScrollBar (LCL) -> ShowScrollBar (Win32) -> Windows.RedrawWindow >> > I don't think it can be avoided. > > I can detect the situation of course, but preventing that call, might lead > to wrong display results. OK. What OS are you using. Here with windows 7 no Paint previous mail Can you check (comment ShowScrollBar) if the paint you are seeing is really from ShowScrollBar?

This would not make sense?

Nothing, except the scrollbars is painted (SynEdit does not paint). If I do not call ShowScrollbar, then there are no scrollbars that could be painted.

Reply by email

luiz americo pereira camara
to Martin

2013/1/5 Martin :

Show quoted text 8 lines
On 05/01/2013 11:19, luiz americo pereira camara wrote: > > Can you check (comment ShowScrollBar) if the paint you are seeing is > really from ShowScrollBar? This would not make sense? Nothing, except the scrollbars is painted (SynEdit does not paint).

I understood that SynEdit.Paint was called when setting Parent in your system, but seems this is not the case.

Although in the description of Bart he sees the whole SynEdit painted.

Luiz

Reply by email

luiz americo pereira camara
to Bart: I have a text editor (LazEdit on Lazarus CCR) which uses a TPageControl to act like a…

@Bart:

Did you tried to set Visible to false before setting Parent and Align and then setting visible to True, like below?

  s:=PageControl1.AddTabSheet;
  PageControl1.ActivePage := s;
  l := TSynEdit.Create(self);
  l.Visible := False
  l.Parent := s;
  l.Align := alClient;
  l.Visible := True

Luiz

2013/1/4 Bart :

Show quoted text 44 lines
Hi, I have a text editor (LazEdit on Lazarus CCR) which uses a TPageControl to act like a Tabbed Document Interface (much like Lazarus SE). Upon creating a new Tab it basically does: - Add a new TTabSheet to the PageControl - Create an instance of a TSynEdit - Set TSynEdit.Parent to the newly created TTabSheet - Set TSynEdit.Align := alClient This works as expected. However there is one visual anomaly: when you create a new Tab, for a brief moment you can see the TSynEdit, unaligned, with Width and Height set to it's defaults (like you would drop it on a Form in Lazarus). Long time ago, in Delphi, I solved this by doing: Try LockWindowUpdate(TheHandle); ... //Create the TSynEdit, align it etc. Finally LockWindowUpdate(0); This delayed any painting up to the point the TSynEdit was aligned. However, this is a Windows only fix. The relevant code is at: https://lazarus-ccr.svn.sourceforge.net/svnroot/lazarus-ccr/applications/lazedit/editorpagecontrol.pp (function TEditorPageControl.AddPage: TEditor; appr. at line 994) Does anyone have a suggestion how to fix this in a cross-platform manner? Bart -- _______________________________________________ Lazarus mailing list http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus

Reply by email

Martin
to luiz americo pereira camara: 2013/1/5 Martin : I understood that SynEdit.Paint was called when setting Parent in your…
luiz americo pereira camara wrote 12 lines
2013/1/5 Martin : > On 05/01/2013 11:19, luiz americo pereira camara wrote: >> Can you check (comment ShowScrollBar) if the paint you are seeing is >> really from ShowScrollBar? > This would not make sense? > > Nothing, except the scrollbars is painted (SynEdit does not paint). I understood that SynEdit.Paint was called when setting Parent in your system, but seems this is not the case. Although in the description of Bart he sees the whole SynEdit painted.

I am sure he was mistaken:

for a brief moment you can see the TSynEdit,

He would see the 2 scrollbars, and in the sort time he would not have paid attention to the absence of all else. Seing the 2 scrollbars *flicker* it is only natural to assume one saw the synedit flicker.

Reply by email

luiz americo pereira camara
to Martin

2013/1/5 Martin :

Show quoted text 27 lines
On 05/01/2013 12:57, luiz americo pereira camara wrote: > > 2013/1/5 Martin : >> >> On 05/01/2013 11:19, luiz americo pereira camara wrote: >>> >>> Can you check (comment ShowScrollBar) if the paint you are seeing is >>> really from ShowScrollBar? >> >> This would not make sense? >> >> Nothing, except the scrollbars is painted (SynEdit does not paint). > > I understood that SynEdit.Paint was called when setting Parent in your > system, but seems this is not the case. > > Although in the description of Bart he sees the whole SynEdit painted. > I am sure he was mistaken: > for a > brief moment you can see the TSynEdit, He would see the 2 scrollbars, and in the sort time he would not have paid attention to the absence of all else. Seing the 2 scrollbars *flicker* it is only natural to assume one saw the synedit flicker.

OK.

Now i see the issue. At runtime i could not notice the flicker and there's no WM_PAINT message involved, only stepping with the debugger is possible to see the control painted

Try

putting SWP_NOREDRAW in SetWindowPos

It fixed here, but not sure of collateral effects

Luiz

Reply by email

luiz americo pereira camara
to luiz americo pereira camara

2013/1/5 luiz americo pereira camara :

Show quoted text 40 lines
2013/1/5 Martin : > On 05/01/2013 12:57, luiz americo pereira camara wrote: >> >> 2013/1/5 Martin : >>> >>> On 05/01/2013 11:19, luiz americo pereira camara wrote: >>>> >>>> Can you check (comment ShowScrollBar) if the paint you are seeing is >>>> really from ShowScrollBar? >>> >>> This would not make sense? >>> >>> Nothing, except the scrollbars is painted (SynEdit does not paint). >> >> I understood that SynEdit.Paint was called when setting Parent in your >> system, but seems this is not the case. >> >> Although in the description of Bart he sees the whole SynEdit painted. >> > I am sure he was mistaken: > >> for a >> brief moment you can see the TSynEdit, > > > He would see the 2 scrollbars, and in the sort time he would not have paid > attention to the absence of all else. Seing the 2 scrollbars *flicker* it is > only natural to assume one saw the synedit flicker. OK. Now i see the issue. At runtime i could not notice the flicker and there's no WM_PAINT message involved, only stepping with the debugger is possible to see the control painted Try putting SWP_NOREDRAW in SetWindowPos It fixed here, but not sure of collateral effects

The collateral effect is that if a control is hidden, it will be still be show until is there a new paint cycle

I come with the below implementation that will have the following behavior. I could not find issues but needs more testing

- When a control is hidden, it's redraw immediately as is today
- When a control is show, its not redraw immediately. The window is invalidated and a paint message is queued

class procedure TWin32WSWinControl.ShowHide(const AWinControl: TWinControl);
const
  VisibilityToFlag: array[Boolean] of UINT = (SWP_HIDEWINDOW,
SWP_SHOWWINDOW or SWP_NOREDRAW);
var
  WinHandle: HWND;
  WinVisible: Boolean;
begin
  WinHandle := AWinControl.Handle;
  WinVisible := AWinControl.HandleObjectShouldBeVisible;
  Windows.SetWindowPos(WinHandle, 0, 0, 0, 0, 0,
    SWP_NOSIZE or SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE or
VisibilityToFlag[WinVisible]);
  //invalidate the window so it can be painted after show
  if WinVisible then
    Windows.RedrawWindow(WinHandle, nil, 0, RDW_INVALIDATE or RDW_FRAME);
end;

Luiz

Reply by email

luiz americo pereira camara
to luiz americo pereira camara

The last code also has a also an undesired effect: Some controls. eg Lazarus options form, are not displayed when show at first time

Luiz

2013/1/5 luiz americo pereira camara :

Show quoted text 72 lines
2013/1/5 luiz americo pereira camara : > 2013/1/5 Martin : >> On 05/01/2013 12:57, luiz americo pereira camara wrote: >>> >>> 2013/1/5 Martin : >>>> >>>> On 05/01/2013 11:19, luiz americo pereira camara wrote: >>>>> >>>>> Can you check (comment ShowScrollBar) if the paint you are seeing is >>>>> really from ShowScrollBar? >>>> >>>> This would not make sense? >>>> >>>> Nothing, except the scrollbars is painted (SynEdit does not paint). >>> >>> I understood that SynEdit.Paint was called when setting Parent in your >>> system, but seems this is not the case. >>> >>> Although in the description of Bart he sees the whole SynEdit painted. >>> >> I am sure he was mistaken: >> >>> for a >>> brief moment you can see the TSynEdit, >> >> >> He would see the 2 scrollbars, and in the sort time he would not have paid >> attention to the absence of all else. Seing the 2 scrollbars *flicker* it is >> only natural to assume one saw the synedit flicker. > > OK. > > Now i see the issue. At runtime i could not notice the flicker and > there's no WM_PAINT message involved, only stepping with the debugger > is possible to see the control painted > > Try > > putting SWP_NOREDRAW in SetWindowPos > > It fixed here, but not sure of collateral effects The collateral effect is that if a control is hidden, it will be still be show until is there a new paint cycle I come with the below implementation that will have the following behavior. I could not find issues but needs more testing - When a control is hidden, it's redraw immediately as is today - When a control is show, its not redraw immediately. The window is invalidated and a paint message is queued class procedure TWin32WSWinControl.ShowHide(const AWinControl: TWinControl); const VisibilityToFlag: array[Boolean] of UINT = (SWP_HIDEWINDOW, SWP_SHOWWINDOW or SWP_NOREDRAW); var WinHandle: HWND; WinVisible: Boolean; begin WinHandle := AWinControl.Handle; WinVisible := AWinControl.HandleObjectShouldBeVisible; Windows.SetWindowPos(WinHandle, 0, 0, 0, 0, 0, SWP_NOSIZE or SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE or VisibilityToFlag[WinVisible]); //invalidate the window so it can be painted after show if WinVisible then Windows.RedrawWindow(WinHandle, nil, 0, RDW_INVALIDATE or RDW_FRAME); end; Luiz

Reply by email