(************************************************************************
*    This File is Part of the AHM Triton Tools                          *
*    for Borland Delphi and C++ Builder.                                *
*************************************************************************
* Copyright © 1995-1999 Alexander H. Mehlhorn (AHM) and Tritontools.com *
* All Rights reserved.                                                  *
*                                                                       *
*    For more Information contact us at                                 *
*    E-Mail : support@tritontools.com                                   *
*    URL : http://www.tritontools.com                                   *
*                                                                       *
*    AHM is copyright by Alexander H. Mehlhorn                          *
*    All Parts of this Collection were developed,                       *
*    designed and implemented by AHM                                    *
*                                                                       *
*    Under no Circumstances may you distribute this file                *
*    in this or any other format. This File is supplied                 *
*    as Evaluation of Source only. No Delphi Components may be developed*
*    using extracts or subsets of this code without expressed permission*
*    by AHM.                                                            *
*                                                                       *
*************************************************************************)
unit AHMTDisplayManager;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  AHMSystemConst,AHMSystemClass;
{$I AHM.INC}
type
  TAHMRestartRequest = procedure(Sender : TObject;Var RebootNow : Boolean) of Object;
  TAHMDisplayAfterChange = procedure(Sender : TObject;NewMode : String) of Object;
  TAHMDisplayManager = class(TAHMSystemsComponent)
  private
    FModes: TStrings;
    FMode: String;
    FRestartRequest: TAHMRestartRequest;
    FBeforeRestart: TNotifyEvent;
    FModeActive: TNotifyevent;
    FOnSuccess: TnotifyEvent;
    FOnFailed: TNotifyEvent;
    FOnNoStore: TNotifyEvent;
    FOnRebootFail: TNotifyevent;
    FAfterChange: TAHMDisplayAfterChange;
    procedure SetMode(const Value: String);
    function GetCurrentMode: String;
    procedure SetCurrentMode(const Value: String);
    { Private declarations }
  protected
    { Protected declarations }
  public
    { Public declarations }
    constructor Create(AOwner : TComponent); override;
    procedure Loaded; override;
    destructor Destroy; override;
    procedure Update; virtual;
    Property Modes : TStrings read FModes;
    Function Execute : Boolean;
  published
    { Published declarations }
    Property Mode : String read FMode write SetMode stored False;
    Property CurrentMode : String read GetCurrentMode write SetCurrentMode stored False;
    Property RestartRequest : TAHMRestartRequest read FRestartRequest write FRestartRequest;
    Property BeforeRestart : TNotifyEvent read FBeforeRestart write FBeforeRestart;
    Property OnAlreadyActive : TNotifyevent read FModeActive write FModeActive;
    Property OnSuccess : TNotifyEvent read FOnSuccess write FOnSuccess;
    Property OnFailed : TNotifyEvent read FOnFailed write FOnFailed;
    Property OnNoStore : TNotifyEvent read FOnNoStore write FOnNoStore;
    Property OnRebootFail : TNotifyevent read FOnRebootFail write FOnRebootFail;
    Property AfterChange : TAHMDisplayAfterChange read FAfterChange write FAfterChange;
  end;

implementation

{ TAHMDisplayManager }

constructor TAHMDisplayManager.Create(AOwner: TComponent);
begin
  inherited Create(Aowner);
  FModes:=TStringlist.Create;
  Update;
end;

destructor TAHMDisplayManager.Destroy;
begin
  FModes.Free;
  inherited Destroy;
end;

function AHMSetShutDown(privilegeName: string; enable: boolean): boolean;
var tpPrev,tp         : TTokenPrivileges;
    token      : THandle;
    dwRetLen   : DWord;
begin
  result := False;
  {$IFDEF AHMINPRISE3}
  OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, token);
  {$ELSE}
  OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, @token);
  {$ENDIF}
  tp.PrivilegeCount := 1;
  if LookupPrivilegeValue(nil, pchar(privilegeName), tp.Privileges[0].LUID) then
  begin
    if enable then tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED
              else tp.Privileges[0].Attributes := 0;
    dwRetLen := 0;
    result := AdjustTokenPrivileges(token, False, tp, SizeOf(tpPrev), tpPrev, dwRetLen);
  end;
  CloseHandle(token);
