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.