问题14:如何设计一个循环,使其不停地检查当前系统时间距离零时的分钟数,当其值大于一个指定的值时跳出该循环。我用了各种循环语句都不能解决,不是未进行循环就是进入

T

thlt

Unregistered / Unconfirmed
GUEST, unregistred user!
问题14:如何设计一个循环,使其不停地检查当前系统时间距离零时的分钟数,当其值大于一个指定的值时跳出该循环。我用了各种循环语句都不能解决,不是未进行循环就是进入死循环。请各位帮帮忙! (100分)<br />实际上我在设计一个定时关机的程序,原以为很简单的,不知道怎么遇到这么多问题。
以下是我写的这段代码,请帮忙修正一下其中的循环语句:
procedure TForm1.Button1Click(Sender: TObject);
var
Present: TDateTime;
Hour, Min, Sec, MSec: Word; //小时,分钟,秒,毫秒
t:String;
y:integer;
z:integer;

begin
Present:= Now;
DecodeTime(Present, Hour, Min, Sec, MSec); //分解出小时,分钟,秒,毫秒
t:=FloatToStr(spinedit1.value); //取得spinedit1中用户设置的分钟数
y:=Hour*60+Min; //当前系统时间距离0:00的分钟数
z:=tag+StrToint(t); //假定用户设定距离0:00时刻z分钟后自动关闭计算机

while y&lt;z do //使用这句时进入死循环,不使用这句时则不进入循环
if y&gt;=z then
begin
// cmdLine := 'c:/windows/notepad.exe'; //跳出循环,打开记事本程序
cmdLine := 'c:/windows/RUNDLL32.EXE USER.EXE,EXITWINDOWS'; //跳出循环关闭计算机
end;

end;
 
怎么只有看的没有答的啊?是不是嫌分少?我的分不多啊!帮帮忙吧各位兄弟!
 
用一个Timer控件
设置Interval为1000,将你要的内容写在OnTimer事件中
procedure TForm1.Timer1Timer(Sender: TObject);
var
Present: TDateTime;
Hour, Min, Sec, MSec: Word; //小时,分钟,秒,毫秒
t:String;
y:integer;
z:integer;

begin
Present:= Now;
DecodeTime(Present, Hour, Min, Sec, MSec); //分解出小时,分钟,秒,毫秒
t:=FloatToStr(Tspinedit1.value); //取得Tspinedit1中用户设置的分钟数
y:=Hour*60+Min; //当前系统时间距离0:00的分钟数
z:=tag+StrToint(t); //其实可以把z看成一个指定的值

if y&gt;=z then
begin
cmdLine := 'c:/windows/notepad.exe'; //跳出循环,打开记事本程序
end;

end;
太晚了,我现在的电脑没有装Delphi不帮你调试了,你自己试一下,若还不行说明你的算法有问题。
 
to muhx:

我试了,还是不能跳出这个循环,算法已测试过,应该没有问题的。
什么原因呢?
 
终于把你的程序看明白了,,也知道了你的意思.
while y&lt;z do //使用这句时进入死循环,不使用这句时则不进入循环
if y&gt;=z then
begin
cmdLine := 'c:/windows/notepad.exe'; //跳出循环,打开记事本程序
end;
//////////////////////////////////////
上面的程序能退出来么?根本就不能,就是说它永远在循环判断.....满足了y&lt;z这个条件,进入循环,而你又y&gt;=z想调出循环,怎么可能呢?y&lt;z和y&gt;=z这两个条件怎么能同时满足呢/比如,你设定的是小于5分钟关机,实际情况确实小于5分钟了,进入循环,原本是要关机,可你又来了句y&gt;=z,它里面的语句是不能执行的,关机语句没有执行,,,,.........................!
 
你的程序是y取得值永远是程序刚执行时候距离0:00的分钟数、
你需要在while y&lt;z 这个循环中,取得当前时间计算Y的值并且每次都要修改。、
你的程序可改为
Y:=NOW;
Z:=INTTOTIME('HH:MM:SS');

while TRUE do //使用这句时进入死循环,不使用这句时则不进入循环、
BEING
Y:=NOW;
if y&gt;=z then
begin
cmdLine := 'c:/windows/notepad.exe'; //跳出循环,打开记事本程序
EXIT;
end;//时间可以直接比较的。
END;
这是你的本意,但是如果要求不用很准确的话,比如每秒钟监测一次
可以用TIMER控见,直接在TIMERTIME事件中写入
IF INTTOTIME(Z)&gt;NOW THEN
你需要的操作//

 
如果不想用Timer控件,这样也可以:
procedure TForm1.Button1Click(Sender: TObject);
var
Present: TDateTime;
Hour, Min, Sec, MSec: Word; //小时,分钟,秒,毫秒
t:String;
y:integer;
z:integer;

