Monitor disablen

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
purebas
Beiträge: 127
Registriert: 11.03.2008 23:59
Wohnort: München

Monitor disablen

Beitrag von purebas »

Ich möchte bei der Nutzung mehrerer Monitor einen oder mehrere Monitore disablen.

Es gibt dazu ein C-Beispiel:
https://docs.microsoft.com/en-us/window ... ay-control

Wenn ich die Beschreibung richtig verstehe, dann disabled das Beispiel alle sekundären Monitore.
Das wäre die Funktionalität, die ich brauche.

Ich schaffe es nicht das Beispiel nach PB zu übersetzen. Kann mich jemand unterstützen?
GPI
Beiträge: 1511
Registriert: 29.08.2004 13:18
Kontaktdaten:

Re: Monitor disablen

Beitrag von GPI »

Ich weis nicht, ob du wirklich das hier willst. Die Routine ist dafür da, um einen Multi-Monitor-Betrieb einzurichten. Wo der Monitor ist, ob er gespiegelt ist oder den Desktop erweitert usw. Da sollte man nicht rumfummeln - es würde bspw. die Desktopicons durcheinanderwürfeln.

Ich hätte einen Alternativvorschlag. Hol dir die Coordinaten von den Desktop() befehlen, erstell ein borderless Fenster auf die volle Desktop-Größe, pin das Fenster und schalte die Fensterfarbe auf schwarz.
Und dran denken: Wenn mehrere Monitore da sind, heißt das nicht, das der erste Monitor der größte ist, oder auf den man Spielen will. Ich hab hier bspw. 2 Fullscreen-Monitore und einen 4k-TV angeschlossen. Gespielt wird mittels Pad auf den 4k, der ist aber Monitor 3.

Ansonsten beschreib mal, warum du das machen willst, eventuell ergeben sich dann völlig neue Lösungsansätze.
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!
Benutzeravatar
purebas
Beiträge: 127
Registriert: 11.03.2008 23:59
Wohnort: München

Re: Monitor disablen

Beitrag von purebas »

Es gibt bei nirsoft diese MultiMonitorTool mit dem kann man Monitor disablen und wieder enablen. Dies möchte ich innerhalb von meinem Programm auch machen können, um bspw. meine Monitore an dem einen Rechner zu aktivieren und gleichzeitig an dem anderen zu deaktivieren. Prinzipiell funktioniert die Schalterei mittels dem MultiMonitorTool. Dazu muss ich jedoch die richtige Konfiguration auf beiden PCs anwenden. Ich möchte ein Tool basteln, wo ich an einen der PCs ein Profil zum Beispiel "Unterricht" auswähle und dann die richtige Monitorzuordnung auf beiden PCs umsetze. Die PC-Kommunikation realisiere ich über TCP.

Was mir noch fehlt ist den Monitor aktivieren bzw. deaktivieren zu können.
GPI
Beiträge: 1511
Registriert: 29.08.2004 13:18
Kontaktdaten:

Re: Monitor disablen

Beitrag von GPI »

ok, schnell übersetzt, ohne groß zu testen, weil ich meine Monitor-Konfiguration nicht zerschießen will:

Code: Alles auswählen

