- Application processmessages delphi android
- Calling Application.ProcessMessages in a Delphi program
- Application processmessages delphi android
- Delphi. Messages. Первые наивные пробы
- Как отправить сообщение из приложения?
- Где найти полный список сообщений?
- Слушает ли Delphi программа сообщения?
- Как отправить “кастомное” сообщение?
- Ещё вариант отправки кастомного сообщения
Application processmessages delphi android
Метод Application.ProcessMessages необходимо применять в динамичных приложениях, требующих немедленного отображения выполненных в программе действий. Для повышения быстродействия программы сообщения (Messages!), которые объект Application посылает объектам программы, этими объектами выполняются не сразу после получения, а по мере накопления некоторой очереди.
Для иллюстрации работы метода Application.ProcessMessages рассмотрим процедуру, троекратным «мельканием» текста в строке ввода обращающего внимание пользователя на то, что данные не введены:
procedure TForm1.Button1Click(Sender: TObject);
var i: Integer;
begin
if Edit1.Text=» then
begin
for i:=1 to 3 do
begin
Edit1.Text:=’Введите данные’;
//Application.ProcessMessages;
sleep(300);
Edit1.Text:=»;
//Application.ProcessMessages;
sleep(300);
end;
Edit1.SetFocus;
end;
end;
Попробуйте выполнить приложение с закомментированными операторами Application.ProcessMessages, и вы никогда не увидите желаемого текста. Программа идёт дальше, невзирая на то, что необходимые действия визуально не отражены на Форме. Теперь раскомментируйте — и желаемый эффект достигнут. Таким образом, метод Application.ProcessMessages заставляет программу немедленно отразить результат действия уже выполненных ею операторов.
Аналогично, программа, выполняющая длительные вычисления, может выглядеть зависшей, так как даже сообщения на перемещение её окна или нажатия на кнопки не будут обработаны, пока вычисления не будут закончены. Поэтому нужно либо выполнять вычисления в отдельном потоке, либо периодически выполнять Application.ProcessMessages. Однако, в этом случае нужно учитывать, что выполнение этого метода несколько тормозит выполнение программы, и его вызов не должен быть слишком частым.
Другой пример, связанный с работой с графикой в Delphi. Динамика построения графиков функций, когда график рисуется постепенно, по мере вычисления очередной точки, выглядит в программе очень эффектно. Чтобы добиться такого эффекта, также необходимо применять метод Application.ProcessMessages. Вычисляя положение очередной точки, нужно после её выведения на холст:
Canvas.LineTo(X[n], Y[n]);
sleep(200);
Без применения последнего оператора мы получим сразу готовый график функции, и даже применение оператора задержки перед выводом очередной точки не поможет.
Источник
Calling Application.ProcessMessages in a Delphi program
Using Application.ProcessMessages is being frowned upon by many because often it means that your program design is flawed. These people usually suggest you should use multi-threading instead, which then opens another can of worms.
First of all, let me make clear, that I am talking about Windows programs written in Delphi using the Visual Component Library (VCL). This is not about Android or IOS development and also not about the Firemonkey (FMX) framework and most certainly not about any dotNET language.
With that out of the way, let’s discuss what Application.ProcessMessages does and why it is being used:
Application is the global object declared by the VCL in the Forms unit which provides methods that are independent of forms. One of them is ProcessMessages. What it does is looking into the Windows message queue and processing any messages it may find there. Since Windows GUIs are message driven, this is important for a program to react to user input as well as other events, e.g. redrawing controls that have changed.
Normally this processing of messages is done automatically in the program’s main message loop that is executed all the time when it is idle. But if your program does some long running work after e.g. the user pressed a button, it might take a while until it gets back to executing the message loop and to the user it will seem to have crashed or hung.
To alleviate this, for many years Delphi programmers have added the occasional call to Application.ProcessMessages in their code. This usually looks like this:
Where DoSomeWork does part of the total work and returns. And then the program calls Application.ProcessMessages to update the user interface.
Why is this bad?
- Processing Windows messages may have some undesired side effects. E.g.:
- Your form might have multiple buttons which do different things. ButtonA might start a long running calculation A while ButtonB might start a different calculation B. And it’s most likely that you don’t want to start calculation B while calculation A is still running.
- Even if your form only has one button that starts an action you still don’t want that action to be started again while the first run hasn’t finished. [*]
- Your calculation might access the user interface to retrieve some configuration. If you do that frequently and in between call Application.ProcessMessages, these settings may have changed, so you might start with one set of configurations and continue with a different one. The result will most likely not be what you expect.
- The user might close the form while the calculation is still running. That could result in resources that the calculation needs being freed, which usually causes errors like Access Violations.
- Each call to Application.ProcessMessages takes time which might slow down your calculations significantly.
So, should we not call Application.ProcessMessages? And how do we keep the GUI active?
As mentioned above, the answer you usually get is to use multi-threading. That is: Move the work into a secondary (or even many secondary) worker thread and let the main thread take care of the user interface. If done properly this works very well. But can you do it properly? Well, I for one have written my share of multi-threaded programs and I can tell you: It’s difficult to do it properly. And most of the time it isn’t necessary.
One of the main stumble blocks is debugging. The Delphi debugger is not particularly suited for debugging multi-threaded programs. It shows you a list of threads and the code which is being executed by the currently active thread (on a multi core system, there is more than one currently active thread, I have no idea how the debugger selects the one to display). You can switch to a different thread and look at the code it is executing. Even worse: The debugger will switch between the threads automatically for no apparent reason, so you press F8 to step over one command and find yourself in the code of a different thread all of a sudden. Other than the debugger, there are of course other debugging methods, e.g. writing to a log or showing message boxes. The latter can only be done safely in the main thread because the VCL is not thread safe. Writing a log will pose the challenge of accessing that log in a thread safe manner.
All that does not mean, you should not use multi-threading if you need it. It just means that you should consider the implications this will have on the complexity of your code and debugging it.
This blog post is not about multi-threading in particular but about Application.ProcessMessages, so I will not go down that route any further.
So, what can we do with a single threaded program to alleviate the above mentioned pitfalls of Application.ProcessMessages?
- First of all: Once you start processing some data, stop the user from interfering.
- Disable the controls in the user interface, including the button that just started the processing. This also gives the user feedback that the program is busy right now. He cannot start anything else and also not change the settings being used by the calculations. Don’t forget to enabled the controls afterwards (e.g. use Try…Finally to ensure them to be re-enabled.)
- Prevent the current form from being closed. This can be done with an OnCloseQuery event.
- Call Application.ProcessMessages as often as necessary, but not too often.
In addition you should provide a visual feedback of the progress and have an Abort button that allows the user to – well – abort the calculations.
Basically you do something like this:
That’s the basic principle which many of our internal tools use. It avoids the complexity of multi-threading while still keeping the UI responsive and allow the user to abort processing. I’m not claiming that it is perfect but it works, is simple to understand and also simple to debug.
Drawbacks are the following:
- If the processing is more complex and should be moved to a procedure in a different unit, it’s easy to forget the Application.ProcessMessages calls. Also if you have these calls in your code, you should not call it in a secondary thread. Bad things will happen, if you do.
- If you call Application.ProcessMessaging in multiple places, it might not be as easy as in the example to keep track of how long ago the last call was. One possible solution is to have a global TTimedProcessMessages object that does the time keeping for you.
- Checking the Abort button is also a problem once your code is no longer in the form’s object. Again, a TTimedProcessMessages object can solve that.
- You cannot use that code in Firemonkey programs and, most unfortunately, you cannot use it for cross platform programs (which would require Firemonkey anyway.)
- Nowadays most computers have multiple cores. This is a single threaded program, so it will only use the processing power of one core. Depending on the amount of processing that needs to be done and whether it can be split into independent work packages, a multi-threading solution would be much more efficient.
Oh, you might ask, where this TTimedProcessMessages object I am talking about can be found. Here you go:
You either create a global variable (no, of course that’s bad) a singleton of this class
or create an instance and pass it around to all methods that need it. These methods then use it like this:
(Note: All the code above has just been typed in as I went along, so it might contain bugs. I haven’t even tried to compile it.)
There you go. Good thing I have disabled comments on this blog anyway, so there will be no way for people to call me unprofessional because I recommend using Application.ProcessMessages. 😉
But if you really want to call me names, here is was the corresponding Google✝ post.
Источник
Application processmessages delphi android
Метод Application.ProcessMessages необходимо применять в динамичных приложениях, требующих немедленного отображения выполненных в программе действий. Для повышения быстродействия программы сообщения (Messages!), которые объект Application посылает объектам программы, этими объектами выполняются не сразу после получения, а по мере накопления некоторой очереди.
Для иллюстрации работы метода Application.ProcessMessages рассмотрим процедуру, троекратным «мельканием» текста в строке ввода обращающего внимание пользователя на то, что данные не введены:
procedure TForm1.Button1Click(Sender: TObject);
var i: Integer;
begin
if Edit1.Text=» then
begin
for i:=1 to 3 do
begin
Edit1.Text:=’Введите данные’;
//Application.ProcessMessages;
sleep(300);
Edit1.Text:=»;
//Application.ProcessMessages;
sleep(300);
end;
Edit1.SetFocus;
end;
end;
Попробуйте выполнить приложение с закомментированными операторами Application.ProcessMessages, и вы никогда не увидите желаемого текста. Программа идёт дальше, невзирая на то, что необходимые действия визуально не отражены на Форме. Теперь раскомментируйте — и желаемый эффект достигнут. Таким образом, метод Application.ProcessMessages заставляет программу немедленно отразить результат действия уже выполненных ею операторов.
Аналогично, программа, выполняющая длительные вычисления, может выглядеть зависшей, так как даже сообщения на перемещение её окна или нажатия на кнопки не будут обработаны, пока вычисления не будут закончены. Поэтому нужно либо выполнять вычисления в отдельном потоке, либо периодически выполнять Application.ProcessMessages. Однако, в этом случае нужно учитывать, что выполнение этого метода несколько тормозит выполнение программы, и его вызов не должен быть слишком частым.
Другой пример, связанный с работой с графикой в Delphi. Динамика построения графиков функций, когда график рисуется постепенно, по мере вычисления очередной точки, выглядит в программе очень эффектно. Чтобы добиться такого эффекта, также необходимо применять метод Application.ProcessMessages. Вычисляя положение очередной точки, нужно после её выведения на холст:
Canvas.LineTo(X[n], Y[n]);
sleep(200);
Без применения последнего оператора мы получим сразу готовый график функции, и даже применение оператора задержки перед выводом очередной точки не поможет.
Источник
Delphi. Messages. Первые наивные пробы
Решил разобраться с устройством Windows, в частности с сообщениями. Народ в сети массово отправляет к Рихтеру и Русиновичу. Книги приобрел – начал читать. Что хочу сказать – первое впечатление – информация ценнейшая для разработки под Windows. Ещё и на русском языке. Но поскольку практика это лучший инструмент познания, решил сделать несколько простых примеров до основательного чтения этих книг. После чтения сделаю ещё несколько примеров, чтобы сравнить насколько лучше понимаю предмет.
Как отправить сообщение из приложения?
Рассмотрим на примере закрытия окна. Сообщение будет WM_CLOSE. Список всех сообщений для Windows можно посмотреть здесь.
Итак, из того, что я понял на данный момент, чтобы отправить сообщения определенному окну, часто используются функции
Оба сообщения закроют окно c Handle равным Form2.Handle Первый параметр – Handle окна, второй параметр – собственно сообщения, а третий и четвертый – дополнительные параметры, которые задействуются или нет от случая к случаю, например координаты курсора. В приведенном примере оба параметра занулены. Если поместить эти инструкции, скажем в обработчик кнопки окна, то после нажатия в ядро Windows будет направлено сообщение о закрытии окна, а Windows, соответственно просто закроет окно.
Где найти полный список сообщений?
В принципе таких ресурсов много. Вот один из них.
Слушает ли Delphi программа сообщения?
Определенно да. Вот простой пример. Поймаем сообщение нажатия правой кнопкой мыши на любом из компонентов приложения.
Если нажмем правой клавишей мыши на любом компоненте приложения, то увидим
Здесь мы отлавливали сообщение о нажатии правой кнопки мыши. Таким же образом можно отлавливать любые другие сообщения из списка.
Как отправить “кастомное” сообщение?
Под кастомным сообщением я подразумеваю сообщение не из списка, а какое-то свое сообщение, например WM_USER+2001. Вот как можно отправить такое кастомное сообщение. Пример основан на официальной документации
Объявляем глобальную константу
Далее создаем и присваиваем обработчик
И последний штрих – отправляем сообщения
Ещё вариант отправки кастомного сообщения
Определяем свою константу (она должна быть прописана выше, чем метод, который её использует, то есть, например, до описания типов)
Далее определяем обработчик сообщения в методах класса формы, например, таким образом
Далее прописываем его
Далее отправляем PostMessage, скажем, по нажатию кнопки
Источник