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

to 小雨哥:

哈哈,我还是第一次见到没有表单的工程,编译通过,不过这个程序不具备定时自动关机功能,只具备定时自动关机提醒功能,并不真正关闭计算机。

不过这段代码确实精彩,但不合我的要求,不知道我能否把它修改为自动关机程序。

其实 TYZhang 给出的代码最符合我的思路,不过我老是与他联系不上,不知道有哪位好心的朋友能就 ID=2623064 帖子的代码修改一下,请调试好后再贴啊!

下两个帖子我干脆给出相关的工程文件 dsgj.dpr 和 表单文件 Unit1.dfm 的代码,省得浪费您的时间了。
(编译时说缺少 res 文件,点确定继续,Delphi 自动生成资源文件。)
 
//工程文件 dsgj.dpr
program dsgj;

uses
Forms,
Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
 
嘿嘿,您把注释掉的 2 句去掉注释试试。
// ExitWindowsEx(EWX_SHUTDOWN or EWX_Force, 0);
// PostMessage(handle,wm_Destroy,0,0);
这 2 句是什么意思?不会看不出来吧。
 
//表单文件 Unit1.dfm
object Form1: TForm1
Left = 192
Top = 107
Width = 544
Height = 375
Caption = 'Form1'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
OldCreateOrder = False
OnCreate = FormCreate
PixelsPerInch = 96
TextHeight = 13
object Label1: TLabel
Left = 24
Top = 16
Width = 42
Height = 13
Caption = 'Label1'
Font.Charset = GB2312_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = #23435#20307
Font.Style = []
ParentFont = False
end
object Label2: TLabel
Left = 240
Top = 16
Width = 42
Height = 13
Caption = 'Label2'
Font.Charset = GB2312_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = #23435#20307
Font.Style = []
ParentFont = False
end
object Label3: TLabel
Left = 24
Top = 48
Width = 91
Height = 13
Caption = #35774#23450#20851#26426#26102#38388#65306
Font.Charset = GB2312_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = #23435#20307
Font.Style = []
ParentFont = False
end
object Label4: TLabel
Left = 189
Top = 48
Width = 65
Height = 13
Caption = #20998#38047#21518#20851#38381
Font.Charset = GB2312_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = #23435#20307
Font.Style = []
ParentFont = False
end
object Label5: TLabel
Left = 24
Top = 120
Width = 42
Height = 13
Caption = 'Label5'
Font.Charset = GB2312_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = #23435#20307
Font.Style = []
ParentFont = False
end
object SpinEdit1: TSpinEdit
Left = 128
Top = 44
Width = 49
Height = 22
Font.Charset = GB2312_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = #23435#20307
Font.Style = []
Increment = 20
MaxValue = 0
MinValue = 0
ParentFont = False
TabOrder = 0
Value = 60
end
object Button1: TButton
Left = 328
Top = 40
Width = 57
Height = 25
Caption = #30830#23450
Font.Charset = GB2312_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = #23435#20307
Font.Style = []
ParentFont = False
TabOrder = 1
OnClick = Button1Click
end
end
 
对您的唯一建议就是不要光要代码,一个代码,看懂全部意思后,即便有些不合意,您也能
动手改成合意的,这样才学得快,何况我贴的代码,原作者就是用来定时关机的,我贴的时
候,怕初学者一不小心关了机才注释掉的。哈哈哈哈,没想到您这么粗旷。
 
to 小雨哥:

您在线啊,太好了。
您的大名我在大富翁早就知道了。诚恳接受您的批评,我拿到就编译,确实没有仔细看代码。我再试一下,估计不会错了。不过要将我原来的设计思路作废我不甘心,TYZhang 朋友也给我指出错误了,可惜功亏一篑,我觉得几乎要成功了,但我不知道问题到底出在哪里?
ID号分别为 2623064 、2623548、2623552 的三个帖子分别给出了对应的单元文件、工程文件、表单文件的代码,.res文件您知道是不需要的。您有时间帮忙试试吗?

 
用timer很容易实现的
 
谢谢您的抬举。我实在没有很多时间,得看我有没有时间来完成,假如有时间我一定去看。
 
procedure TForm1.Timer1Timer(Sender: TObject);
begin
If 当前事件=指定的时间 Then
Begin
Timer1.Enabled := False;
关机;
End;
end;
 
你呼叫我,好有几次了吧,第一次没有看清楚,第二次,看到有回答是正确的,所以就........
//没有测试的代码,不能说正确的,呵呵

如果你用timer就不要用循环了,真接判断就可以了,因为timer就是一个循环
,用循环就不要用timer
==============
var
Present: TDateTime;
Hour, Min, Sec, MSec: Word; //小时,分钟,秒,毫秒
t:String;
y:integer;
z:integer;
begin
t:=FloatToStr(spinedit1.value); //取得spinedit1中用户设置的分钟数
z:=tag+StrToint(t); //假定用户设定距离0:00时刻z分钟后自动关闭计算机
repeat
DecodeTime(now, Hour, Min, Sec, MSec); //分解出小时,分钟,秒,毫秒
y:=Hour*60+Min; //当前系统时间距离0:00的分钟数
//这里有必要延时,(最好放在一个线程中)要不CPU将被这个循环消耗的差不多
until y>z
//你的操作
// cmdLine := 'c:/windows/notepad.exe'; //跳出循环,打开记事本程序
cmdLine := 'c:/windows/RUNDLL32.EXE USER.EXE,EXITWINDOWS'; //跳出循环关闭计算机
 
