-
Создал компонент TStatusBar1, потомок от TStatusBar. Нужно каждую секунду обновлять данные на нём... Как нормально органзовать обновление? Думал следующим образом - но в результате вся программа виснет......
procedure TStatusBar1.WMPaint(var Message: TWMPaint);
var
a:TTime;
begin
self.Panels.Items[2].Text:='Текущее время: '+TimeToStr(Time);
inherited;
a:=Now+StrToTime('00:00:01');
while TimeToStr(a)<>TimeToStr(Now) do
Application.ProcessMessages;
SendMessage(self.Handle,WM_Paint,0,0);
end;
-
> [0] Delperec (30.08.08 15:29)
Не нужно тут в твоей задаче новых компонентов.... Достаточно имеющихся TStatusBar и TTimer.... В единственном обработчике таймера написать: StatusBar1.Panels.Items[2].Text:='Текущее время: '+TimeToStr(Time);
-
Согласен, так можно сделать - но нужно реализовать обновление значений непосредственно из компоненты TStatusBar1 - т.е. на форме должен быть только один компонент TStatusBar1 и никаких таймеров дополнительных - а обновление текста чтобы происходило..
-
> [2] Delperec (30.08.08 15:53) > т.е. на форме должен быть только один компонент TStatusBar1 > и никаких таймеров дополнительных - а обновление текста > чтобы происходило..
Просто подумать, а не копировать... unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, ExtCtrls, StdCtrls;
type
TMyStatusBar = class(TStatusBar)
private
FTimer: TTimer;
procedure UpdateTime(Sender: TObject);
procedure SetActive(const Value: Boolean);
function GetActive: Boolean;
protected
procedure Resize; override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property Active: Boolean read GetActive write SetActive;
end;
TForm1 = class(TForm)
CheckBox1: TCheckBox;
procedure FormCreate(Sender: TObject);
procedure CheckBox1Click(Sender: TObject);
private
StB: TMyStatusBar;
public
end;
var
Form1: TForm1;
implementation
constructor TMyStatusBar.Create(AOwner: TComponent);
begin
inherited;
FTimer:=TTimer.Create(self);
FTimer.OnTimer:=UpdateTime;
Panels.Add;
Panels.Add;
end;
destructor TMyStatusBar.Destroy;
begin
FTimer.Free;
inherited;
end;
function TMyStatusBar.GetActive: Boolean;
begin
Result:=FTimer.Enabled;
end;
procedure TMyStatusBar.Resize;
begin
Panels[0].Width:=Width-100;
inherited;
end;
procedure TMyStatusBar.SetActive(const Value: Boolean);
begin
FTimer.Enabled := Value;
end;
procedure TMyStatusBar.UpdateTime(Sender: TObject);
begin
Panels[1].Text:=TimeToStr(Time);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
StB:=TMyStatusBar.Create(Self);
StB.Parent:=Self;
StB.Active:=True;
end;
procedure TForm1.CheckBox1Click(Sender: TObject);
begin
StB.Active:=CheckBox1.Checked;
end;
end.
-
> на форме должен быть только один компонент TStatusBar1 и > никаких таймеров дополнительных
А никто от тебя и не требует, чтобы таймер был именно на форме.
Но без таймера в той или иной его ипостаси дело никак не обойдется.
-
Ну как правильно уже насоветовали. Поэтому разберем полеты?
> но нужно реализовать обновление
скорее не "нужно", а "хотел" :)
Теперь посмотри на свой код в [0]. Внутри WMPaint ты изменяешь текст, который надо отобразить, тем самым рекурсивно вызывая этот же самый WMPaint еще раз. Даже если далее текст не меняется и WMPaint не вызывается вновь проходим дальше до SendMessage. Здесь зависаем до обработки нового сообщения WM_Paint, т.е. опять рекурсия. В следующих витках опять зависаем на SendMessage, пока после секунды не изменится текст и опять рекурсивный вызов. В итоге ты должен получить Stack Overflow. Поставь галку использовать debug dcu, поставь бряк в своей проце и вызови окно Call Stack. Посмотри результаты в окне.
-
это так, для справки - в Д2007 есть конкретный глюк со статут баром. Выражается в том, что иногда на статус баре рисуется первый пункт главного меню. Кодгировцы, правда, не смогли воспроизвести глюк :) Решается так. procedure TForm_Main.WndProc(var Message: TMessage);
begin
with Message do
begin
case Msg of
WM_DRAWITEM:
begin
with PDrawItemStruct(Message.LParam)^ do
if (CtlType = ODT_MENU) and Assigned(Menu) and
(hwndItem = fStatusBarPro.Handle)
then
CtlType := ODT_STATIC;
end;
end;
end;
inherited WndProc(Message);
end; Есть еще замечательные компоненты StatusBarPro. Бесплатные. Могут многое.
-
Удалено модератором
|