2016-09-05 7 views
1

우리 소프트웨어가 실행되는 동안 Windows가 종료되지 않도록하는 우리 시스템 용 작은 도구를 만들려고합니다. 독립성을 위해 this 정보를 사용하여 시스템 종료를 막는 별도의 응용 프로그램을 만들었습니다.Delphi - 트레이 응용 프로그램에서 Windows 종료 방지

그러나 응용 프로그램이 트레이로 최소화되면 Windows는 단순히 응용 프로그램을 종료하고 정상적으로 종료됩니다. 양식이 표시되면 (일명 Form.OnCreate 이벤트에서 Application.Minimize 호출에 주석을 달았습니다) 종료가 정상적으로 수행되지 않습니다.

MainWindow 후크를 사용하여 라이브를 유지하거나 어쩌면 시스템 종료를 방지하는 다른 방법을 얻을 수 있습니까?

감사합니다.

현재 코드 :

unit Main; 

interface 

uses 
    Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, 
    Vcl.Controls, Vcl.Forms, Vcl.Dialogs, TlHelp32, dateutils, Vcl.AppEvnts, Vcl.ExtCtrls; 

type 
    TForm1 = class(TForm) 
    TrayIcon1: TTrayIcon; 
    ApplicationEvents1: TApplicationEvents; 
    procedure FormCreate(Sender: TObject); 
    function HookEndSession(var Message: TMessage): Boolean; 
    procedure WMQueryEndSession(var Msg : TWMQueryEndSession) ; 
     message WM_QueryEndSession; 
    procedure ApplicationEvents1Minimize(Sender: TObject); 
    procedure ApplicationEvents1Restore(Sender: TObject); 
    procedure TrayIcon1DblClick(Sender: TObject); 
    private 
    { Private declarations } 
    public 
    { Public declarations } 
    end; 

var Form1: TForm1; 
var Mutex : THandle; 

implementation 

{$R *.dfm} 



procedure TForm1.WMQueryEndSession(var Msg: TWMQueryEndSession); 
begin 
    Msg.Result := 0; 
end; 

function TForm1.HookEndSession(var Message: TMessage): Boolean; 
begin 
    result := false; 
    if Message.Msg = WM_ENDSESSION then begin 
    Message.Result := 0; 
    result := true; 
    end; 
end; 


procedure TForm1.TrayIcon1DblClick(Sender: TObject); 
begin 
    WindowState := wsNormal; 
    Application.Terminate; 
end; 

procedure TForm1.ApplicationEvents1Minimize(Sender: TObject); 
begin 
    Hide(); 
    WindowState := wsMinimized; 
    TrayIcon1.Visible := True; 
end; 

procedure TForm1.ApplicationEvents1Restore(Sender: TObject); 
begin 
    Application.Minimize; 
end; 

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    Mutex := CreateMutex(nil, True, 'preventWinShutdown'); 
    if (Mutex = 0) OR (GetLastError = ERROR_ALREADY_EXISTS) then 
    Application.Terminate; 

    Application.HookMainWindow(HookEndSession); 

    TrayIcon1.Hint := 'Windows Shutdown prevented.'; 
    //Application.Minimize; 
end; 


end. 

답변

4

나는 손에 XE3을 가지고 있지 않지만 XE7에, TCustomTrayIcon.WindowProc 명시 적으로 로그 오프/종료와 함께 진행하기 위해 Windows에 신호 (TRUE에 해당) 1을 반환하여 WM_QUERYENDSESSION를 처리/다시 시작하십시오. 당신은 그것을 무시할 수 있습니다보다 완벽한 솔루션을

type 
    TTrayIcon = class(Vcl.ExtCtrls.TTrayIcon) 
    protected 
    procedure WindowProc(var Message: TMessage); override; 
    end; 

procedure TTrayIcon.WindowProc(var Message: TMessage); 
begin 
    case Message.Msg of 
    WM_QUERYENDSESSION: 
     Message.Result := 0; 
    else 
     inherited WindowProc(Message); 
    end; 
end; 

, 당신은 별도의 단위로 새로운 클래스를 만들 것이다, TCustomTrayIcon 재 출판 특성 및 TTrayIcon이하는 것처럼, 노출하고자하는 이벤트를 상속 설치 IDE의 구성 요소를 사용하고 프로젝트에서이 구성 요소를 사용하십시오.

위 예제는 사용자가 TForm1 앞에 간단히 선언하고이 장치에서만 즉시 사용할 수있는 인터 포저 클래스가 포함 된 빠른 예제입니다.

3

Ondrej는 솔루션의 절반에 불과하다고 말했습니다.

Vista 이상에서는 ShutdownBlockReasonCreate()을 사용해야합니다. 이 기능은 다음 이유로 인해주의의 귀하의 경우 특히 중요하다 : 종료를 차단해야

Application Shutdown Changes in Windows Vista

응용 프로그램이 Windows XP에서 새로운 종료 이유 API를

를 사용한다, 마이크로 소프트는 권장하는 응용 프로그램의 경우 셧다운을 막기 위해 필요한 이유를 설명하는 자체 UI가 표시되어야하므로 셧다운이 실패 할 때 사용자가 덜 좌절하게된다. 앞에서 설명한 것처럼 Windows Vista는 응용 프로그램이 차단 종료에 제공 한 모든 이유를 나열하는 새 UI를 표시하여 종료가 더 이상 실패 할 때 사용자 불만을 줄입니다. 응용 프로그램이 FALSE 반환 또는 WM_QUERYENDSESSION에 응답하지뿐만 아니라 종료를 차단해야하는 경우가 차단되는 이유

Windows Vista에서

, 그것은 이유 문자열 설명에 윈도우를 제공하는 간단한 API를 사용하여 새로운 UI를 활용한다 종료.이 API는 간단하다 :이 API의

BOOL ShutdownBlockReasonCreate(HWND hWnd, LPCWSTR pwszReason);

BOOL ShutdownBlockReasonDestroy(HWND hWnd);

BOOL ShutdownBlockReasonQuery(HWND hWnd, LPWSTR pwszBuff, DWORD *pcchBuff);

를 사용하여 개별 ShutdownBlockReason에 대한 MSDN 설명서뿐만 아니라,이 항목의 뒷부분에 더 자세히 설명되어있다() 기능.

다시 말하지만 이 API는 종료를 차단하기 위해 WM_QUERYENDSESSION에 FALSE (또는 응답 지연)를 반환 할 필요를 대체하지 않습니다. 응용 프로그램은 API 사용 외에도이 작업을 수행해야합니다. WM_QUERYENDSESSION에 TRUE를 반환하는 응용 프로그램은 API을 사용했는지 여부에 관계없이 시스템 종료시 닫힙니다.

응용 프로그램에 표시 가능한 최상위 창이없는 경우 종료를 성공적으로 차단해야하는 경우이 API를 사용해야합니다. 이러한 응용 프로그램은 API을 사용하지 않고 종료를 차단하면 자동으로 종료됩니다.