begin
z:=tag+StrToint(t); //其实可以把z看成一个指定的值
y:=0;
while y&lt;z do
begin
Present:= Now;
DecodeTime(Present, Hour, Min, Sec, MSec); //分解出小时,分钟,秒,毫秒
t:=FloatToStr(Tspinedit1.value); //取得Tspinedit1中用户设置的分钟数
y:=Hour*60+Min; //当前系统时间距离0:00的分钟数
Application.ProcesseMessage;
if Application.Terminated then Exit;
end;
cmdLine := 'c:/windows/notepad.exe'; //跳出循环,打开记事本程序
..........
end;
 
基本的程序设计都有问题,楼上说的对,循环体不对!
 
to TYZhang:

代码未通过,编译时出现错误:
[Error] Unit1.pas(72): Undeclared identifier: 'ProcesseMessage'
但是我不知道标识符 PocesseMessage 应该如何声明?请指点一下!

另外我觉得下面这句代码
t:=FloatToStr(spinedit1.value); //取得spinedit1中用户设置的分钟数

应该放在
z:=tag+StrToint(t); //其实可以把z看成一个指定的值
的前面吧?
 
to 陈晨:

好象您把我意思搞错了,我的意思是要计算机在用户指定的时间到达后执行另外一个程序,比如关闭计算机。
 
procedure TForm1.Button1Click(Sender: TObject);
var
Present: TDateTime;
Hour, Min, Sec, MSec: Word; //小时,分钟,秒,毫秒
t:String;
y:integer;
z:integer;
begin
t:=FloatToStr(Tspinedit1.value); //取得Tspinedit1中用户设置的分钟数
z:=tag+StrToint(t); //其实可以把z看成一个指定的值
y:=0;
while y&lt;z do
begin
Present:= Now;
DecodeTime(Present, Hour, Min, Sec, MSec); //分解出小时,分钟,秒,毫秒
y:=Hour*60+Min; //当前系统时间距离0:00的分钟数
Application.ProcessMessages;
if Application.Terminated then Exit;
end;
cmdLine := 'c:/windows/notepad.exe'; //跳出循环,打开记事本程序
..........
end;
 
陈晨说的对的啊
你的错误是在循环里没有再查询时间
加上Y:=Now就对了啊
 
三楼的 muhx说的没错呀
 
to TYZhang:

原来是ProcessMessages写错了啊。
现在编译是通过了(还要做一些修改)。但是时间到了以后,屏幕上什么事情也没有发生。
我把代码全部贴出来,调整好以后就是一个完整的关机程序了,请哪位朋友帮忙调试一下,我不知道TYZhang的代码哪里还有问题,谢谢了!

Unit1.pas内容:

unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Spin,ShellAPI;

type
TForm1 = class(TForm)
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
SpinEdit1: TSpinEdit;
Label4: TLabel;
Button1: TButton;
Label5: TLabel;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
Present: TDateTime;
Year, Month, Day, Hour, Min, Sec, MSec: Word;
//x:integer;

begin
Present:= Now;
DecodeDate(Present, Year, Month, Day);//可以分解出年,月,日
Label1.Caption := '今天是' + IntToStr(Year)+'年'+IntToStr(Month)+
'月'+IntToStr(Day) + '日 ' ;
DecodeTime(Present, Hour, Min, Sec, MSec);//分解出小时,分钟,秒,毫秒
Label2.Caption := '现在的时间是' +IntToStr(Hour) +'时'+IntToStr(Min) + '分 '+
IntToStr(sec)+'秒'+IntToStr(Msec)+'毫秒';
tag:=Hour*60+Min; //Tag是Form的一个属性,不用重新声明。
end;

procedure TForm1.Button1Click(Sender: TObject);
var
Present: TDateTime;
Hour, Min, Sec, MSec: Word; //小时,分钟,秒,毫秒
t:String;
y:integer;
z:integer;
begin
Present:= Now;
DecodeTime(Present, Hour, Min, Sec, MSec);//分解出小时,分钟,秒,毫秒
t:=FloatToStr(spinedit1.value); //取得Tspinedit1中用户设置的分钟数
z:=tag+StrToint(t); //取得spinedit1中用户设置的分钟数
Label5.Caption := '当前时刻距离0:00时刻'+IntToStr(Hour*60+Min)+'分钟'+'你已设定距离0:00时刻' +IntToStr(z) +'分钟后关机';
//Label5.Caption := '现在的时间是' +IntToStr(Hour) +'时'+IntToStr(Min) + '分 ';
y:=0;
while y&lt;z do
begin
Present:= Now;
DecodeTime(Present, Hour, Min, Sec, MSec); //分解出小时,分钟,秒,毫秒
y:=Hour*60+Min; //当前系统时间距离0:00的分钟数
Application.ProcessMessages;
if Application.Terminated then Exit;
end;
//cmdLine := 'c:/windows/notepad.exe'; //跳出循环,打开记事本程序
cmdLine := 'c:/windows/RUNDLL32.EXE USER.EXE,EXITWINDOWS'; //跳出循环,关机

