AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Hibernate und Standby erkennen

Ein Thema von himitsu · begonnen am 28. Nov 2006 · letzter Beitrag vom 23. Jul 2016
Antwort Antwort
Seite 3 von 3     123   
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#21

AW: Hibernate und Standby erkennen

  Alt 22. Jul 2016, 12:59
Adhoc sehe ich zwei Möglichkeiten:
  1. Stateless mit einem ClientDataSet (der Umbau wird aber wohl zu aufwändig sein)
  2. Eine statische Klasse die Tokens (Interface wegen ARC) herausgibt und beim ersten Token den Modus setzt und beim Verschwinden des letzten Tokens den Status wieder zurücksetzt (geringer Aufwand beim Einbau in das aktuelle Programm)

Auf die Schnelle mal dahingetippt
Delphi-Quellcode:
unit System.PowerManagement;

interface

uses
  System.Generics.Collections;

type
  TPowerModeOption = ( Display, System, Away );
  TPowerModeOptions = set of TPowerModeOption;

  IPowerManagementToken = interface
    [ '{F6326420-9BE9-4CAE-9EC8-0E6C4EE1B265}' ]
    function GetOptions( ): TPowerModeOptions;
    property Options: TPowerModeOptions read GetOptions;
  end;

  IPowerManagementService = interface
    procedure SetOptions( PowerModeOptions: TPowerModeOptions );
  end;

  PowerManagement = class sealed
  private type
    TInternalPowerManagementToken = class
    private
      FOptions: TPowerModeOptions;
    public
      constructor Create( Options: TPowerModeOptions );
      destructor Destroy; override;

      property Options: TPowerModeOptions read FOptions;
    end;

    TPowerManagementToken = class( TInterfacedObject, IPowerManagementToken )
    private
      function GetOptions( ): TPowerModeOptions;
    private
      FToken: TInternalPowerManagementToken;
    public
      constructor Create( Options: TPowerModeOptions );
      destructor Destroy; override;
    end;

    TNullService = class( TInterfacedObject, IPowerManagementService )
    private { IPowerManagementService }
      procedure SetOptions( PowerModeOptions: TPowerModeOptions );
    end;
  private
    class var _Service : IPowerManagementService;
    class var _Tokens : TList<TInternalPowerManagementToken>;
    class var _CurrentOptions: TPowerModeOptions;
    class constructor Create( );
    class destructor Destroy( );
    class procedure TokensNotify( Sender: TObject; const Item: TInternalPowerManagementToken; Action: TCollectionNotification );
  public
    class function GetToken( const PowerModeOptions: TPowerModeOptions ): IPowerManagementToken;
  end;

implementation

uses
{$IFDEF MSWINDOWS}
  System.PowerManagement.Win,
{$ENDIF}
  System.SysUtils;

{ PowerManagement.TPowerManagementToken }

constructor PowerManagement.TPowerManagementToken.Create( Options: TPowerModeOptions );
begin
  inherited Create( );
  if Options <> [ ]
  then
    FToken := TInternalPowerManagementToken.Create( Options );
end;

destructor PowerManagement.TPowerManagementToken.Destroy;
begin
  FToken.DisposeOf( );
  inherited;
end;

function PowerManagement.TPowerManagementToken.GetOptions: TPowerModeOptions;
begin
  if Assigned( FToken )
  then
    Result := FToken.Options
  else
    Result := [ ];
end;

{ PowerManagement }

class constructor PowerManagement.Create;
begin
{$IFDEF MSWINDOWS}
  _Service := TWindowsPowerManagementService.Create;
{$ELSE}
  _Service := TNullService.Create;
{$ENDIF}
  _Tokens := TList<TInternalPowerManagementToken>.Create( );
  _Tokens.OnNotify := TokensNotify;
  _CurrentOptions := [ ];
end;

class destructor PowerManagement.Destroy;
begin
  _Service.SetOptions( [ ] );
  _Tokens.Free;
end;

class function PowerManagement.GetToken( const PowerModeOptions: TPowerModeOptions ): IPowerManagementToken;
var
  lToken: TPowerManagementToken;
begin
  lToken := TPowerManagementToken.Create( PowerModeOptions );
  Result := lToken;
end;

class procedure PowerManagement.TokensNotify(
  Sender : TObject;
  const Item: TInternalPowerManagementToken;
  Action : TCollectionNotification );
var
  lToken : TInternalPowerManagementToken;
  lOptions: TPowerModeOptions;
