-3

It may sound silly, but I encountered a few situations, when I would like the application not to show what is happening, until an another specific action happens (stringGrids are filled with data, UI is prepared...). Is there a way to prevent messages from being sent from application to OS?

So, is there some oposit to

application.processmessages

? Something like:

application.stopProcessingMessages;

fill stringGrids, prepare the UI...

application.processMessagesAgain;

?

Of course, I could run the actions in a separate thread, but there are situations where I either don't want to, or cannot do it in a separate thread.

j.kaspar
  • 751
  • 1
  • 11
  • 29
  • What is *grid*? There's no *Application.StopProcessingMessages*, but depending on what specifically you're doing there are ways to stop some components from updating the screen. However, as you've posted no real relevant information, it's difficult to offer suggestions. What you've posted for code is pretty much *I have code that does blah, blah, blah. Without any details, how do I change the behavior of that code?* – Ken White Mar 24 '16 at 17:07
  • Many different ways to skin this one. Starting with using a control over than a grid. A virtual mode list view for instance. Keeping all of your data in a UI control is poor design. You are just reaping the consequences of that. Suppressing painting would be one way to patch it up. Not too hard to achieve. You should never call `ProcessMessages`. You probably would benefit from a better understanding of how Windows messages work. – David Heffernan Mar 24 '16 at 17:08
  • I don't want to stick exactly to the grid example. But in this case I am talking about TStringGrid – j.kaspar Mar 24 '16 at 17:08
  • 1
    You might use `WM_SETREDRAW` to suspend redrawing. Frankly though, your design sounds badly wrong, and I think you have a problem in your understanding of how the system works. Spending large amounts of time working from the main thread is a big problem. If it takes time to gather the data, do that in a background thread. When you have it all, update the UI. – David Heffernan Mar 24 '16 at 17:17
  • @DavidHeffernan I don't want to keep all of the data in an UI control. In this example I have data in datasets, arrays etc. And some of them need to be picked up and displayed in grid. As I am writing this, I realized, that I could simply create some new array, fill it in the for loop and then fill the grid with data in this separated array. So it shows me, that different situations will have different solutions. I just wanted to know if there is a general way to suppress the painting. Masking the grid is also a good idea. – j.kaspar Mar 24 '16 at 17:17
  • 1
    You won't need to suppress any painting if you gather the new data in the background, and then update once you have it all. That's just a better solution. – David Heffernan Mar 24 '16 at 17:22
  • Listen to what KenW and DavidH say. Atm, you are thinking about this problem in completely the wrong way. Btw are you filling your grid from a dataset, and if so which kind? Reason I ask is that some know how to retrieve data in the background without you having to code a secondary thread to do it. – MartynA Mar 24 '16 at 18:22

2 Answers2

2

Check TDataSet.DisableControls for data aware controls, and BeginUpdate / EndUpdate for some VCL / RTL classes (including TStrings), and - specific for the mentioned TStringGrid - see Delphi TStringGrid Flicker

Community
  • 1
  • 1
mjn
  • 36,362
  • 28
  • 176
  • 378
  • WM_SETREDRAW - that's precisely what I needed. The example I provided is not good. If I update the grid in a for loop, it "flickers" even if I add a row in each pass. Thank you... – j.kaspar Mar 24 '16 at 18:21
  • WM_SETREDRAW? That was mentioned much earlier. It's probably not the right solution to the problem you described though. – David Heffernan Mar 24 '16 at 19:57
  • @DavidHeffernan It was mentioned, yes but I had no idea what it does, until I read the topic linked here. I also voted your comment, where you mentioned it, up. It is the right solution, everybody just stick to the, not very good, example with the for loop and grid. The question was pretty much clear... – j.kaspar Mar 24 '16 at 20:32
  • It's probably not the right solution. If you want to learn about it you can read the docs. Do you know how to find them? – David Heffernan Mar 24 '16 at 20:38
0

It turned out, that although I thought, that using the WM_SETREDRAW message is the right solution, it has a few disadvantages. The biggest one is, that if used, user can click through the form. So the final solution is simply an empty TPanel placed over the whole form like this

  panel1.Left:= 0;
  panel1.Top:= 0;
  panel1.Width:= frmMain.Width;
  panel1.Height:= frmMain.Height;

After the form is prepared, the panel is shrunk, made invisible etc. It reliably hides every flickering and other things, that doesn't look good, and I want to hide them from the user.

j.kaspar
  • 751
  • 1
  • 11
  • 29