创建具有托盘的服务程序

2016-02-19 20:45 21 1 收藏

get新技能是需要付出行动的,即使看得再多也还是要动手试一试。今天图老师小编跟大家分享的是创建具有托盘的服务程序,一起来学习了解下吧!

【 tulaoshi.com - 编程语言 】

  我的主页: http://www.tommstudio.com/

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com/bianchengyuyan/)

  Windows 2000/XP和2003等支持一种叫做"服务程序"的东西.程序作为服务启动有以下几个好处:
  
      (1)不用登陆进系统即可运行.
      (2)具有SYSTEM特权.所以你在进程管理器里面是无法结束它的.
  
      笔者在2003年为一公司开发机顶盒项目的时候,曾经写过课件上传和媒体服务,下面就介绍一下如何用Delphi7创建一个Service程序.
      运行Delphi7,选择菜单File--New--Other---Service Application.将生成一个服务程序的框架.将工程保存为ServiceDemo.dpr和Unit_Main.pas,然后回到主框架.我们注意到,Service有几个属性.其中以下几个是我们比较常用的:
  
      (1)DisplayName:服务的显示名称
      (2)Name:服务名称.
  
      我们在这里将DisplayName的值改为"Delphi服务演示程序",Name改为"DelphiService".编译这个项目,将得到ServiceDemo.exe.这已经是一个服务程序了!进入CMD模式,切换致工程所在目录,运行命令"ServiceDemo.exe /install",将提示服务安装成功!然后"net start DelphiService"将启动这个服务.进入控制面版--管理工具--服务,将显示这个服务和当前状态.不过这个服务现在什么也干不了,因为我们还没有写代码:)先"net stop DelphiService"停止再"ServiceDemo.exe /uninstall"删除这个服务.回到Delphi7的IDE.
  
      我们的计划是为这个服务添加一个主窗口,运行后任务栏显示程序的图标,双击图标将显示主窗口,上面有一个按钮,点击该按钮将实现Ctrl+Alt+Del功能.
  
      实际上,服务程序莫认是工作于WinLogon桌面的,可以打开控制面板,查看我们刚才那个服务的属性--登陆,其中"允许服务与桌面交互"是不打钩的.怎么办?呵呵,回到IDE,注意那个布尔属性:Interactive,当这个属性为True的时候,该服务程序就可以与桌面交互了.
  
      File--New--Form为服务添加窗口FrmMain,单元保存为Unit_FrmMain,并且把这个窗口设置为手工创建.完成后的代码如下:
  
  
  


  unit Unit_Main;
  
  interface
  
  uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs, Unit_FrmMain;
  
  type
  TDelphiService = class(TService)
  procedure ServiceContinue(Sender: TService; var Continued: Boolean);
  procedure ServiceExecute(Sender: TService);
  procedure ServicePause(Sender: TService; var Paused: Boolean);
  procedure ServiceShutdown(Sender: TService);
  procedure ServiceStart(Sender: TService; var Started: Boolean);
  procedure ServiceStop(Sender: TService; var Stopped: Boolean);
  private
  { Private declarations }
  public
  function GetServiceController: TServiceController; override;
  { Public declarations }
  end;
  
  var
  DelphiService: TDelphiService;
  FrmMain: TFrmMain;
  implementation
  
  {$R *.DFM}
  
  procedure ServiceController(CtrlCode: DWord); stdcall;
  begin
    DelphiService.Controller(CtrlCode);
  end;
  
  function TDelphiService.GetServiceController: TServiceController;
  begin
    Result := ServiceController;
  end;
  
  procedure TDelphiService.ServiceContinue(Sender: TService;
  var Continued: Boolean);
  begin
    while not Terminated do
    begin
      Sleep(10);
      ServiceThread.ProcessRequests(False);
    end;
  end;
  
  procedure TDelphiService.ServiceExecute(Sender: TService);
  begin
    while not Terminated do
    begin
      Sleep(10);
      ServiceThread.ProcessRequests(False);
    end;
  end;
  
  procedure TDelphiService.ServicePause(Sender: TService;
  var Paused: Boolean);
  begin
    Paused := True;
  end;
  
  procedure TDelphiService.ServiceShutdown(Sender: TService);
  begin
    gbCanClose := true;
    FrmMain.Free;
    Status := csStopped;
    ReportStatus();
  end;
  
  procedure TDelphiService.ServiceStart(Sender: TService;
  var Started: Boolean);
  begin
    Started := True;
    Svcmgr.Application.CreateForm(TFrmMain, FrmMain);
    gbCanClose := False;
    FrmMain.Hide;
  end;
  
  procedure TDelphiService.ServiceStop(Sender: TService;
  var Stopped: Boolean);
  begin
    Stopped := True;
    gbCanClose := True;
    FrmMain.Free;
  end;
  
  end.
  


  
  主窗口单元如下:
  
  


  unit Unit_FrmMain;
  
  interface
  
  uses
  Windows, Messages, SysUtils, Variants, Classes, ShellApi, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls;
  
  const
  WM_TrayIcon = WM_USER + 1234;
  type
  TFrmMain = class(TForm)
  Timer1: TTimer;
  Button1: TButton;
  procedure FormCreate(Sender: TObject);
  procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  procedure FormDestroy(Sender: TObject);
  procedure Timer1Timer(Sender: TObject);
  procedure Button1Click(Sender: TObject);
  private
  { Private declarations }
  IconData: TNotifyIconData;
  procedure AddIconToTray;
  procedure DelIconFromTray;
  procedure TrayIconMessage(var Msg: TMessage); message WM_TrayIcon;
  procedure SysButtonMsg(var Msg: TMessage); message WM_SYSCOMMAND;
  public
  { Public declarations }
  end;
  
  var
  FrmMain: TFrmMain;
  gbCanClose: Boolean;
  implementation
  
  {$R *.dfm}
  
  procedure TFrmMain.FormCreate(Sender: TObject);
  begin
    FormStyle := fsStayOnTop; {窗口最前}
    SetWindowLong(Application.Handle, GWL_EXSTYLE, WS_EX_TOOLWINDOW); {不在任务栏显示}
    gbCanClose := False;
    Timer1.Interval := 1000;
    Timer1.Enabled := True;
  end;
  
  procedure TFrmMain.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  begin
    CanClose := gbCanClose;
    if not CanClose then
    begin
      Hide;
    end;
  end;
  
  procedure TFrmMain.FormDestroy(Sender: TObject);
  begin
    Timer1.Enabled := False;
    DelIconFromTray;
  end;
  
  procedure TFrmMain.AddIconToTray;
  begin
    ZeroMemory(@IconData, SizeOf(TNotifyIconData));
    IconData.cbSize := SizeOf(TNotifyIconData);
    IconData.Wnd := Handle;
    IconData.uID := 1;
    IconData.uFlags := NIF_MESSAGE or NIF_ICON or NIF_TIP;
    IconData.uCallbackMessage := WM_TrayIcon;
    IconData.hIcon := Application.Icon.Handle;
    IconData.szTip := 'Delphi服务演示程序';
    Shell_NotifyIcon(NIM_ADD, @IconData);
  end;
  
  procedure TFrmMain.DelIconFromTray;
  begin
    Shell_NotifyIcon(NIM_DELETE, @IconData);
  end;
  
  procedure TFrmMain.SysButtonMsg(var Msg: TMessage);
  begin
    if (Msg.wParam = SC_CLOSE) or
    (Msg.wParam = SC_MINIMIZE) then Hide
    else inherited; // 执行默认动作
  
