zamtmn / metadarkstyle

74 stars 22 forks source link

StatusBar white flicker when loading and maximizing the form - fix proposal #20

Closed klaus101 closed 1 year ago

klaus101 commented 1 year ago

When a form initially is loaded, and, later, each time when it is maximized,, a StatusBar would appear painted in white for a short period of time. That's not severe, but not very nice either, and it is easy to fix:

uwin32widgetsetdark.pas:

function StatusBarWndProc(Window: HWND; Msg: UINT; wParam: Windows.WPARAM; lParam: Windows.LPARAM; uISubClass: UINT_PTR; dwRefData: DWORD_PTR): LRESULT; stdcall;
.........
  if Msg = WM_ERASEBKGND then
  begin
    StatusBar:= TStatusBar(Info^.WinControl);
    TWin32WSStatusBar.DoUpdate(StatusBar);
    DC:= BeginPaint(Window, @ps);
    LCanvas:= TCanvas.Create;
    try
      LCanvas.Handle:= DC;
      LCanvas.Brush.Color:= SysColor[COLOR_MENUBAR];
      LCanvas.FillRect(ps.rcPaint);
    finally
      LCanvas.Handle:= 0;
      LCanvas.Free;
    end;
    EndPaint(Window, @ps);
    Result:= 0;     // For me it doesn't make a difference if 0 or 1 are returned ..
    Exit;
  end;

  if Msg = WM_PAINT then

Could you pleaes verify the effect and apply the fix?

zamtmn commented 1 year ago

thanks!

klaus101 commented 1 year ago

Unfortunately there is a caveat: statusbar flicker on form resize

So, what would be needed is some means to skip (exit) the measure if the initial drawing had been already done and the window had not been maximized (so achieving: no initial flash, no flash at maximizing, and no flicker at resize). I don't know yet if/how this is possible with the help of already available variables.

klaus101 commented 1 year ago

Somehow sceptical i experimented a times and came up with a version (without FillRect) even much shorter than the previous one:

  if Msg = WM_ERASEBKGND then
  begin
    StatusBar:= TStatusBar(Info^.WinControl);
    TWin32WSStatusBar.DoUpdate(StatusBar);
    DC:= BeginPaint(Window, @ps);
    EndPaint(Window, @ps);
    Result:= 0;
    Exit;
  end;

zamtmn, when xou have the time to: could you see if that does achieve the following statusbar goals:

zamtmn commented 1 year ago

The code looks strange, it doesn't draw anything))

klaus101 commented 1 year ago

Yes! But i think the clue is in the BeginPaint/EndPaint … so requesting to replace unwanted (eg. white) parts of the background now quite early enough …. The FillRect itself will be done in the WM_PAINT then.

I found it out by wondering why one should have doubled FillRects (in WM_ERASEBKGND as well as in WM_PAINT) and if we couldn’t avoid that.

klaus101 commented 1 year ago

Ok, stepping again more inside … if one should be uncomfortable with the BeginUpdate/EndUpdate (I did read somewhere in the MS docs that it shouldn’t be called from outside the WM_PAINT). this simplification should do the job as well:

  if Msg = WM_ERASEBKGND then
  begin
    StatusBar:= TStatusBar(Info^.WinControl);
    TWin32WSStatusBar.DoUpdate(StatusBar);
    //DC:= BeginPaint(Window, @ps);
    //EndPaint(Window, @ps);
    Result:= 0;
    Exit;
  end;

So probably the clue is an enforce of drawing via the call of “DoUpdate”, which internally does some UpdateStatusBarPanel. I’d guess, at the end this pushes the drawing so that white areas will early enough disappear.

At least it appears to solve the three parts of the issue as mentioned above. What do you think, can you reproduce the effect on your side? Should i prepare a merge request?

zamtmn commented 1 year ago

Should i prepare a merge request?

I think yes

klaus101 commented 1 year ago

Did so ..

klaus101 commented 1 year ago

You change src/uwin32widgetsetdark.pas and add other copy uwin32widgetsetdark.pas to root. something wrong

Obviously. Positioned on my repo, branch "addition", metadarkstyle/src, i uploaded uwin32widgetsetdark.pas and noticed afterwards the change was not herein. I assumed. maybe i needed a to do a commit from my "addition" to my "main", but afterwards the changef was not herein. Then i repeated the first step, but not with dragdrop, but by direct load / fileOpendialog, and the change could be seen. Very strange and somehow unfamiliar for me. Sorry for this inconvenience!

EDIT: Oh yes, i see the file in the root of "addition". - Deleted it.

zamtmn commented 1 year ago

thanks!