begin
  lOptions := [ ];

  for lToken in _Tokens do
    begin
      lOptions := lOptions + lToken.FOptions;
    end;

  if _CurrentOptions <> lOptions
  then
    begin
      _Service.SetOptions( lOptions );
      _CurrentOptions := lOptions;
    end;
end;

{ PowerManagement.TNullService }

procedure PowerManagement.TNullService.SetOptions( PowerModeOptions: TPowerModeOptions );
begin
  // do nothing
end;

{ PowerManagement.TInternalPowerManagementToken }

constructor PowerManagement.TInternalPowerManagementToken.Create( Options: TPowerModeOptions );
begin
  inherited Create;
  FOptions := Options;
  _Tokens.Add( Self );
end;

destructor PowerManagement.TInternalPowerManagementToken.Destroy;
begin
  _Tokens.Remove( Self );
  inherited;
end;

end.
Delphi-Quellcode:
unit System.PowerManagement.Win;

interface

uses
  Winapi.Windows,
  System.SysUtils,
  System.PowerManagement;

type
  TWindowsPowerManagementService = class( TInterfacedObject, IPowerManagementService )
  private { IPowerManagementService }
    procedure SetOptions( PowerModeOptions: TPowerModeOptions );
  end;

implementation

{ TWindowsPowerManagementService }

procedure TWindowsPowerManagementService.SetOptions( PowerModeOptions: TPowerModeOptions );
var
  esFlags: Cardinal;
  lResult: Cardinal;
begin
  esFlags := 0;

  if TPowerModeOption.Display in PowerModeOptions
  then
    esFlags := esFlags or ES_DISPLAY_REQUIRED;
  if TPowerModeOption.System in PowerModeOptions
  then
    esFlags := esFlags or ES_SYSTEM_REQUIRED;
  if TPowerModeOption.Away in PowerModeOptions
  then
    esFlags := esFlags or ES_AWAYMODE_REQUIRED;

  if esFlags <> 0
  then
    esFlags := esFlags or ES_CONTINUOUS;

  lResult := SetThreadExecutionState( esFlags );
  if lResult = 0
  then
    raise Exception.Create( 'Could not set ThreadExecutionState' );
end;

end.
Delphi-Quellcode:
unit Forms.MainForm;

interface

uses
  Winapi.Windows, Winapi.Messages,
  System.SysUtils, System.Variants, System.Classes, System.PowerManagement,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm1 = class( TForm )
    CheckBox1: TCheckBox;
    CheckBox2: TCheckBox;
    CheckBox3: TCheckBox;
    SetModeButton: TButton;
    ClearModeButton: TButton;
    procedure ClearModeButtonClick( Sender: TObject );
    procedure SetModeButtonClick( Sender: TObject );
  private
    FToken: IPowerManagementToken;
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.ClearModeButtonClick( Sender: TObject );
begin
  FToken := nil;
end;

procedure TForm1.SetModeButtonClick( Sender: TObject );
var
  lOptions: TPowerModeOptions;
begin
  lOptions := [ ];

  if CheckBox1.Checked
  then
    lOptions := lOptions + [ TPowerModeOption.Display ];

  if CheckBox2.Checked
  then
    lOptions := lOptions + [ TPowerModeOption.System ];

  if CheckBox3.Checked
  then
    lOptions := lOptions + [ TPowerModeOption.Away ];

  FToken := PowerManagement.GetToken( lOptions );
end;

end.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)

Geändert von Sir Rufo (22. Jul 2016 um 14:04 Uhr)
  Mit Zitat antworten Zitat
mm1256

Registriert seit: 10. Feb 2014
Ort: Wackersdorf, Bayern
640 Beiträge
 
Delphi 10.1 Berlin Professional
 
#22

AW: Hibernate und Standby erkennen

  Alt 22. Jul 2016, 16:48
Danke @Sir Rufo für das Beispiel. Um auf Anhieb zu verstehen, wie du das meinst, muss ich erst mal meinen Kenntnisstand etwas vertiefen. Schöne Aufgabe für das Wochenende.

