Eigene Titelleiste für (Dialog)Fenster

  • WPF MVVM
  • .NET (FX) 4.5–4.8

Es gibt 42 Antworten in diesem Thema. Der letzte Beitrag () ist von kafffee.

    Eigene Titelleiste für (Dialog)Fenster

    Hallo und Guten Morgen zusammen,

    ich möchte heute mal ein Thema anschneiden, das für mehrere interessant sein könnte: Wie gesagt, eine eigene Titelleiste designen.

    Mein Ansatz:

    Im entsprechenden Fenster:

    XML-Quellcode

    1. <Grid>
    2. <Grid.RowDefinitions>
    3. <RowDefinition Height="32"/>
    4. <RowDefinition Height="*"/>
    5. </Grid.RowDefinitions>
    6. <Rectangle Grid.Row="0" Fill="Red">
    7. <Rectangle.InputBindings>
    8. <MouseBinding MouseAction="LeftClick" Command="{Binding AendereFensterPosition}"/>
    9. </Rectangle.InputBindings>
    10. </Rectangle>
    11. <ContentPresenter Grid.Row="1" Content="{Binding}"/>
    12. </Grid>


    Statt dem Rectangle könnte man auch ein Label oder sowas nehmen oder ein paar Buttons noch dazu... Das Fenster dann natürlich auf WindowStyle.None setzen.

    Ich öffne das Fenster dann über einen WindowService, in dem ich das anzuzeigende ViewModel übergebe an die Funktion, die mir auch den Handle vom Fenster zurückgibt.

    VB.NET-Quellcode

    1. Private Fenster As View.DialogFenster
    2. Public Function OeffneFenster(Breite As Integer, Hoehe As Integer, WindowName As String, DataContext As Object, Owner As Object) As IntPtr Implements ViewModel.Services.IWindowService.OpenWindow
    3. Dim MeinFenster As New View.DialogFenster(WindowName, DataContext, SizeToContent.WidthAndHeight, WindowStartupLocation.CenterScreen)
    4. MeinFenster.Owner = MeinFenster.FindOwnerWindow(Owner)
    5. Application.Current.Dispatcher.Invoke(Sub() MeinFenster.Show())
    6. Fenster = MeinFenster
    7. Dim FensterHandle As IntPtr = New WindowInteropHelper(Fenster).Handle
    8. Return FensterHandle
    9. End Function


    Und im ViewModel:

    VB.NET-Quellcode

    1. Dim LeeresVM = New ViewModel.LeeresViewModel
    2. Dim FensterHandle As IntPtr = FensterService.OpenWindow(vstInfo.editorWidth + 40, vstInfo.editorHeight + 40, "EffektVST", LeeresVM, Me)


    Jetzt kommt aber die erste Herausforderung:

    In dem Fenster soll das Plugin eines VST-Instruments oder -Effekts angezeigt werden. Das ist bereits von der bass.dll implementiert und geht so:

    VB.NET-Quellcode

    1. BassVst.BASS_VST_EmbedEditor(AngewendeteEffekte(index).Handle, FensterHandle)


    Problem ist bloss, dass mir der Editor natürlich in dem neu geöffneten Fenster nicht unter meinem Rectangle angezeigt wird sondern mitten drüber. GIbt es vielleicht eine Möglichkeit, das irgendwie in die richtige Grid-Zelle zu bugsieren oder zumindest die Position im Fenster zu bestimmen?

    Zweites Problem ist:

    Ich möchte über die Titelleiste die Fensterposition mit dem Rectangle verschieben können. Da hab ich mir gedacht, ich brauche ja bloss irgendwie auf das MouseMove-Ereignis meines Rectangles zu reagieren, dann zu checken, ob die Maustaste auch gerdückt ist, und dann das Fenster an die errechnete Position zu schieben.

    Bloss, wie komm ich an MouseMove und MouseButtonown ran, am besten noch MVVM-konform vom ViewModel aus?

    Bin gespannt auf Eure Ideen

    kafffee
    Das mit dem verschieben des Fensters ist leicht gemacht, eine Klasse mit AttachedProperties
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class AttachedMouseBehaviour
    2. Public Shared ReadOnly MouseMoveCommandProperty As DependencyProperty = DependencyProperty.RegisterAttached("MouseMoveCommand", GetType(ICommand), GetType(AttachedMouseBehaviour), New FrameworkPropertyMetadata(New PropertyChangedCallback(AddressOf MouseMoveCommandChanged)))
    3. Private Shared Sub MouseMoveCommandChanged(dependencyObject As DependencyObject, dependencyPropertyChanegdeventArgs As DependencyPropertyChangedEventArgs)
    4. Dim frameworkElement As FrameworkElement = DirectCast(dependencyObject, FrameworkElement)
    5. AddHandler frameworkElement.MouseMove, AddressOf FrameworkElement_MouseMove
    6. End Sub
    7. Private Shared Sub FrameworkElement_MouseMove(sender As Object, mouseEventArgs As MouseEventArgs)
    8. Dim frameworkElement As FrameworkElement = DirectCast(sender, FrameworkElement)
    9. Dim command As ICommand = GetMouseMoveCommand(frameworkElement)
    10. If Not command Is Nothing Then command.Execute(mouseEventArgs)
    11. End Sub
    12. Public Shared Sub SetMouseMoveCommand(element As UIElement, value As ICommand)
    13. element.SetValue(MouseMoveCommandProperty, value)
    14. End Sub
    15. Public Shared Function GetMouseMoveCommand(element As UIElement) As ICommand
    16. Return DirectCast(element.GetValue(MouseMoveCommandProperty), ICommand)
    17. End Function
    18. End Class


    Die zuweisung im XAML

    VB.NET-Quellcode

    1. <Rectangle Grid.Row="0" Fill="Red" local:AttachedMouseBehaviour.MouseMoveCommand="{Binding MouseMoveCommand}"/>


    Im Viewmodel:(Du musst über den Service für das Fenster an das Handle kommen!)

    VB.NET-Quellcode

    1. Public Property MouseMoveCommand As RelayCommand
    2. Public Sub New()
    3. MouseMoveCommand = New RelayCommand(Function(o) True, Sub(o) OnMouseMove())
    4. End Sub
    5. Private Sub OnMouseMove()
    6. Dim svc As MainWindowService = DirectCast(ApplicationServices.GetService(Of IMainWindowService), MainWindowService)
    7. If svc Is Nothing Then Return
    8. Dim handle As IntPtr = svc.Gethandle()
    9. If handle <> IntPtr.Zero Then
    10. NativeMethods.ReleaseCapture()
    11. NativeMethods.SendMessage(handle, NativeMethods.WM_NCLBUTTONDOWN, NativeMethods.HT_CAPTION, 0)
    12. End If
    13. End Sub


    Dazu noch die NativeMethods:

    VB.NET-Quellcode

    1. Imports System.Runtime.InteropServices
    2. Public Class NativeMethods
    3. Public Const WM_NCLBUTTONDOWN As Integer = &HA1
    4. Public Const HT_CAPTION As Integer = &H2
    5. <DllImport("user32.dll", CharSet:=CharSet.Auto)>
    6. Public Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As IntPtr
    7. End Function
    8. <DllImport("user32.dll")>
    9. Public Shared Function ReleaseCapture() As Boolean
    10. End Function
    11. End Class
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D
    Man kann auch einen Schritt weitergehen und – statt einer Zeile – ein ganzes DialogFenster, Input- oder MessageBox selbst entwerfen und zum Leben erwecken – man muss dann nichts aus dem Standardrepertoire mehr oder weniger „hacken” und ist in der Gestaltung ganz frei. Auf dem Screenshot ist das die grüne Box im ShowDialogmodus geöffnet, die jederzeit mit der Maus verschoben und der gesamte Inhalt dynamisch, z.B. umschaltbar aus einem Hintergrundthread, in drei Sprachen angezeigt bzw. sofort geändert werden kann. Bilder und noch andere Elemente sind hier auch schon integriert, bei dieser einfachen Eingabe der Baudrate als Zahl aber designmäßig versteckt, nicht sichtbar. Eine explizite, selbstentworfene Titelleiste mit Icon(s) hat die Box auch, ist aber hier auch absichtlich ausgeblendet, sofort schließen geht auch mit ESC - kann man aber bei Bedarf alles mit einem kurzen Befehl zuschalten oder den Inhalt – samt Text – ändern oder anpassen. Mittels Vererbung nicht nur als Input-, sondern auch als Info- oder ErrorBox verwendbar - verschiedene Versionen sind dann als Ableitung in der Regel schnell erledigt.
    Bilder
    • MyInputBox_1.png

      47,52 kB, 632×565, 65 mal angesehen
    Das gleichzeitige Erscheinen von Dummheit und Unmündigkeit nach Immanuel Kant ist eines der schlimmsten Dinge, die einem Homo sapiens in geistiger Hinsicht widerfahren können, hat manchmal aber auch durchaus seine Vorteile.
    Ja, zumindest würde ich ein eigenes FrameworkElement für eine Titelleiste machen. Dann spart man sich das Verschieben mit den API-Funktionen in den ViewModels und hat das nicht redundant in mehreren ViewModels.
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D
    Man kann selbstverständlich auch solche merkwürdigen – runden, elliptischen – Fenster kreieren, ist aber für mein Empfinden etwas zu altbacken (altmodisch). Abgerundete Ecken würden vielleicht noch einigermaßen etwas Modernes vermitteln, passt aber optisch eh in mein Gesamtkonzept nicht sonderlich hinein. Na wie auch immer, es ist letzendlich alles nur eine Sache des Geschmacks und des Könnens des Autors, was da am Ende so auf dem Bildschirm stehenbleibt – oder sich gar von einem Rechteck in eine Ellipse dynamisch vor Augen des Betrachters beim Öffnen in einer kurzen Animation verwandelt. Dieser Screenshot ist in der Skalierung etwas kleiner und richtigerweise in 100% gemacht, der vorherige war mit Windowsskalierung auf 125% erstellt worden. Die ganzen Skalierungen oder Bildschirmauflösungen sollte man beim Schreiben natürlich auch mal durchspielen/testen, aber bei WPF ist das nicht so tragisch wie es bei WinForms der Fall war.
    Bilder
    • MyInputBox_Ellipse.png

      38,28 kB, 554×431, 57 mal angesehen
    Das gleichzeitige Erscheinen von Dummheit und Unmündigkeit nach Immanuel Kant ist eines der schlimmsten Dinge, die einem Homo sapiens in geistiger Hinsicht widerfahren können, hat manchmal aber auch durchaus seine Vorteile.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Gregor Jasinski“ ()

    @DTF

    Bin gerade am Ausprobieren deines Quellcodes, aber an folgender Stelle meckert er:

    VB.NET-Quellcode

    1. MouseMoveCommand = New RelayCommand(Function(o) True, (o) OnMouseMove())


    Die Signatur des geschachtelten Sub ist nicht mit dem Delegaten "Prredicate(Of Object)" kompatibel.

    Weisst du vielleicht was da nicht stimmt, ich kann mit diesem Fehler nix anfangen...


    Gregor Jasinski schrieb:

    Man kann auch einen Schritt weitergehen und – statt einer Zeile – ein ganzes DialogFenster, Input- oder MessageBox selbst entwerfen und zum Leben erwecken

    Wenn ich das Gleiche meine wie du, dann hab ich das schon 8o , zumindest so in der Art...
    Ich benutze mein DialogFenster für jegliche Art von Dialogen in meinem Programm. Ich übergebe beim Öffnen ein ViewModel und dann hab ich in der Application.xaml dann eine View zugeordnet, die dann angezeigt wird...

    DTF schrieb:

    Ja, zumindest würde ich ein eigenes FrameworkElement für eine Titelleiste machen.

    Ist das was Grösseres? Wie macht man sowas? Kann man damit evtl. auch mein zweites Problem lösen? D.h. dass das was mir diese Funktion liefert:

    VB.NET-Quellcode

    1. BassVst.BASS_VST_EmbedEditor(AngewendeteEffekte(index).Handle, FensterHandle)


    Dass ich das im Fenster frei platzieren kann und es nicht einfach über meiner View obendrüber angezeigt wird?

    kafffee schrieb:

    Bin gerade am Ausprobieren deines Quellcodes, aber an folgender Stelle meckert er:


    Es reicht nicht den Namen der Funktion anzugeben, ich nutzte eine Anonyme Sub in der die genannte Sub aufgerufen wird. Du hast das "Sub" vergessen.

    VB.NET-Quellcode

    1. New RelayCommand(Function(o) True, Sub(o) OnMouseMove())


    kafffee schrieb:

    Ist das was Grösseres? Wie macht man sowas?

    Dazu habe ich heute hier etwas geschrieben, so machst du ein eigenes FrameworkElement.
    Selberstellte Grafik in WPF

    Die ganze Sache zum Verschieben kommt in diese Klasse, ein Paar DependencyProperties dazu für Command-Binding damit im ViewModel bescheid gegeben werden kann, wenn minimiert, maximiert oder geschlossen werden soll. Kann man in 10-15 Minuten mit einer Tasse Kaffee schaffen. Mit ein wenig mehr Aufwand könnte man sich noch ein Paar extra Features einbauen, so das man Buttons oder so in der Titelleiste platzieren kann.

    Beim letzen Punkt mit dem VST, da bin ich nicht sicher. Was genau macht diese Funktion?
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D
    Die Funktion ruft das Userinterface eines VSTs auf, also quasi ein Audioeffekt oder Instrunent, das als VST(*.dll) vorhanden ist. Erstes Argument ist der Handle eines Audiostreams, zweites Argument der Handle des Fensters in dem das UI angezeigt werden soll.

    Ich guck mir deinen Link mal an, aber ich befürchte in 15 min werde ich damit nicht durch sein. Egal wenn ich Fragen hab meld ich mich nochmal... :)
    Also mit dieser Funktion wird eine Art Steuerelement erstellt. Steuerelemente müsstest du mit diesem Code(API Funktionen) auch verschieben können, ansonsten kann man aber auch mit MouseDown+MouseUp+MouseMove arbeiten.
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    kafffee schrieb:

    (...) Ich benutze mein DialogFenster für jegliche Art von Dialogen in meinem Programm. Ich übergebe beim Öffnen ein ViewModel und dann hab ich in der Application.xaml dann eine View zugeordnet, die dann angezeigt wird...

    Das im ersten Satz mache ich ähnlich wie Du, die Ähnlichkeiten enden dann mit dem Beginn des zweiten Satzes abrupt, ich brauche keine „ViewModelle und Views” nach Dogma X oder Y, um das Fenster zu öffnen, zu verändern oder mit ihm zu kommunizieren – die Dogmatiker würden hier reihenweise einen Anfall bekommen (Peng! Peng! Peng! Einer nach dem anderen), wenn sie erfahren und sehen würden, wie einfach die Dinge gemacht werden können - was ich quasi intuitiv in der Regel auch so mache ; )
    Das gleichzeitige Erscheinen von Dummheit und Unmündigkeit nach Immanuel Kant ist eines der schlimmsten Dinge, die einem Homo sapiens in geistiger Hinsicht widerfahren können, hat manchmal aber auch durchaus seine Vorteile.

    DTF schrieb:

    Du hast das "Sub" vergessen.


    Ah okay. Aber da kommt immer noch der gleiche Fehler...

    DTF schrieb:

    Steuerelemente müsstest du mit diesem Code(API Funktionen) auch verschieben können

    Wie mach ich das? Das ist absolutes Neuland für mich... Idealfall wäre es natürlich das in einer Grid Zelle zu platzieren...

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „kafffee“ ()

    Anstatt ein Window-Handle, ein Control-Handle an die Funktion übergeben in WPF sollten die Controls auch eins haben.

    Aber mit der TitelLeiste ist doch ein wenig mehr als 15 Minuten. Ich dachte mir das kann ich auch gebrauchen, hab mich deshalb auch drangesetzt, das funktionert zum Teil schon, also das mit dem Verschieben des Fensters. Was aber noch nicht geht, das die Größe der Grid Row/Column übernommen wird(bzw. des Parents), ich denke man wird zusätzlich noch ein ControlTemplate anlegen müssen. Aber da schau ich morgen erst weiter.
    @Gregor Jasinski Weist du zufällig was darüber? Liege ich richtig mit dem Template?

    Edit, Ja das mit dem ControlTemplate scheint es zu sein. Geht in die richtige Richtung, was mir nun noch nicht gefällt, das ich das Template in den App-Resource bekannt machen muss. Mal schauen ob man das auch im Konstruktor der Klasse laden kann.

    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „DTF“ ()

    DTF schrieb:

    @Gregor Jasinski Weist du zufällig was darüber? Liege ich richtig mit dem Template? (...)

    Also, ich weiß, dass bei mir alles wunderschön funktioniert – Titelleiste, verschieben, verändern der Größe, ein-/ausblenden einzelner Elemente in der Box usw, hier noch ein Screenshot mit der provisorischen Titelleiste, denn noch ist es nicht akut, diese tatsächlich in dieser Anwendung verwenden zu müssen – vielleicht kommt es aber noch, weil ich an der Applikation noch schreibe. Ich habe vor zwei Wochen auch mal spaßhalber aus einem Hintergrundthread ein Stück Code als Test geschrieben, um die Sprache der ganzen Anwendung im Sekundentakt zu wechseln – der Wechsel vollzieht sich automatisch in jedem (sic!) Fenster in diesem Takt, egal, ob in der Front ein Dialogfenster geöffnet ist oder nicht, und es ist auch egal, wie viele Fenster gerade sichtbar sind; auch in dem Dialogfenster selbst ändert sich alles – sowohl die Textinhalte als auch die Texte auf den Buttons, in den Menüs etc, denn das zu ändern gehört natürlich auch dazu. Ich weiß allerdings nicht, ob Du mit dem, was Du da versuchst, richtig oder falsch liegst, weil ich die ganzen Details nicht kenne und mich mit diesen aber auch nicht auseinandersetzen möchte – wie ich schon sagte, viele machen alles nach irgendwelchen Dogmen und dadurch viel zu umständlich, am Ende hat man oft so einen Kuddelmuddel kreuz und quer in den Codedateien, dass man selbst nicht mehr weiß, wo, was, wie zusammengehört und/oder -arbeitet; und manchmal weiß man am Ende auch nicht, warum es eigentlich arbeitet, falls es tatsächlich mal arbeitet. Um einen Apfel für einen Apfelkuchen zu wiegen, muss man ihn nicht verpacken und in ein Labor schicken, man kann auch eine Küchenwaage nehmen. Wer's genauer haben will, kann auch eine Briefwaage nehmen. Es ist darüberhinaus meistens auch noch ressourcenschonender, performanter und vor allem sehr sicher, dass der Apfel unterwegs nicht verloren geht, falls irgendwo in dieser Kette etwas schieflaufen sollte, was ja gelegentlich passiert.
    Bilder
    • MyInputBox_1+TL.png

      86,71 kB, 1.013×763, 61 mal angesehen
    Das gleichzeitige Erscheinen von Dummheit und Unmündigkeit nach Immanuel Kant ist eines der schlimmsten Dinge, die einem Homo sapiens in geistiger Hinsicht widerfahren können, hat manchmal aber auch durchaus seine Vorteile.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Gregor Jasinski“ ()

    Gregor Jasinski schrieb:

    am Ende hat man oft so einen Kuddelmuddel kreuz und quer in den Codedateien,


    Exakt, das habe ich ja vor zu vermeiden. Deshalb habe ich vor das im Konstruktor irgendwie zu laden, nahezu jeder Entwickler der MVVM anwendet hat ja ein Projekt mit seinen Basics(Service-Interfaces, eine Klasse die INotifyPropertyChanged implementiert etc..). Da ist ein weiterer NameSpace mit CustomControls immer noch übersichtlich. Wenn dann das Template im Kontruktor geladen wird, so das man es nicht irgendwo im XAML bekannt machen muss, ist das doch optimal(Solange man das dann noch von außen überschreiben kann bei Bedarf). Evtl. macht es bei der Titelleist doch Sinn eine fixe höhe zu nehmen, dann spar ich das Template. Aber lernen will ich das denn doch, kann das irgendwie nicht so stehen lassen.

    Den Umstieg zu WPF hatte ich mir letzes Jahr leichter vorgestellt, aber immerhin, die Grundlagen scheine ich bald drauf zu haben.
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D
    Ich hab mal ein bisschen gegoogelt. Das einzige Control was wohl anscheinend einen Handle bekommt scheint das Popup zu sein. Das wär ja super und würde völlig reichen bei mir...
    Folgendes hab ich gefunden, aber wie binde ich das in meine MVVM Applikation ein?:

    stackoverflow.com/questions/78…nd-of-a-wpf-popup-control
    Das hab ich mal auspropiert, habe einfach mal verschiedene Controls auf einem Grid platziert, kommt immer das gleiche Handle. 8| Sogar das vom Grid ist das gleiche.

    Hab auch das mit dem PopUp probiert, da bekam ich verschiedene Handles.(Mehere PopUps) Um das WVVM konform zu machen wüsste ich nur das in den Service für das Window einzubauen. Da hast du ja die Window-Instanz und kannst so an das Popup kommen.

    C#-Quellcode

    1. public interface IMainWindowService : IWindowService
    2. {
    3. IntPtr GetPopUpChildHandle();
    4. }

    C#-Quellcode

    1. public class MainWindowService : IMainWindowService
    2. {
    3. MainWindow window;
    4. //........
    5. public IntPtr GetPopUpChildHandle()
    6. {
    7. IntPtr hwnd = ((HwndSource)PresentationSource.FromVisual(window.PopUp1.Child)).Handle;
    8. return hwnd;
    9. }
    10. //..........
    11. }


    Edit: Aber ich denke du wirst das PopUp verschieben müsen, den sonst verschiebt du das COntrol auf dem Popup wenn das denn überhaupt Funktioniert.
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „DTF“ ()

    Ja das sieht doch nach was aus :)

    Wichtig ist eben auch, dass mehrere offen sein müssen und sich dann nicht ins Gehege kommen, aber das scheint ja gegeben zu sein.

    Und natürlich, klar, man muss sie definitiv verschieben können, meinst du das geht nicht auch mit dem Code aus deinem ersten Post? Ich glaube der Fehler den ich da bekomme hängt damit zusammen dass ich ein falsches Argument übergebe oder dass eins fehlt da scheint es zwei Überladungen zu geben.

    Aber du wolltest ja glaub eh das Frameworkelement machen, da warte ich einfach mal ab, denn das mit den DLL Imports da hab ich ehrlich keine Ahnung von....

    Beziehungsweise man könnte evtl. sogar das MouseMove Element vom Rectangle nehmen mit ist grad eingefallen wie das gehen könnte....

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „kafffee“ ()

    kafffee schrieb:

    Ich glaube der Fehler den ich da bekomme hängt damit zusammen dass ich ein falsches Argument übergebe oder dass eins fehlt da scheint es zwei Überladungen zu geben.


    Mit den verschiedenen Überladungen meinst du welche Funktion? Ohne zu wissen was du gemacht hast, kann ich nichts dazu sagen, ich habe keine Code gesehen.

    Ich werde morgen(schon so spät 8| ) im Laufe des Tages weitermachen und dann eine Mappe hochladen, mit der kannst du dann Experimentieren. Ich hoffe du kommst mit C# klar.

    kafffee schrieb:

    denn das mit den DLL Imports da hab ich ehrlich keine Ahnung von....


    In Net/NetFX brauchen wir halt die DllImporte, die API-Funktionen sind in DLLs von Windows. In C++ kann man die so aufrufen, weil die Definitionen dazu in den inkludierten Headern sind, welche uns nicht viel nutzen in Net/NetFX. Ausser das wir neben der MS-Doku noch weiteres recherchieren können. Falls du lernen willst damit umzugehen lerne C++, das wäre m.M.n. der einfachste Weg.
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    kafffee schrieb:

    Eigene Titelleiste für (Dialog)Fenster
    Ich bin da etwas unbeleuchtet, wenn man mit Window-Handles hantiert.
    ist mir unangenehm nahe am Betriebssystem, sind keine vernünftigen Datentypen, und nach meiner Erfahrung gerne für schlecht zu debuggende Abstürze gut.
    Kann man nicht bei Wpf bleiben?
    Versuchma ein Canvas aufs Window zu tun, und in das Canvas ein RectAngle, bei dem du Top=-50 setzst.
    Da müsste sich das Rectangle über den Window-Titel legen.
    Leute ich hab die Lösung, einfacher gehts nicht:

    VB.NET-Quellcode

    1. Imports System.Windows.Interop
    2. Public Class PlugInWindow
    3. Private Sub TitelLeiste_MouseLeftButtonDown(sender As Object, e As MouseButtonEventArgs)
    4. DragMove()
    5. End Sub
    6. End Class


    Ist halt Code Behind...

    Nur den Handle vom Popup zu bekommen ist nicht so leicht. Ich hab in meinem Service das hier:

    VB.NET-Quellcode

    1. Namespace Services
    2. Public Class WindowService
    3. Implements ViewModel.Services.IWindowService
    4. Private _win As View.SpsWindow
    5. Public PlugInFenster As View.PlugInWindow
    6. Public PopUpHandle As IntPtr
    7. Public Function OeffnePlugInFenster(FensterTitel As String, Hoehe As Integer, Breite As Integer, DataContext As Object, Owner As Object) As IntPtr Implements ViewModel.Services.IWindowService.OeffnePlugInFenster
    8. PlugInFenster = New View.PlugInWindow()
    9. PlugInFenster.Title = FensterTitel
    10. PlugInFenster.Height = Hoehe
    11. PlugInFenster.Width = Breite
    12. PlugInFenster.DataContext = New ViewModel.PlugInWindowViewModel(FensterTitel)
    13. PopUpHandle = ((HwndSource)PresentationSource.FromVisual(PlugInFenster.MeinPopUp.Child)).Handle
    14. Application.Current.Dispatcher.Invoke(Sub() PlugInFenster.Show())
    15. Return New WindowInteropHelper(PlugInFenster).Handle
    16. End Function


    Da kommt der Fehler '"HwndSource" ist ein Klassentyp und kann nicht als Ausdruck verwendet werden in Zeile 15.

    Und wenn ich das mache:

    VB.NET-Quellcode

    1. PopUpHandle = New WindowInteropHelper(PlugInFenster.MeinPopUp.Child).Handle


    Dann kommt:

    "PlugInWindowTest.view.PlugInWindow.MeinPopUp" ist "Friend" und in diesem Kontext nicht zugreifbar.

    Müsst ihr mal ausprobieren, ich komm da nicht weiter :)

    Edit:
    Das Windows-Loaded-Ereginis des PlugInWindows zu abonnieren und dann die Property im Service setzen, geht auch nicht, da kommt der Fehler "darf nicht null sein". Wahrscheinlich weil das Popup noch nicht initialisiert wurde:

    VB.NET-Quellcode

    1. Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs)
    2. FensterService.PopUpHandle = New WindowInteropHelper(MeinPopUp.Child).Handle
    3. End Sub

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „kafffee“ ()