end;
  
  procedure TFrmMain.TrayIconMessage(var Msg: TMessage);
  begin
    if (Msg.LParam = WM_LBUTTONDBLCLK) then Show();
  end;
  
  procedure TFrmMain.Timer1Timer(Sender: TObject);
  begin
    AddIconToTray;
  end;
  
  procedure SendHokKey;stdcall;
  var
  HDesk_WL: HDESK;
  begin
    HDesk_WL := OpenDesktop ('WinLogon', 0, False, DESKTOP_JOURNALPLAYBACK);
    if (HDesk_WL 0) then
    if (SetThreadDesktop (HDesk_WL) = True) then
    PostMessage(HWND_BROADCAST, WM_HOTKEY, 0, MAKELONG (MOD_ALT or MOD_CONTROL, VK_DELETE));
  end;
  
  procedure TFrmMain.Button1Click(Sender: TObject);
  var
  dwThreadID : DWORD;
  begin
    CreateThread(nil, 0, @SendHokKey, nil, 0, dwThreadID);
  end;
  
  end.
  
  program ServiceDemo;
  
  uses
  SvcMgr,
  Unit_Main in 'Unit_Main.pas' {DelphiService: TService},
  Unit_frmMain in 'Unit_frmMain.pas' {frmMain};
  
  {$R *.RES}
  
  begin
    Application.Initialize;
    Application.CreateForm(TDelphiService, DelphiService);
    Application.Run;
  end.
  

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com/bianchengyuyan/)

  
  
  窗体代码如下:
  


  object DelphiService: TDelphiService
  OldCreateOrder = False
  DisplayName = 'Delphi服务演示程序'
  Interactive = True
  OnContinue = ServiceContinue
  OnExecute = ServiceExecute
  OnPause = ServicePause
  OnShutdown = ServiceShutdown
  OnStart = ServiceStart
  OnStop = ServiceStop
  Left = 261
  Top = 177
  Height = 150
  Width = 215
  end
  
  object frmMain: TfrmMain
  Left = 192
  Top = 107
  Width = 696
  Height = 480
  Caption = '我的服务测试程序'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  OnCloseQuery = FormCloseQuery
  OnCreate = FormCreate
  OnDestroy = FormDestroy
  PixelsPerInch = 96
  TextHeight = 13
  object Button1: TButton
  Left = 296
  Top = 264
  Width = 75
  Height = 25
  Caption = 'Button1'
  TabOrder = 0
  OnClick = Button1Click
  end
  object Timer1: TTimer
  OnTimer = Timer1Timer
  Left = 120
  Top = 192
  end
  end
  


  
  

