Form andocken - und von der WorkArea ausschliessen



  • Abend Leute ...

    Für meine Anwendung habe ich mir überlegt eine Sidebar Ansicht darzustellen, welche auf dem Desktop verankert ist - und von anderen Anwendungen nicht überdeckt werden sollte. Eben so wie es die meisten Sidebars können. Leider klemmt es irgendwie an der durchführung - wo auch sonst 🙂

    void Kinder::Sidebar::sidebarandocken ()
    	{
    	this->TopMost = true;
    	RECT rc1;
    	rc1.right  = GetSystemMetrics (SM_CXSCREEN) - this->Size.Width;
    	rc1.bottom = this->Height;
    	rc1.left   = 0;
    	rc1.top	   = 0;
    
    	SystemParametersInfo (SPI_SETWORKAREA, 0, &rc1, 0); 
    	this->Invalidate ();
    	}
    

    Was muss ich hier noch machen, damit sich keine Anwendungen über diese Legen.



  • Ich habe hierzu ein Snippet gefunden, allerdings in C#.

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    
    namespace WindowsApplication1
    {
        /// <sumary>
        /// Beinhaltet Information über die Application Bar.
        /// Eine ausführliche Beschreibung finden Sie in MSDN APPBARDATA Dokumentation.
        /// </sumary> 
        [StructLayout(LayoutKind.Sequential)]
        public struct APPBARDATA
        {
            public uint cbSize;
            public IntPtr hWnd;
            public uint uCallbackMessage;
            public uint uEdge;
            public RECT rc;
            public int lParam;
        }
        /// <sumary>
        /// Speichert Größe und Position der AppBAr.
        /// </sumary>
        [StructLayout(LayoutKind.Sequential)]
        public struct RECT
        {
            public int left;
            public int top;
            public int right;
            public int bottom;
        }
        public partial class Form1 : Form
        {
            const int ABM_NEW         = 0x00000000;
            const int ABM_REMOVE      = 0x00000001;
            const int ABM_SETPOS      = 0x00000003;
            const int ABM_QUERYPOS    = 0x00000002;
    
            const int ABE_TOP = 1;
    
            public Form1()
            {
                InitializeComponent();
                FormBorderStyle = FormBorderStyle.SizableToolWindow;
            }
            /// <sumary>
            /// OnLoad wird überschrieben, um die ApplicationBar zu initialisieren.
            /// Dabei wird am oberen Rand des Desktops ein Bereich reserviert, in dem das Fenster dann platziert wird.
            /// </sumary>
            protected override void OnLoad(EventArgs e)
            {
                base.OnLoad(e);
    
                // Datenstruktur für AppBar erzeugen und initialisieren.
                APPBARDATA abd = new APPBARDATA();
                abd.cbSize = (uint)Marshal.SizeOf(typeof(APPBARDATA));
                abd.hWnd = this.Handle;
                abd.uCallbackMessage = RegisterWindowMessage(Guid.NewGuid().ToString()); 
    
                // AppBar beim System registrieren.
                SHAppBarMessage(ABM_NEW, ref abd);
    
                // Größe und Position festlegen.
                // In dem Beispiel wird oben am Desktop 100 Pixel Platz reserviert.
                abd.rc = new RECT();
                abd.uEdge = ABE_TOP;
                abd.rc.top = 0;
                abd.rc.left = 0;
                abd.rc.bottom = 100;
                abd.rc.right = SystemInformation.PrimaryMonitorSize.Width;
    
                // Die Gröse und Position der AppBar prüfen.
                // Wenn diese nicht gültig sind, werden die 
                // korrigierte Werte zurückgegeben.
                SHAppBarMessage(ABM_QUERYPOS, ref abd);
                // Größe und Position der AppBarsetzen
                SHAppBarMessage(ABM_SETPOS, ref abd);
                // Größe und Position des Anwendungsfenster im AppBar Bereich positionieren
                Location = new Point(abd.rc.left, abd.rc.top);
                Size = new Size(abd.rc.right, abd.rc.bottom);
            }
    
            /// <sumary>
            /// Beim Beenden des Programms wieder aufräumen.
            /// </sumary>
            protected override void OnClosed(EventArgs e)
            {
                APPBARDATA abd = new APPBARDATA();
                abd.cbSize = (uint)Marshal.SizeOf(typeof(APPBARDATA));
                abd.hWnd = this.Handle;
    
                SHAppBarMessage(ABM_REMOVE, ref abd);
    
                base.OnClosed(e);
            }
            [DllImport("shell32.dll")]
            static extern IntPtr SHAppBarMessage(uint dwMessage,
               ref APPBARDATA pData);
            [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
            static extern uint RegisterWindowMessage(string lpString);
        }
    }
    

    Leider muss ich zugeben, dass mir das noch eine Nummer zu hoch ist - um es alleine umzusetzen. Jemand langeweile - um mich zu unterstützen?



  • Hier hänge ich im Moment, da ich mit Pointern noch nicht wirklich zurecht komme:

    namespace Kinder {
    
    	struct APPBARDATA
    		{
    		UINT cbSize;
    		IntPtr hWnd;
    		UINT uCallbackMessage;
    		UINT uEdge;
    		RECT rc;
    		int lParam;
    		} *PAPPBARDATA;
    
    	struct RECT
    		{
    		int left;
    		int top;
    		int right;
    		int bottom;
    		};
    
    virtual void OnLoad(System::EventArgs^  e) override
    				{
    				String ^message; // <-- von System::String zu LPCSTR
    				LPCSTR mess = nullptr;
    
    				APPBARDATA *abd = new APPBARDATA();
    				abd->cbSize = sizeof (APPBARDATA);
    				abd->hWnd = this->Handle;
    
    				System::Guid ^guid = gcnew System::Guid ();
    				message = guid->NewGuid().ToString();
    				mess = (LPCTSTR)(System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(message).ToPointer());
    				abd->uCallbackMessage = RegisterWindowMessage(mess);				
    
    				SHAppBarMessage(ABM_NEW, abd);
    
    Fehler	1	error C2664: 'SHAppBarMessage': Konvertierung des Parameters 2 von 'Kinder::APPBARDATA' in 'PAPPBARDATA' nicht möglich	c:\users\jan\documents\visual studio 2008\projects\kinder\kinder\Sidebar.h	143
    

    SHAppBarMessage fordert einen doch einen Pointer auf die APPBARDATA Struktur ?! Mir fehlt es hier einfach an können.



  • Kann mir wirklich keiner weiterhelfen?

    String ^message; 
    	LPCSTR mess = nullptr;	
    	APPBARDATA	*abd	= new APPBARDATA();	
    	PAPPBARDATA	*pabd	= new PAPPBARDATA();
    
    	System::Guid ^guid = gcnew System::Guid ();
    	message = guid->NewGuid().ToString();
    	mess = (LPCTSTR)(System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(message).ToPointer());
    	HWND hwnd = (HWND)this->Handle.ToPointer();	
    
    	abd->rc.bottom	= rc1.bottom;
    	abd->rc.left	= this->Location.X - this->Size.Width;
    	abd->rc.right	= rc1.right;
    	abd->rc.top		= 0;
    	abd->uEdge		= 1;
    	abd->uCallbackMessage = RegisterWindowMessage(mess);
    	abd->hWnd = hwnd;
    	abd->cbSize = sizeof (abd);					
    
    	SHAppBarMessage(ABM_NEW, *pabd );
    

    ... ich komme einfach nicht dahinter, was SHAppBarMessage von mir will.

    Fehler	1	error C2664: 'SHAppBarMessage': Konvertierung des Parameters 2 von 'Kinder::PAPPBARDATA' in 'PAPPBARDATA' nicht möglich
    

    Das Struct Appbardata ist doch im gleichen Namespace deklariert.

    typedef struct _AppBarData 
    		 {
    	     DWORD cbSize;
    	     HWND hWnd;
    	     UINT uCallbackMessage;
    	     UINT uEdge;
    	     RECT rc;
    	     LPARAM lParam;
    		} APPBARDATA, *PAPPBARDATA;
    


  • Das Ende vom Lied ist nun, dass das ganze völliger Quatsch ist:

    fensterminimieren ();
    
    	RECT standard,rc2;
    	SystemParametersInfo(SPI_GETWORKAREA, 0, &standard, 0);	
    
    	registryhilfe::regdaten::auflösungx = standard.right;
    	registryhilfe::regdaten::auflösungy = standard.bottom;
    
    	this->Height	= standard.bottom;	
    	this->Location = System::Drawing::Point (standard.right - this->Size.Width, 0);
    
    	rc2.bottom = standard.bottom;
    	rc2.left   = 0;
    	rc2.right  = this->Location.X;
    	rc2.top	   = 0;
    
    	SystemParametersInfo (SPI_SETWORKAREA, 0, &rc2, 0);
    	this->Invalidate ();
    

    ...das tuts auch. Hätte ich mal auf mein Bauchgefühl gehört.


Anmelden zum Antworten