Zum Inhalt springen

[C#] Handles aller verfügbaren Screens ermitteln


Gateway_man

Empfohlene Beiträge

Hi leute,

gleich noch ein zweites Problem.

Ich möchte Screenshots über die WinApi machen.

Beim dem Primary Screen ist das kein Problem.

Für diesen hol ich mir das Handle über GetDesktopWindow aus der User32.dll.

Das klappt auch wunderbar.

Allerdings möchte ich auch weitere Screens supporten.

Ich bin dann auf EnumDisplayMonitors gestoßen.

Die Funktion liefert mir im Grunde schon alle Screens zurück, jedoch ist das Handle Invalid.

Ich hab das Handle meines Hauptbildschirmes das ich mit EnumDisplayMonitors mit dem Handle verglichen, das ich mit GetDesktopWindow bekomme.

Sie sind unterschiedlich (aber kein Zero).

Und wenn ich dann natürlich ein Screenshot machen möchte sagt mir GetLastError das das Handle Invalid ist.

Das ist die Klasse die mir die Informationen über alle MonitorDevices geben soll:


   public sealed class MonitorIdentifier

    {

        #region Fields

        private int counter = 0;

        private int maxDevices = System.Windows.Forms.Screen.AllScreens.Count();

        private CloneableList<ScreenDevice> availableScreens = null;

        private AsyncStateChanged asyncResult = null;

        USER32.MonitorEnumDelegate med;

        #endregion

        public MonitorIdentifier() {

            med = new USER32.MonitorEnumDelegate(EnumDisplayMonitorsCallBack);

        }

        public MonitorIdentifier(AsyncStateChanged result) 

        { 

        med =  new USER32.MonitorEnumDelegate(EnumDisplayMonitorsCallBack);

        asyncResult = result;

        if (asyncResult == null)

            throw new InvalidOperationException("AsyncResult can't be null!");

        }


        #region Public Functions

        public bool BeginEnumMonitors()

        {

            if (AsyncResult == null)

                throw new InvalidOperationException("AsyncResult can't be null!");

            else

                return USER32.EnumDisplayMonitors(IntPtr.Zero, IntPtr.Zero, med, IntPtr.Zero);

        }

        #endregion

        #region Properties

        public AsyncStateChanged AsyncResult {

            get { return asyncResult; }

            set { asyncResult = value; }

        }

        #endregion

        #region Private Functions

        private bool EnumDisplayMonitorsCallBack(IntPtr hMonitor, IntPtr hdcMonitor, ref NativeStructures.RECT lprcMonitor, IntPtr dwData){

            counter++;

            IntPtr ptr = Utillity.WinApi.USER32.GetDesktopWindow();

            NativeStructures.MonitorInfo mi = new NativeStructures.MonitorInfo();

            mi.size = (uint)Marshal.SizeOf(mi);

            bool success = USER32.GetMonitorInfo(hMonitor, ref mi);

            if (availableScreens == null)

            {

                availableScreens = new CloneableList<ScreenDevice>();

            }

            if (success) {

                ScreenDevice dev = new ScreenDevice();

                dev.mInfo = mi;

                dev.hMonitor = hMonitor;

                dev.dwData = dwData;

                dev.hdcMonitor = hdcMonitor;

                availableScreens.Add(dev);


            }


            if (counter == maxDevices) 

            {

                asyncResult.Invoke(this, new object[] { availableScreens.Clone() });

                counter = 0;

                availableScreens.Clear();

                availableScreens = null;

            }

            return success;

        }

        #endregion

    }

Das ist die ScreenDevice Structure:

    public struct ScreenDevice

    {

        #region Fields

        public Utillity.NativeStructures.MonitorInfo mInfo;

        public IntPtr hMonitor;

        public IntPtr hdcMonitor;

        public NativeStructures.RECT Rect;

        public IntPtr dwData;

        #endregion

    };

Das ist die MonitorInfo Structure:

        [StructLayout(LayoutKind.Sequential)]

        public struct MonitorInfo

        {

            public uint size;

            public RECT monitor;

            public RECT work;

            public uint flags;

        };

Die User32 Signaturen sehen bei mir so aus:

        [DllImport("user32.dll")]

        public static extern bool EnumDisplayMonitors(IntPtr hdc, IntPtr lprcClip, MonitorEnumDelegate lpfnEnum, IntPtr dwData);


        [DllImport("user32.dll")]

        public static extern bool GetMonitorInfo(IntPtr hmon, ref NativeStructures.MonitorInfo mi);

Definition des MonitorEnumDelegate:

public delegate bool MonitorEnumDelegate(IntPtr hMonitor, IntPtr hdcMonitor, ref NativeStructures.RECT lprcMonitor, IntPtr dwData);

Das AsyncStateChanged Delegate ist eigentlich nicht relevant aber falls es jemand wissen möchte wie es definiert wurde:

public delegate void AsyncStateChanged(object sender, object[] data);

Ein Beispielaufruf sieht so aus:

    public partial class Form1 : Form

    {

    private ScreenDevice dev = new ScreenDevice();

    private Utillity.Templates.CloneableList<Utillity.Devices.ScreenDevice> screens = null;

    private Utillity.Devices.MonitorIdentifier monitoridentifier = null;

        public Form1()

        {

            InitializeComponent();

            monitoridentifier = new Utillity.Devices.MonitorIdentifier(new Utillity.AsyncStateChanged(AsyncFinished));

            monitoridentifier.BeginEnumMonitors();

        }

        private void AsyncFinished(object sender, object[] data) 

        {

            if (data != null) {

                screens = (Utillity.Templates.CloneableList<Utillity.Devices.ScreenDevice>)data[0];


                //dev = screens.Where(P => P.mInfo.monitor.Left > 0).ToList()[0];

                dev = screens[1];

            }

        private void CaptureScreen()

        {

            Bitmap bmp;

            if (dev.hMonitor != IntPtr.Zero)

                bmp = (Bitmap)Utillity.ImageUtil.CaptureScreen.CaptureWindow(dev.hMonitor);

            else

                bmp = Utillity.ImageUtil.CaptureScreen.GetDesktopImage();

            if (bmp != null)

            {

                pictureBox1.Image = bmp;

            }

        }


    }


Um das Wertetechnisch hier mal zu erfassen.

Laut GetDesktopWindow hat mein Primärer Desktop das handle 65552.

Laut EnumDisplayMonitors hat mein Primärer Desktop das handle 65537.

Das handle das ich über GetDesktopWindow() ist gültig, hingegen EnumDisplayMonitors ein ungültiges Handle zurückgibt.

Hat jemand eine Idee?

lg

Gateway

Link zu diesem Kommentar
Auf anderen Seiten teilen

Das handle das ich über GetDesktopWindow() ist gültig, hingegen EnumDisplayMonitors ein ungültiges Handle zurückgibt.
Das Handle ist nicht ungültig. Es ist ein gültiges Monitor-Handle. Nur kann eine Funktion, die ein Fenster-Handle erwartet, damit einfach nichts anfangen.

Das Problem ist eigentlich die Verwendung von GetDesktopWindow, denn diese Funktion beschränkt sich selbst aus Kompatibilitätsgründen auf den Primären Monitor. Wenn du deinen Desktop auf weitere Monitore erweiterst, ist deine Desktopfläche dementsprechend größer.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ah okay.

Kennst du zufällig eine ApiFunktion mit der ich den kompletten Bildschirmbereich für das bild erfassen kann?

Ich kann ja dannach mit BitBlt den entsprechend relevanten Bereich herauskopieren.

Alternativvorschläge sind auch erwünsch :). Wichtig für mich ist, das das ganze über pInvoke geschieht.

lg

Gateway

Link zu diesem Kommentar
Auf anderen Seiten teilen

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...