Советы пользователям Delphi и C++Builder


         

Отключение хранителя экрана


Нередко разработчики приложений, выполняющих какие-либо длительные действия (например, обработку большого количества данных или пересылку данных на удаленный компьютер с помощью низкоскоростной линии связи), сталкиваются с проблемами, создаваемыми так называемыми хранителями экрана (screen savers). Хранители экрана представляют собой, по существу, такие же Windows-приложения, нередко потребляющие немалое количество самых разнообразных ресурсов, за исключением собственно люминофора, которым покрыта внутренняя поверхность экрана монитора. Поэтому при запущенном хранителе экрана в общем случае производительность любого другого приложения, выполняющего какие-либо длительные действия, может существенно снизиться.

Чтобы понять, как предотвратить запуск хранителя экрана, следует вспомнить, что операционные системы с графическим пользовательским интерфейсом (в том числе Windows) основаны на посылке и обработке сообщений, а также на обработке событий. Windows постоянно обрабатывает разнообразные события, в том числе события, связанные с перемещением мыши или нажатием клавиш. Хранитель экрана запускается операционной системой, если по истечении заранее заданного (то есть установленного пользователем операционной системы) промежутка времени не происходило двух указанных выше типов событий. Для этого операционная система посылает активному приложению сообщение WM_SYSCOMMAND с параметром WPARAM, равным SC_SCREENSAVE. Именно это сообщение и следует перехватить в нашем приложении.

Перехват сообщения можно осуществить, создав обработчик события OnMessage объекта TApplication, наступающего при получении приложением очередного сообщения Windows. Соответствующая функция имеет два параметра: имя сообщения и параметр handled, указывающий, обрабатывается ли такое сообщение данным приложением. Если он установлен равным false, сообщение обрабатывается операционной системой. В противном случае оно обрабатывается приложением.

Создадим простейший пример, иллюстрирующий перехват такого сообщения. Для этого поместим на форму радиогруппу из двух элементов:



Рис. 2. Форма приложения для определения цветового разрешения экрана.
Теперь создадим функцию-член класса TForm1 (в C++Builder 4 для этого есть специальный эксперт, встроенный в Code Explorer, однако не возбраняется создать определение функции вручную):

Рис. 3. Создание новой функции-члена класса TForm1 с помощью C++Builder 4.
Создадим текст этой функции, а также обработчик события, связанный с созданием формы приложения и указывающий, какая функция должна вызываться при получении сообщения данным приложением:
void __fastcall TForm1::ProcessMess(TMsg & msg, bool &handled) { //TODO: Add your source code here if (msg.message==WM_SYSCOMMAND && msg.wParam==SC_SCREENSAVE && RadioGroup1->ItemIndex==1) handled=true; else handled=false;
} //---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender) { Application->OnMessage = ProcessMess;
}
Если функция создана вручную, следует не забыть создать ее определение в h-файле:


class TForm1 : public TForm { __published: // IDE-managed Components TRadioGroup *RadioGroup1; void __fastcall FormCreate(TObject *Sender); private: void __fastcall ProcessMess(TMsg & msg, bool &handled);
public: // User declarations __fastcall TForm1(TComponent* Owner); };
Аналогичный код для Delphi имеет вид:
unit Unit1;
interface
uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls;
type TForm1 = class(TForm) RadioGroup1: TRadioGroup; procedure FormCreate(Sender: TObject); private procedure ProcessMess(var msg:TMsg; var handled:boolean) ; { Private declarations } public { Public declarations } end;
var Form1: TForm1;
implementation
{$R *.DFM}
{ TForm1 } procedure TForm1.ProcessMess(var msg: TMsg; var handled: boolean); begin if (msg.message=WM_SYSCOMMAND) and (msg.wParam=SC_SCREENSAVE) and (RadioGroup1.ItemIndex=1) then handled:=true else handled:=false;
end;
procedure TForm1.FormCreate(Sender: TObject); begin Application.OnMessage:=ProcessMess; end;end.
Если созданное таким образом приложение активно, хранитель экрана будет запускаться (или не запускаться) в зависимости от того, какая опция выбрана в радиогруппе.

Содержание раздела