哎!真的PF你,这么简单的问题.

我把它放到笔记里去吧!!!
http://www.delphibbs.com/keylife/iblog_show.asp?xid=8009

对你的要求此程序都不用改了,在edit里改变定时时间后按启动就行了.
 
to jianguobu:

线程真是个好东西。可怜我翻遍了手头所有的5本delphi书,都没有关于线程的介绍,所以我的线程方面的知识几乎是一片空白。看来只有在互联网上找了,希望朋友们推荐一下这方面的链接,在此谢谢了!

您的程序我编译通过了,功能齐全,使用方便,总之一切OK,再次感谢!

看了您的笔记以后才发现,其实您已经把代码全部贴出来了,我现在知道怎么用这些代码构造一个工程文件了,可惜已经浪费您不少时间了,我的水平实在很臭。

我还想等等 TYZhang 不用线程的方法能不能调试好,没有办法,我就是太顽固了。最迟三天后结帖吧,这期间希望能联系上 TYZhang 。
 
to 小雨哥:

还是要手动啊!不过这是小问题啦,我已发现问题所在,这段代码真是妙不可言,产生的EXE文件才51K,真是小到不能再小了,而设置又是极其的简单。

不过这段代码稍微修改一下可以产生两个程序,一个是定时关机,另一个是定时提醒。
我得好好研究这段代码。

以后还望多多指点!多多推荐这类优秀的代码!万分感谢了!

to 陈晨 and WoDing 朋友:

您两的办法我还在试。。。希望都能成功!感谢你们!
 
to 陈晨:

编译时未通过,出错信息如下:
[Error] Unit1.pas(61): Undeclared identifier: 'INTTOTIME'

INTTOTIME 到底如何声明啊,是哪种变量呢?
 
to WoDing:

编译通过,但是循环体外的程序未被执行。
 
循环中怎么没有看见对Y的操作?当然会是死循环了
 
procedure TForm1.Button1Click(Sender: TObject);
var
Present: TDateTime;
Hour, Min, Sec, MSec: Word; //小时,分钟,秒,毫秒
t:String;
y:integer;
z:integer;
begin
//t:=FloatToStr(spinedit1.value); //取得spinedit1中用户设置的分钟数
z:=tag+StrToint(edit1.text);//假定用户设定距离0:00时刻z分钟后自动关闭计算机
repeat
DecodeTime(now, Hour, Min, Sec, MSec); //分解出小时,分钟,秒,毫秒
y:=Hour*60+Min; //当前系统时间距离0:00的分钟数
//Application.ProcessMessages ;没有作用
sleep(10000);//延时,进程进入假死状态
//这里有必要延时,(最好放在一个线程中)要不CPU将被这个循环消耗的差不多
until y>z ;
//你的操作
showmessage('到循环体外边了!');
end;
 
TYZhang 的代码没错,你所说的没反应,只是这条语句(cmdLine := 'c:/windows/RUNDLL32.EXE USER.EXE,EXITWINDOWS')关不了机而已.
那你按我下的试试吧(我在2000下调试通过的.)

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
function ControlWin2K(timer:integer): Boolean;
{ Private declarations }
public
{ Public declarations }
end;

const
DllName = 'Advapi32.dll';
var
Form1: TForm1;

implementation

{$R *.dfm}

function TForm1.ControlWin2K(timer:integer): Boolean;
var
GetDll: HWND;
InitiateSystemShutdownExA: function(
lpMachineName, lpMessage: string;
dwTimeout: DWord;
bForceAppsClosed, bRebootAfterShutdown: Boolean;
dwReason: DWord
): Integer; stdcall;
begin
GetDll := LoadLibrary(DllName);
if GetDll = 0 then
raise Exception.Create('加载Advapi32.dll出错,程序异常终止!');
@InitiateSystemShutdownExA := GetProcAddress(GetDll,'InitiateSystemShutdownExA');
if @InitiateSystemShutdownExA <> nil then
begin
InitiateSystemShutdownExA('127.0.0.1', 'hi', timer,
True, True, 0); //这里的timer就是定时关机的时间(秒为单).
end;
end;

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
AbortSystemShutdown('127.0.0.1');
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<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'; //跳出循环,关机
ControlWin2K(1);
end;

end.


注:你也可以去掉你那部份循环,直接用那个函数就行了.给定timer值,就会按时关机了.
 
to jianguobu:

TYZhang 的代码没错,你所说的没反应,只是这条语句(cmdLine := 'c:/windows/RUNDLL32.EXE USER.EXE,EXITWINDOWS')关不了机而已.
那你按我下的试试吧(我在2000下调试通过的.)
============
不是cmdLine := 'c:/windows/RUNDLL32.EXE USER.EXE,EXITWINDOWS')关不了机的问题,我改为普通语句,如:
showmessage('ok!');
也同样没有反应。

我的系统是WIN98,您给的代码不知道我能否调试成功?
谢谢您了!




 
晕,这个简单的问题怎么还没结呀

我都试过行的.你用如下代码试试看,我把z的值改为3,点了按钮,马上就执行了.

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;
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;
z := 3;
while y<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'; //跳出循环,关机
showmessage('OK');
end;

end.
 
顶部