DelphiFeeds.com

  • Dashboard
  • Popular Stories
  • Trending Stories
  • Feeds
  • Login
Trending now

Delphi JOSE JWT Is A Powerful JSON Web Token Library For Delphi

Learn How Not To Use Square Brackets in Your Program In This Learn Delphi Video

Easily Communicate With The TI Gas Sensor Platform Using Delphi And C++ Builder

Powerful Video Game Collection Curation Software Is Built In Delphi

Rise of Legions Multiplayer RPG Windows Game Built In Delphi

Cross-Platform 4D Solar System Simulation Is Built In Delphi

Flexible Cross-Platform Open-Source Component Suite For Delphi FireMonkey

Quickly And Easily Hook Delphi And Windows API Functions With The DDetours Library

Discover How to Use C++ Alias Templates For Windows Development In C++Builder

QuickLib Is A Powerful Third Party Library For Delphi Which Can Boost Productivity

Discover How to Clone The Classic Minesweeper Game in Delphi in This Learn Delphi Video

TMS VCL UI Pack v10.5 released

GitHub – pierrejean-coudert/delphi-libraries-list: List of Delphi Libraries and Frameworks

Melbourne Meeting – January 2021

Comprehensive Music Theory and Ear Training App Built In Delphi

The Unfortunate Effect of WM_SETREDRAW

1
Francesca Gaillard Francesca Gaillard 10 years ago in Bug, Delphi, LockWindowUpdate, User Interface, windows 0

… or why simply replacing LockWindowUpdate by WM_SETREDRAW is not that straightforward.

As you know, when you want to avoid flickering or multiple partial redraws of your Forms, during a flurry of updates for instance, even though it is very tempting, you must not use LockWindowUpdate. The Windows documentation has been updated from the days when it practically enticed people into using this API call for this wrong purpose and Raymond Chen has explained in detail why:
What does LockWindowUpdate do?
With what operations is LockWindowUpdate meant to be used?
With what operations is LockWindowUpdate not meant to be used?
Final remarks on LockWindowUpdate

Now, just replacing LockWindowUpdate(MyForm.Handle) by SendMessage(MyForm.Handle, WM_SETREDRAW, 0, 0) on the whole Form is not the solution either. Even though I’ve seen it recommended here or there.
Oh, it does a good job at preventing any painting on the Form, and if drawing is re-enabled quickly enough, there is little chance to cause the problem we’ll see below.

Simulate a long calculation that coincides with some visible UI changes.

Create a new VCL Forms application and put 2 Buttons on the Main Form.
In the 1st ButtonClick handler, paste the following code:

procedure TForm1.Button1Click(Sender: TObject);
begin
  Button1.Width := Button1.Width*2;
  Repaint;
  sleep(2000);
  Button1.Width := Button1.Width div 2;
  Repaint;
end;

If you click the button, its size changes, the application stays unresponsive for 2 s (lengthy processing without a background thread) then everything is back to normal. If you click on the Form while it is “frozen” nothing happens unless you have an onClick event, or try to move the Form for instance, and in that case the event action is executed after the Form is unfrozen, when message processing can resume and handle the backlog.

Now, if you don’t want the UI changes to be visible.

You can wrap all that code with WM_SETREDRAW (like you’d be tempted to do with LockWindoUpdate):

procedure TForm1.Button1Click(Sender: TObject);
begin
  SendMessage(Handle, WM_SETREDRAW, Ord(False), 0);
  try
    Button1.Width := Button1.Width*2;
    Repaint;
    sleep(2000);
    Button1.Width := Button1.Width div 2;
    Repaint;
  finally
    SendMessage(Handle, WM_SETREDRAW, Ord(True), 0);
  end;
end;

Try it again. Seems good, the button size does not appear to change. But, wait!
Try to click anywhere on the form while it is “busy”.
Oops! Clicked through it, like it did not even exist!
It’s even more obvious when the form is above the Delphi editor: as soon as you click the button, the cursor changes from the regular Arrow pointer to the text IBeam.

Try with Notepad.

In case you’d believe it is some defect special to the VCL Forms, you can try and paste the following code in the 2nd Button OnClick handler. It opens Notepad for a new text document, prevents redrawing on it for 3s then re-enables it.
Note: If the window title is different (non English Windows…), you may have to adapt the 2nd FindWindow parameter or use an empty string.

procedure TForm1.Button2Click(Sender: TObject);
var
  h: THandle;
begin
  ShellExecute(Handle, nil, 'Notepad.exe', '','', SW_SHOWNORMAL);
  sleep(100);
  // you may have to change the default title in non English Win7 or put ''
  h := FindWindow('Notepad', 'Untitled - Notepad');
  if IsWindow(h) then begin
    SendMessage(h, WM_SETREDRAW, Ord(False), 0);
    try
      sleep(3000);
    finally
      SendMessage(h, WM_SETREDRAW, Ord(True), 0);
    end;
  end;
end;

Try to click anywhere on the Notepad window when it is “locked”, you’ll get right through it just as well!

What if you need to prevent drawing on the Form while doing some processing?

As it is very rare that the UI controls subject to unwanted drawing are directly placed on the Form, the easiest solution is to prevent drawing for the utmost parent, very often a Panel or a Tab/PageControl (the ClientWindow would not work).
And if you don’t have a master parent, you can always insert a Panel with alClient as a main container between the Form and the rest of the controls.
Useful tip: Contrary to DisableControls/EnableControls for the DataSets, WM_SETREDRAW does not care about nested calls, it does not matter how many times you call WM_SETREDRAW False (although avoiding sending unnecessary messages flying around is always desirable). You just have to guarantee that you’ll call WM_SETREDRAW True when you are done with your updates.

Why do we have this strange behavior?

Practically, WM_SETREDRAW default behavior is for the Window receiving it to disappear, but without causing the screen to be refreshed to show what’s behind. We are left with a “ghost” painting of the current Window, and is truly very static indeed.
It has been explained, sort of, by Raymond Chen in a very recent post:
There’s a default implementation for WM_SETREDRAW, but you might be able to do better

Trending Stories

  • Delphi JOSE JWT Is A Powerful JSON Web Token Library...

  • Learn How Not To Use Square Brackets in Your Program...

  • Easily Communicate With The TI Gas Sensor Platform Using Delphi...

  • Powerful Video Game Collection Curation Software Is Built In Delphi

  • Rise of Legions Multiplayer RPG Windows Game Built In Delphi

Embarcadero GetIt

  • ProDelphi 64-bit & 32-bit. Lite version

    Source code profiler for measuring runtime of 64 and 32 bit applications developed with Delphi. […]

  • TChromeTabs

    TChrome tabs is a comprehensive implementation of Google Chrome's tab system - features include - […]

  • ICS for FMX and VCL

    ICS is a Delphi library composed of many internet components supporting all major protocols and […]

  • ICS for VCL

    ICS is a Delphi library composed of many internet components supporting all major protocols and […]

  • SynEdit for VCL

    SynEdit for Delphi and CBuilder. Syntax highlighting edit control, not based on the Windows common […]

  • Learn Delphi
  • Learn C++
  • Embarcadero Blogs
  • BeginEnd.net
  • Python GUI
  • Firebird News
  • Torry’s Delphi Pages
Copyright DelphiFeeds.com 2021. All Rights Reserved
Embarcadero
Login Register

Login

Lost Password

Register

Lost Password