Procedure DetachDisplay()
  
  Protected.l            FoundSecondaryDisp = #False;
  Protected.l           DispNum = 0                 ;
  Protected.DISPLAY_DEVICE  DisplayDevice
  Protected.l            Result;
  ;Protected.c           szTemp[200];
  Protected.l             i = 0            ;
  Protected.DEVMODE   defaultMode          ;
  
  ;// initialize DisplayDevice
  ;ZeroMemory(&DisplayDevice, SizeOf(DisplayDevice));
  DisplayDevice\cb = SizeOf(DisplayDevice)
  
  ; get all display devices
  While (EnumDisplayDevices_(#Null, DispNum, @DisplayDevice, 0))
    FillMemory(@defaultMode, SizeOf(DEVMODE),0);
    defaultMode\dmSize = SizeOf(DEVMODE)       ;
    If ( Not EnumDisplaySettings_(@DisplayDevice\DeviceName, #ENUM_REGISTRY_SETTINGS, @defaultMode) )
      Debug("Store default failed")
    EndIf      
    
    If ((DisplayDevice\StateFlags & #DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) And Not(DisplayDevice\StateFlags & #DISPLAY_DEVICE_PRIMARY_DEVICE))
      
      Protected.DEVMODE    DevMode;
      FillMemory(@DevMode, SizeOf(DevMode),0);
      DevMode\dmSize = SizeOf(DevMode)       ;
      DevMode\dmFields = #DM_PELSWIDTH | #DM_PELSHEIGHT | #DM_BITSPERPEL | #DM_POSITION | #DM_DISPLAYFREQUENCY | #DM_DISPLAYFLAGS 
      Result = ChangeDisplaySettingsEx_(DisplayDevice\DeviceName, 
                                        @DevMode,
                                        #Null,
                                        #CDS_UPDATEREGISTRY,
                                        #Null);
      Debug "Disable:"+PeekS(@DisplayDevice\DeviceName, SizeOf(DisplayDevice\DeviceName))
      
      ;The code below shows how To re-attach the secondary displays To the desktop
      
      ;             ChangeDisplaySettingsEx_(DisplayDevice\DeviceName,
      ;                                    @defaultMode,
      ;                                    #Null,
      ;                                    #CDS_UPDATEREGISTRY,
      ;                                    #Null);
      ;Debug "Enable:"+PeekS(@DisplayDevice\DeviceName, SizeOf(DisplayDevice\DeviceName))
      
    Else
      Debug "don't change:"+PeekS(@DisplayDevice\DeviceName, SizeOf(DisplayDevice\DeviceName))
    EndIf
    
    
    ; Reinit DisplayDevice just To be extra clean
    
    FillMemory(@DisplayDevice, SizeOf(DisplayDevice),0);
    DisplayDevice\cb = SizeOf(DisplayDevice)           ;
    DispNum + 1
  Wend ;End While For all display devices
EndProcedure

DetachDisplay()
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!
Benutzeravatar
purebas
Beiträge: 127
Registriert: 11.03.2008 23:59
Wohnort: München

Re: Monitor disablen

Beitrag von purebas »

Vielen Dank!

Leider passiert da gar nix, bei den sekundären Monitoren. Meine Hoffnung war die, dass diese sich deaktivieren. Dann hätte ich mich weiter rein hängen können.

Wahrscheinlich funktioniert das so nicht.
GPI
Beiträge: 1511
Registriert: 29.08.2004 13:18
Kontaktdaten:

Re: Monitor disablen

Beitrag von GPI »

Führ den code mal als admin aus. Wird in debug fenster was geschrieben?
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!
GPI
Beiträge: 1511
Registriert: 29.08.2004 13:18
Kontaktdaten:

Re: Monitor disablen

Beitrag von GPI »

tja, wenn MS halt nur funktionierende Beispiele bei ihrer API haben.
Ausschalten ist kein Problem - wie oben geschrieben, die sind dann wirklich komplett weg, icons und fenster werden verschoben etc. Nur das einschalten krieg ich ums verrecken nicht hin. Ich hab hier ein 3-Monitor-Betrieb und er schaltet mir nur einen der sekundären an und dann auch noch den falschen.
Ich fürchte durch das ausschalten bekommen die Monitore neue Namen...
wie auch immer: Hier der Code zum rumspielen:

Code: Alles auswählen

EnableExplicit

#CDS_ENABLE_UNSAFE_MODES = $00000100

Structure sDisplays
  name.c[32]
  isSecondary.l
  def.devmode
  errorstring.s
EndStructure

Global NewList Displays.sDisplays()

Procedure Display_Init()
  Protected.l DispNum = 0 
  Protected.DISPLAY_DEVICE DisplayDevice
  Protected.l Result
  
  ;// initialize DisplayDevice
  FillMemory(@DisplayDevice, SizeOf(DisplayDevice))
  DisplayDevice\cb = SizeOf(DisplayDevice)
  
  ClearList(Displays())
  
  
  ; get all display devices
  While (EnumDisplayDevices_(#Null, DispNum, @DisplayDevice, 0))
    AddElement(displays())
    CopyMemory(@DisplayDevice\DeviceName, @Displays()\name, SizeOf(sDisplays\name))
    
    FillMemory(@Displays()\def, SizeOf(DEVMODE),0)
    Displays()\def\dmSize = SizeOf(DEVMODE) 
    If ( Not EnumDisplaySettings_(@Displays()\name, #ENUM_REGISTRY_SETTINGS, @Displays()\def) )
      Debug("Store default failed")
    EndIf 
    
    Displays()\isSecondary = Bool((DisplayDevice\StateFlags & #DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) And Not(DisplayDevice\StateFlags & #DISPLAY_DEVICE_PRIMARY_DEVICE))      
    
    ; Reinit DisplayDevice just To be extra clean 
    FillMemory(@DisplayDevice, SizeOf(DisplayDevice),0)
    DisplayDevice\cb = SizeOf(DisplayDevice) 
    
    DispNum + 1
  Wend ;End While For all display devices
  
  ProcedureReturn DispNum  
EndProcedure

Procedure Display_SetCurrentActive(flag.l)
  Protected.l DispNum = 0 
  Protected.DISPLAY_DEVICE DisplayDevice
  Protected.l Result
  Protected *data
  
  Protected.DEVMODE MyDevMode
  If flag
    CopyStructure(displays()\def, MyDevMode, DEVMODE)
    ;MyDevMode\dmFields =  #DM_POSITION | #DM_PELSHEIGHT | #DM_PELSWIDTH; | #DM_DISPLAYFREQUENCY ;| #DM_DISPLAYFLAGS
  Else    
    MyDevMode\dmSize = SizeOf(DevMode) 
    MyDevMode\dmFields =  #DM_POSITION | #DM_PELSHEIGHT | #DM_PELSWIDTH
  EndIf
  Result = ChangeDisplaySettingsEx_(@displays()\name, 
                                    @MyDevMode,
                                    #Null,
                                    #CDS_UPDATEREGISTRY | #CDS_NORESET,
                                    #Null)
  
  Select result
      
    Case #DISP_CHANGE_SUCCESSFUL
      displays()\errorstring = "The settings change was successful."
      
      ;         Case #DISP_CHANGE_BADDUALVIEW
      ;           Debug "The settings change was unsuccessful because the system is DualView capable."
      
    Case #DISP_CHANGE_BADFLAGS
      displays()\errorstring = "An invalid set of flags was passed in."
      
    Case #DISP_CHANGE_BADMODE
      displays()\errorstring = "The graphics mode is Not supported."
      
    Case #DISP_CHANGE_BADPARAM
      displays()\errorstring = "An invalid parameter was passed in. This can include an invalid flag Or combination of flags."
      
    Case #DISP_CHANGE_FAILED
      displays()\errorstring = "The display driver failed the specified graphics mode."
      
    Case #DISP_CHANGE_NOTUPDATED
      displays()\errorstring = "Unable To write settings To the registry."
      
    Case #DISP_CHANGE_RESTART
      displays()\errorstring = "The computer must be restarted For the graphics mode To work. "
      
    Default
      displays()\errorstring = "Unkown :"+result
  EndSelect
  
  
  Debug PeekS(@displays()\name,32)+" "+"Result:"+displays()\errorstring
  
EndProcedure
Procedure Display_finalize()
  ChangeDisplaySettingsEx_ (#Null, #Null, #Null, 0, #Null);  
EndProcedure
Procedure Display_DisableSecondary()
  ForEach displays()
    If displays()\isSecondary
      Display_SetCurrentActive(#False)
    EndIf
  Next
  Display_finalize()
EndProcedure
Procedure Display_EnableSecondary()
  ForEach displays()
    If Not displays()\isSecondary
      Display_SetCurrentActive(#True)
    EndIf
  Next
  ForEach Displays()
    If displays()\isSecondary
      Display_SetCurrentActive(#True)
    EndIf    
  Next
  Display_finalize()  
EndProcedure


Display_Init()

MessageRequester("Test","noch sind die zweiten da!")
Display_DisableSecondary()
MessageRequester("Test","Jetzt nur noch main")
Display_EnableSecondary()
MessageRequester("Test","hoffentlich alles gut")

CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!
Antworten