Ja gut aber WAS willst du denn machen? Wenn ein MDI-Child offen ist willst du Standby nicht verhindern, aber du willst auch kein Standby haben. Du musst dich für eins entscheiden.
Oder hoffst du auf eine Datenbankverbindung die den Standby überlebt? Keine Ahnung ob sowas geht, aber darauf würde ich nicht wetten.
Es ist so, wenn kein MDI aktiv ist, habe ich kein Problem damit, bei PBT_APMSUSPEND die Db-Connection zu schließen, und bei PBT_APMRESUMEAUTOMATIC (das kommt ja schon, wenn der User nur seine Maus bewegt) wieder zu verbinden. Wenn aber MDI- oder andere Fenster geöffnet sind, müsste ich mir den Zustand (offen/geschlossen), den Satzzeiger (DB-Cursor) und den Status (Browse, Edit usw.) aller offenen Datenbanken merken und anschließend wieder restaurieren. Dass ist sehr aufwändig, wenn nicht gar unmöglich. Die Datenbank (NexusDB) unterstützt auch einen Re-Connect, aber eben diese umfassende Restauration nicht, und dann kommt die Standby-Verhinderung ins Spiel.
Gruss Otto
Wenn du mit Gott reden willst, dann bete.
Wenn du ihn treffen willst, schreib bei Tempo 220 eine SMS
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#23

AW: Hibernate und Standby erkennen

  Alt 22. Jul 2016, 18:00
@mm1256

Eigentlich ganz einfach:

In jeder Form-Instanz die jetzt den Ruhezustand doof finden würde, holst du dir einfach ein Token
FToken := PowerManagement.GetToken( [ TPowerModeOption.System ] ); .

Es ist egal ob du dir das Token holst, wenn die Instanz erzeugt wird, oder erst zum Zeitpunkt wenn du einen Ruhezustand-Kritischen Moment erreichst.

Wenn es der Form-Instanz dann wieder egal ist, ob das System in den Ruhezustand geht, dann einfach das Token auf nil setzen.

Die PowerManagement -Klasse sorgt nun dafür, dass der Modus ab einem Token eingeschaltet wird und auch wieder ausgeschaltet wird, wenn es kein Token mehr gibt.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
mm1256

Registriert seit: 10. Feb 2014
Ort: Wackersdorf, Bayern
640 Beiträge
 
Delphi 10.1 Berlin Professional
 
#24

AW: Hibernate und Standby erkennen

  Alt 23. Jul 2016, 10:52
Vielen Dank Sir Rufo für die Erklärung!

Jetzt hätte ich nur noch ein Problem zu lösen: Die Anwendung verwendet insgesamt (grob geschätzt) etwa 150 Formulare, aufgeteilt auf mehrere Module (Exen). Viele von den Formularen sind vererbt. Das reduziert zwar den Aufwand etwas, ist mir aber trotzdem noch etwas zu hoch. Aber, für ein kleineres Projekt in dem ich auch diese Anforderung habe, werde ich es mal ausprobieren!
Gruss Otto
Wenn du mit Gott reden willst, dann bete.
Wenn du ihn treffen willst, schreib bei Tempo 220 eine SMS
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#25

AW: Hibernate und Standby erkennen

  Alt 23. Jul 2016, 11:19
Du kannst dir diese Funktionalität auch mit einer Unit hineinbringen
Delphi-Quellcode:
unit Vcl.BaseForm;

interface

uses
  System.PowerManagement,
  Vcl.Forms;

type
  TForm = class( Vcl.Forms.TForm )
  private
    FToken: IPowerManagementToken;
    function GetPowerModeOptions: TPowerModeOptions;
    procedure SetPowerModeOptions( const Value: TPowerModeOptions );
  protected
    function GetDefaultPowerMode( ): TPowerModeOptions; virtual;
    property PowerModeOptions: TPowerModeOptions read GetPowerModeOptions write SetPowerModeOptions;
  public
    procedure AfterConstruction; override;
  end;

implementation

{ TForm }

procedure TForm.AfterConstruction;
begin
  FToken := PowerManagement.GetToken( GetDefaultPowerMode( ) );
  inherited;
end;

function TForm.GetDefaultPowerMode: TPowerModeOptions;
begin
  Result := [ ];
end;

function TForm.GetPowerModeOptions: TPowerModeOptions;
begin
  Result := FToken.Options;
end;

procedure TForm.SetPowerModeOptions( const Value: TPowerModeOptions );
begin
  if PowerModeOptions <> Value
  then
    FToken := PowerManagement.GetToken( Value );
end;

end.
und diese Unit einfach nur noch nach der Vcl.Forms in die uses Liste aufnehmen. Dann brauchst du bei den Forms, die so etwas benötigen entweder nur die GetDefaultPowerMode zu überschreiben oder du setzt einfach den Wert der Eigenschaft PowerModeOptions .

Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 3 von 3     123   


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:24 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz