Einzelnen Beitrag anzeigen

Meta777

Registriert seit: 8. Sep 2004
Ort: Magdeburg
248 Beiträge
 
Delphi 10 Seattle Enterprise
 
#9

AW: Multi-Monitor-Umgebung: Bestimmten Monitor abschalten

  Alt 18. Dez 2012, 21:41
Ahoi,

mittels DDC/CI geht dies wohl am besten (vorausgesetzt die Monitore unterstützen es). Ich hatte mal irgendwo ein Testproject, wenn ich das finde häng ich es an.

hth

ACHTUNG: Der Code kann die Monintoreinstellungen zu unbrauchbaren Werten hin ändern. Prüfe ggf. vorher ob du deinen Monitor über das OSD zurücksetzen kannst. Zum Factory Reset über den Source verwende die im "VESA Monitor Control Command Set" (Tabelle 8.1) definierten Codes.


Shalom

EDIT: Units hinzugefügt (TPmMoniControl ist als Singleton implementiert, deswegen hab ich auch die Singleton unit angefügt [die es hier auch im Forum geben müsste]). Das Ganze war wie gesagt ein Testproject und erhebt kein Anspruch auf Vollständigkeit ABER man konnte einzelne Monitor abschalten.

Verwendungsbeispiel:
die Methode "actToggleMoniPower" wird einer Action zugewiesen. Im "Tag"-Property der Action muss die Monitornummer stehen. Auf dem Form sind eine TListBox, eine TTreeView und um Codes zu senden eine TEdit und ein Button.

Delphi-Quellcode:
function EnumDisplayMonitorsCallback(hm: HMONITOR; dc: HDC; r: PRect; l: LPARAM): Boolean; stdcall;
//Callback für Auflistung aller Monitore

  function RectToStr: String;
  begin
    Result := Format('%d-%d %d|%d', [r.Left, r.Right, r.Top, r.Bottom]);
  end;

begin
  Form1.lbMonitorsAvailabe.AddItem(RectToStr, TObject(hm));
end;


procedure TForm1.FormCreate(Sender: TObject);
begin
  EnumDisplayMonitors(0, nil, EnumDisplayMonitorsCallback, 0);
end;

procedure TForm1.lbMonitorsAvailabeClick(Sender: TObject);
begin
  //Vom Monitor unterstützte Codes ermitteln...
  TPmMoniControl.GetVCPCodesAvailable(HMONITOR(lbMonitorsAvailabe.Items.Objects[
    lbMonitorsAvailabe.ItemIndex]));
  Assign(TPmMoniControl.ReqInstance);
end;

procedure TForm1.Assign(ASource: TPersistent);
var
  i: Integer;
  LLastNodeAdded: TTreeNode;

  procedure AddChilds(AParent: TTreeNode; AValues: TStrings);
  var
    i: Integer;
  begin
    for i := 0 to AValues.Count-1 do
      tvCodes.Items.AddChild(AParent, AValues[i]);
  end;

begin
  if (ASource <> nil) AND (ASource.InheritsFrom(TPmMoniControl)) then
  begin
    tvCodes.Items.Clear;
    for i := 0 to TPmMoniControl(ASource).CodesAvailable.Count-1 do
    begin
      LLastNodeAdded := tvCodes.Items.AddChild(nil,
        TPmMoniControl(ASource).CodesAvailable[i]);
      if TPmMoniControl(ASource).CodesAvailable.Objects[i] <> nil then
        AddChilds(LLastNodeAdded,
          TStrings(TPmMoniControl(ASource).CodesAvailable.Objects[i]));
    end;//for i := 0 to TPmMoniControl(ASource).CodesAvailable.Count-1 do
  end else
    inherited;
end;

procedure TForm1.btnSendClick(Sender: TObject);
var
  LVCPCode: Byte;
  LData: DWORD;
begin
  LVCPCode := StrToInt('$' + tvCodes.Selected.Text);
  LData := StrToInt(eValue.Text);
  if not TPmMoniControl.Send(LVCPCode, LData) then
    RaiseLastOSError;
end;

procedure TForm1.actToggleMoniPower(Sender: TObject);
const
  //although we assume that the monitor is powered on by default we store the
  //value visa versa for simplicity (so we do not need to set the initial
  //powerstate to True [1] in the actions .Tag-property)
  konPowerValue: Array[Boolean] of Byte = (1, 4);
var
  LMoniNumber, LPowerState: Byte;
begin
  //the Monitor number is set in the .Tag property at designtime!
  LMoniNumber := Lo(TAction(Sender).Tag);
  //In the High-Byte we store the power state - get it here
  LPowerState := Hi(TAction(Sender).Tag);
  //at least the monitor should be "detected"
  Assert(lbMonitorsAvailabe.Items.Count >= LMoniNumber);
  //toogle the the powerstate - if it's True (1) set to False (0) and visa versa
  LPowerState := Ord(NOT Boolean(LPowerState));
  //Get VCP Codes via the HMonitor handle
  TPmMoniControl.GetVCPCodesAvailable(HMonitor(
    lbMonitorsAvailabe.Items.Objects[LMoniNumber-1]));
  //Send new power state value
  TPmMoniControl.Send($D6, konPowerValue[Boolean(LPowerState)]);
  //Save the new power state if it could be send to the monitor
  TAction(Sender).Tag := MakeWord(LMoniNumber, LPowerState);
end;
Angehängte Dateien
Dateityp: pas pmMoniControl.pas (5,5 KB, 33x aufgerufen)
Dateityp: pas pmSingleton.pas (4,8 KB, 28x aufgerufen)

Geändert von mkinzler (20. Dez 2012 um 08:55 Uhr)
  Mit Zitat antworten Zitat