来源:https://www.tulaoshi.com/n/20160219/1624434.html

延伸阅读
所谓托盘程序顾名思义就是象托起的盘子一样的程序。而所谓的托起的盘子就是程序运行中显示出的图标,而托起的位置就是视窗系统的的工具栏了。托盘程序具有直观、占用屏幕空间较小并且可以为它定义多个功能菜单,这就给操作者带来了方便,所以越来越多的程序设计者都把程序设计成托盘这种方式。我们已经看过了用其他语言设计托盘程序的例子...
托盘程序是指这样一类程序:当程序运行后,会在系统的托盘区(也有说是状态区域)创建此程序的图标,使用者可以通过点击图标出现的菜单来控制程序的运行状态。托盘程序有很多优点,如不占屏幕,后台运行,便于控制等。所以现在越来越多的程序都做成了托盘程序。在VB.NET中,编写托盘程序是比较方便和简单的。这是因为VB.NET没有自身类库,...
译者说明:我是通过翻译来学习C#的,文中涉及到的有Visual Studio.NET有关操作,我都根据中文版的VS.NET显示信息来处理的,可以让大家不致有误解。 作者:Mark Strawmyer 我们将研究如何创建一个作为Windows服务的应用程序。内容包含什么是Windows服务,如何创建、安装和调试它们。会用到System.ServiceProcess.ServiceBase命名空间的类。 ...
自从微软公司推出Windows 95操作系统以来,系统托盘应用作为一种极具吸引力的用户界面设计深受广大用户的喜爱。使用系统托盘作为用户界面的Windows应用程序数不胜数,比如"金山词霸"、"Winamp"、"RealPlayer"等等。 这些程序运行时不显示运行窗口,只在任务栏上显示一个图标,表示程序正在运行,用户可以通过鼠标与应用程序交互,程序开发人...
         为儿童制作的常用教学软件是绘画软件。这些软件大都是基于早先为7 0 、8 0 年代的计算 机设计的简单的绘画软件。         最基本地,用户可以在屏幕上点击或拖动鼠标绘画。.在本例中,用户还可以选择不同颜 色和不同画刷。     &nb...

经验教程

392

收藏

99
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部