end;


function TAHMDisplayManager.Execute: Boolean;
Var AutoReboot : Boolean;
    I : Integer;
    ResultDev : Bool;
    DevMode : TDeviceMode;
    ResFlag : Integer;
begin
   ResFlag:=0;
   result:=false;
   AutoReboot:=True;
   FillChar(DevMode,SizeOf(DevMode),0);
   DevMode.dmSize:=SizeOf(DevMode);
   ResultDev:=True;
   I:=0;
   if not(FMode<>CurrentMode) then
   begin
     if assigned(FModeActive) then FModeActive(self);
   end else
   while ResultDev=True do
   begin
     ResultDev:=EnumDisplaySettings(nil,I,DevMode);
     Inc(I);
     if Resultdev then
     if (inttostr(DevMode.dmPelsWidth)+'x'+inttostr(DevMode.dmPelsHeight)+' ('+inttostr(DevMode.dmBitsPerPel)+'-bit)')=FMode then
     begin
       ChangeDisplaySettings(DevMode,CDS_UPDATEREGISTRY);
       if assigned(FAfterChange) then FAfterChange(Self,FMode);
       case ResFlag of
          DISP_CHANGE_SUCCESSFUL :
          begin
            result:=True;
            If assigned(FOnSuccess) then FOnSuccess(Self);
          end;
          DISP_CHANGE_FAILED	 : If assigned(FOnFailed) then FOnFailed(Self);
          DISP_CHANGE_BADFLAGS : If assigned(FOnFailed) then FOnFailed(Self);
          DISP_CHANGE_BADMODE : If assigned(FOnFailed) then FOnFailed(Self);
          DISP_CHANGE_NOTUPDATED : If assigned(FOnNoStore) then FOnNoStore(Self);
          DISP_CHANGE_RESTART :
          begin
            if assigned(FRestartRequest) then FRestartRequest(self,AutoReboot);
            if AutoReboot then
            begin
              if assigned(FBeforeRestart) then FBeforeRestart(self);
              AHMSetShutdown(ahmscseshutdownpriv, true);
              if not ExitWindowsEx(EWX_REBOOT, 0) then
              begin
                if assigned(FOnRebootFail) then FOnRebootFail(Self);
              end else result:=true;
              AHMSetShutdown(ahmscseshutdownpriv, False);
            end;
          end;
       else
        If assigned(FOnFailed) then FOnFailed(Self);
       end;
       Break;
     end;
   end;
end;

function TAHMDisplayManager.GetCurrentMode: String;
begin
  result:=Inttostr(GetDeviceCaps(GetDC(0),HorzRes))+'x'+
          Inttostr(GetDeviceCaps(GetDC(0),VertRes))+' ('+
          Inttostr(GetDeviceCaps(GetDC(0),BitsPixel))+'-bit)';
end;

procedure TAHMDisplayManager.Loaded;
begin
  inherited Loaded;
end;

procedure TAHMDisplayManager.SetCurrentMode(const Value: String);
begin
// Nothing ... only makes it visible in design
end;

procedure TAHMDisplayManager.SetMode(const Value: String);
Var I : Integer;
begin
  for I:=0 to FModes.count-1 do
  if Value=FModes[I] then FMode := Value;
end;

procedure TAHMDisplayManager.Update;
Var I : Integer;
    Result : Bool;
    DevMode : TDeviceMode;
begin
  I:=0;
  FModes.Clear;
  Result:=True;
  while Result=True do
  begin
    FillChar(DevMode,SizeOf(DevMode),0);
    DevMode.dmSize:=SizeOf(DevMode);
    Result:=EnumDisplaySettings(nil,I,DevMode);
    if Result then
    FModes.Add(inttostr(DevMode.dmPelsWidth)+'x'+inttostr(DevMode.dmPelsHeight)+' ('+inttostr(DevMode.dmBitsPerPel)+'-bit)');
    Inc(I);
  end;
end;

end.