end;
end.
 
哎!用个线程不是很好解决吗???

//线程
unit MyTimer;

interface

uses
Windows, Classes, SysUtils, Dialogs;

type
TMyTimer = class(TThread)
private
{ Private declarations }
protected
LTimerDate : TDateTime;
procedure Execute; override;
public
constructor Create(TimerDate:TDateTime);
destructor Destroy; override;
end;

implementation

procedure TMyTimer.Execute;
begin
while now&lt;LTimerDate do
;
if now&gt;LTimerDate then
showmessage('时间到');//此处改为你的关机
{ Place thread code here }
end;

constructor TMyTimer.Create(TimerDate:TDateTime);
begin
LTimerDate := TimerDate;
inherited Create(False);
end;

destructor TMyTimer.Destroy;
begin
inherited Destroy;
end;

end.

//main.pas
unit main;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, DateUtils, MyTimer;

type
TForm1 = class(TForm)
Edit1: TEdit;
Button1: TButton;
Button2: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
switch_Auto:integer;
{ Private declarations }
public
{ Public declarations }
end;

var
Timer :TMyTimer;
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
edit1.Text := DateTimeToStr(IncMinute(Now,5));
switch_Auto:=0;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
if switch_Auto=0 then begin
Timer:=TMyTimer.Create(StrToDateTime(Edit1.Text));
switch_Auto:=1;
end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
if switch_Auto=1 then begin
Timer.Terminate;
switch_Auto:=0;
end;
end;

end.

 
cmdLine := 'c:/windows/notepad.exe'; //跳出循环,打开记事本程序
这不是赋值语句吗?
用Winexec()调用一下试试。
 
to jianguobu:

未调试成功。麻烦您把相应的.dpr和.dfm文件代码在这里也帖一下好吗?
 
to 大家:

其实,TYZhang 的办法几乎可以成功了,可惜我目前与他联系不上,请大家就在帖子:

来自:thlt, 时间:2004-5-23 14:11:39, ID:2623064

的基础上改吧,谢谢各位了!
 
拉倒吧,前辈先贤的代码拿来抄一抄算啦!
不需要单元文件,直接保存为 AutoShutDown.dpr 编译即可。
编译时说缺少 res 文件,点确定继续,Delphi 自动生成资源文件。

program AutoShutDown;

uses
Windows,
ShellAPI,
Sysutils,
Messages;

{$R *.RES}
var
WinClass:TWndClassA;
Handle:hwnd;
Inst,Button1, Label1, Edit1: Integer;
Msg: TMsg;
tid: TNotifyIconDataA;
sdt:tdatetime;
timerid:integer;
hFont: Integer;
const
AppName='AutoShutDown';
st='定时关机';
About=st+' 1.0, Keyes.chen@263.net, Keyes 1999.10.23';
gjs='设定关机时间';
procedure SetShutdownTime;
var
Textlength: Integer;
Text: PChar;i:tdatetime;
begin
TextLength := GetWindowTextLength(Edit1);
GetMem(Text, TextLength + 1);
GetWindowText(Edit1, Text, TextLength + 1);
try
i:=Strtodatetime(Text);
if i&lt;=now then
begin
MessageBox(handle,'不对吧!早过了.','错误',mb_ok or MB_ICONERROR);
exit;
end;
sdt:=i;
timerid:=Settimer(handle,1000,1000,nil);
Showwindow(handle,sw_hide);
lstrcpy (tid.szTip,pchar(st+' 关机时间:'+Datetimetostr(sdt)));
Shell_NotifyIcon (nim_modify, @tid);
except
Killtimer(handle,timerid);
Messagebox(handle,pchar('关机时间设定错误'#13#10#13#10+'格式因该是:'+Datetimetostr(now)),AppName,Mb_ok or MB_ICONINFORMATION);
end;
FreeMem(Text, TextLength + 1);
end;
function WindowProc(hWnd, uMsg, wParam, lParam: Integer): Integer; stdcall;
var pt:tpoint;pm:Hmenu;
begin
result:=0;
Case uMsg of
wm_timer:
begin
if now&gt;=sdt then
begin
Killtimer(handle,timerid);
MessageBox(handle,'时间到了!时间到了.','定时信息',mb_ok or mb_IconExclamation or MB_TOPMOST);
// ExitWindowsEx(EWX_SHUTDOWN or EWX_Force, 0);
// PostMessage(handle,wm_Destroy,0,0);
end;
end;
wm_User:
begin
Case lparam of
WM_LBUTTONDBLCLK:
begin
showwindow(handle,sw_restore);
setforegroundwindow(handle);
end;
wm_LButtonDown,wm_RButtonDown:
begin
GetCursorPos (pt);
pm := CreatePopupMenu;
AppendMenu (pm,0,Ord ('S'),gjs);
AppendMenu (pm, 0, Ord ('A'), '关于...');
AppendMenu (pm, mf_Separator, 0, Nil);
AppendMenu (pm, 0, Ord ('E'), '退出');
SetForegroundWindow (handle);
if TrackPopupMenu (pm, tpm_BottomAlign or tpm_RightAlign, pt.x,{GetDeviceCaps(dc,Vertres)}pt.y, 0, handle, Nil) then
SetForegroundWindow (handle);
DestroyMenu (pm)
end;
end;
end;
wm_Destroy:
begin
Shell_NotifyIcon (nim_Delete, @tid);
Killtimer(handle,timerid);
halt;
end;
wm_Command:
begin
if (lParam = Button1) then begin SetshutdownTime;exit end;
Case Loword(wParam) of
Ord ('A'): MessageBox (0, About, AppName, mb_ok or MB_ICONINFORMATION);
Ord ('E'): PostMessage (handle, wm_Close, 0, 0);
Ord ('S'):
begin
Showwindow(handle,sw_restore);
end;
end;
end;
end;
Result := DefWindowProc(hWnd, uMsg, wParam, lParam);
end;

begin
{ ** Register Custom WndClass ** }
if FindWindow (AppName, Nil) &lt;&gt; 0 then begin
Messagebox(handle,'已经有一个AutoShutDown运行了',AppName,mb_ok or MB_ICONWARNING);
halt(0);
end;
Inst := hInstance;
with WinClass do
begin
style := CS_CLASSDC or CS_PARENTDC;
lpfnWndProc := @WindowProc;
hInstance := Inst;
hbrBackground := color_btnface + 1;
lpszClassname := AppName;
hCursor := LoadCursor(0, IDC_ARROW);
end;
RegisterClass(WinClass);
Handle := CreateWindowEx(WS_EX_WINDOWEDGE, AppName, 'AutoShutDown 1.00',
WS_VISIBLE {or WS_SIZEBOX} or WS_CAPTION or WS_SYSMENU,
283, 238, 325, 65, 0, 0, Inst, nil);
Button1 := CreateWindow('Button', 'OK', WS_VISIBLE or WS_CHILD or BS_PUSHLIKE or BS_TEXT,
236, 8, 75, 20, handle, 0, Inst, nil);
Label1 := Createwindow('Static', '', WS_VISIBLE or WS_CHILD or SS_LEFT,
8, 12, 80, 13, Handle, 0, Inst, nil);
Edit1 := CreateWindowEx(WS_EX_CLIENTEDGE, 'Edit', Pchar(Datetimetostr(now)), WS_CHILD or WS_VISIBLE or
WS_BORDER {or ES_PASSWORD}, 88, 8, 141, 21, Handle, 0, Inst, nil);
hFont := CreateFont(-12, 0, 0, 0, 500, 0, 0, 0, GB2312_CHARSET,
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH or FF_DONTCARE, '宋体');
if hFont &lt;&gt; 0 then
begin
SendMessage(Button1, WM_SETFONT, hFont, 0);
SendMessage(Label1, WM_SETFONT, hFont, 0);
SendMessage(Edit1, WM_SETFONT, hFont, 0);
end;
SetWindowText(Label1, pchar(gjs+':'));
SetFocus(Edit1);
UpdateWindow(Handle);
tid.cbSize := sizeof (tid);
tid.Wnd := handle;
tid.uID := 1;
tid.uFlags := nif_Message or nif_Icon or nif_Tip;
tid.uCallBackMessage := wm_User;
tid.hIcon := LoadIcon (hInstance, 'MAINICON');
lstrcpy (tid.szTip,st);
Shell_NotifyIcon (nim_Add, @tid);
while(GetMessage(Msg, Handle, 0, 0)) do
begin
TranslateMessage(msg);
DispatchMessage(msg);
end;
end.
 
来自:thlt, 时间:2004-5-22 21:51:15, ID:2622831
to 陈晨:
好象您把我意思搞错了,我的意思是要计算机在用户指定的时间到达后执行另外一个程序,比如关闭计算机。
============================
我怎么看不出来错呢?我觉得可以的啊?用TTimer可以的。
 
顶部