AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi SPI_SETDRAGFULLWINDOWS, aber nur für eigene Anwendung
Thema durchsuchen
Ansicht
Themen-Optionen

SPI_SETDRAGFULLWINDOWS, aber nur für eigene Anwendung

Ein Thema von Bernhard Geyer · begonnen am 14. Sep 2016 · letzter Beitrag vom 14. Sep 2016
Antwort Antwort
Benutzerbild von Bernhard Geyer
Bernhard Geyer

Registriert seit: 13. Aug 2002
17.170 Beiträge
 
Delphi 10.4 Sydney
 
#1

SPI_SETDRAGFULLWINDOWS, aber nur für eigene Anwendung

  Alt 14. Sep 2016, 13:34
Ich würde gerne für die eigene Anwendung das Feature "Full Window Drag" deaktivieren.
Finde aber bisher nur lösungen um über das Setzen von SPI_SETDRAGFULLWINDOWS diese Systemweit einzustellen
Windows Vista - Eine neue Erfahrung in Fehlern.
  Mit Zitat antworten Zitat
Benutzerbild von mael
mael

Registriert seit: 13. Jan 2005
391 Beiträge
 
Delphi XE3 Professional
 
#2

AW: SPI_SETDRAGFULLWINDOWS, aber nur für eigene Anwendung

  Alt 14. Sep 2016, 14:33
Ich glaube nicht dass das zuverlässig funktioniert, wenn man nicht selbst den Drag-Code implementiert. Vom Systemdesign (Windows) her ist es nicht vorgesehen, dass je nach Programm einzustellen. Alle Einstellungen die das irgendwie hinbiegen wären dann unzuverlässige Hacks.

Das selber zu implementieren ist auch nicht ganz trivial. Ansätze wären wohl die Window Messages: WM_NCLBUTTONDOWN und WM_NCHITTEST (und verwandte Non-Client-Area-Nachrichten).

In WM_NCLBUTTONDOWN und Co. könnte man dann die Nachricht nicht an DefWindowProc() weiterleiten um somit den Windows-eigenen Drag-Drop-Prozess zu verhindern. Ob das auch die Option abfängt, über die Tastatur ein Fenster zu verschieben, wäre zu testen.

Man könnte dann selbst ein Drag-Rechteck auf den Bildschirm zeichnen und wieder löschen, mit XOR-Operationen oder sowas wie DrawFocusRect(). Vielleicht gibt es auch noch etwas bei Multi-Monitor-Konfigurationen zu beachten.


Der Aufwand einer korrekten Implementierung ist beträchtlich, und unter neueren Windows-Versionen (mindestens ab Vista, wahrscheinlich auch XP) ist das Verschieben eines Fensters eh per Grafikkarte beschleunigt, daher die Frage:
Welches Problem soll das lösen?


P.S.: Hier ist ein Ansatz für das Resizen eines Fensters: http://stackoverflow.com/questions/2...aying-my-c-sha

Würde es aber nicht empfehlen, weil das ein unzuverlässiger Hack ist der sich auf undokumentierte Implementierungsdetails verlässt die sich ändern können. Außerdem könnte ein Abstürzen oder sonstiger Fehler in deinem Programm dann alle Programme beeinflussen (also immer das Drag-Rectangle anzeigen).
HxD, schneller Hexeditor:
http://mh-nexus.de/hxd

Geändert von mael (14. Sep 2016 um 14:43 Uhr)
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#3

AW: SPI_SETDRAGFULLWINDOWS, aber nur für eigene Anwendung

  Alt 14. Sep 2016, 15:50
Klar geht das

Delphi-Quellcode:
function TMagnetic.SetFullWindowDrag(HWND: DWORD; ShowFullWindow: Boolean): Boolean;

// Aktiviert oder deaktiviert die Anzeige von Fensterinhalten während des
// Ziehens oder der Größenänderung von Anwendungsfenstern.
// Der Rückgabewert gibt Aufschluss darüber, ob der Aufruf zu einer Änderung
// gegenüber der vorherigen Einstellung geführt hat (True) oder nicht (False).

begin
  // Bisherige Einstellung ermitteln:

  result := SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, @lOldSetting, 0);
  if result = false then
    // Result := False;
    // Der abfragende Aufruf war nicht erfolgreich
    // (z.B. Windows 95 ohne "PLUS!"-Pack).
    exit; // Rückgabewert bleibt False

  // Eine Aktion ist nur dann notwendig, wenn sich der bisherige
  // vom gewünschten Wert unterscheidet:
  if Bool(lOldSetting) <> ShowFullWindow then
    // Wert ändern und Erfolg prüfen:
    result := SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, Abs(DWORD(ShowFullWindow)), nil,
      SPIF_UPDATEINIFILE or SPIF_SENDWININICHANGE);

end;
mach mein TMagnetic wech dann sollte das funktionieren.

Zitat:
In WM_NCLBUTTONDOWN und Co. könnte man dann die Nachricht nicht an DefWindowProc() weiterleiten um somit den Windows-eigenen Drag-Drop-Prozess zu verhindern. Ob das auch die Option abfängt, über die Tastatur ein Fenster zu verschieben, wäre zu testen.
Sorry das ist schlichtweg falsch.

Delphi-Quellcode:
{$REGION 'WM_ENTERSIZEMOVE'}
    WM_EXITSIZEMOVE:
      begin
        if FullDrag then
          SKAERO_MagneticWindow.SetFullWindowDrag(MainApp.Handle, False);
      end;
{$ENDREGION}
Delphi-Quellcode:
{$REGION 'WM_NCLBUTTONDOWN'}
    WM_NCLBUTTONDOWN:
      begin
        IsMoving := TRUE;
        if (wP = HTCAPTION) and FullDrag then
          SKAERO_MagneticWindow.SetFullWindowDrag(MainApp.Handle, True);
      end;
{$ENDREGION}
Zitat:
weil das ein unzuverlässiger Hack ist
Das hat nichts mit einem Hack zu tun.. ich verwende das schon seit Jahren und hatte keine Probleme.
Man muss es nur richtig machen.

Aber ja nebenbei du kannst es deaktivieren aber mit meiner Anwendung würde es wieder aktiviert.
Also eine Dauerhafte Möglichkeit das Auszuschalten wirst du nicht finden.

gruss

Geändert von EWeiss (14. Sep 2016 um 15:59 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von mael
mael

Registriert seit: 13. Jan 2005
391 Beiträge
 
Delphi XE3 Professional
 
#4

AW: SPI_SETDRAGFULLWINDOWS, aber nur für eigene Anwendung

  Alt 14. Sep 2016, 18:41
Klar geht das
Ich habe doch selbst auf ähnlichen Code verlinkt, und erklärt warum es Probleme damit geben kann und das unsauber ist. Die Kommentare in dem Link sagen ähnliches.


Zitat:
Zitat:
In WM_NCLBUTTONDOWN und Co. könnte man dann die Nachricht nicht an DefWindowProc() weiterleiten um somit den Windows-eigenen Drag-Drop-Prozess zu verhindern. Ob das auch die Option abfängt, über die Tastatur ein Fenster zu verschieben, wäre zu testen.
Sorry das ist schlichtweg falsch.
Vielleicht missverstanden (siehe triviales Beispiel unten). Wenn man die entsprechenden Window-Messages abfängt, wird natürlich kein Drag&Drop eingeleitet, da Windows nie mitbekommt dass man die Maustaste auf der Titelleiste gedrückt hält.
Der Sinn dahinter ist, dass man dann selber ein eigenes Drag&Drop implementieren kann, ohne sich mit der Windows-eigenen Implementierung zu verheddern.
Ein Test zeigt auch dass Alt+Leertaste|Verschieben und Verwenden der Pfeiltasten zum Verschieben noch funktioniert.
Also das was ich gesagt habe...

Beispiel, einfach eine neue VCL-Anwendung erstellen, dann den Quelltext von Unit1.pas mit folgendem ersetzen:
Delphi-Quellcode:
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs;

type
  TForm1 = class(TForm)
  private
    procedure WMNCLButtonDown(var Message: TWMNCLButtonDown); message WM_NCLBUTTONDOWN;
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.WMNCLButtonDown(var Message: TWMNCLButtonDown);
begin
  Message.Result := 1;
end;

end.
Zitat:
Das hat nichts mit einem Hack zu tun.. ich verwende das schon seit Jahren und hatte keine Probleme.
Man muss es nur richtig machen.
Wie setzt man eine systemweite Einstellung zurück wenn die eigene Anwendung abstürzt? Und es braucht auch nur eine Änderung in der Abfrage dieses systemweiten Flags passieren (innherhalb vom Windowscode/neue Versionen), so dass dann eben nicht mehr erst beim Draggen abgefragt wird und somit Windows deine Änderungen nicht mehr mitbekommt.
Ähnliches ist schon mal passiert was Toplevel-Fenster und die Behandlung von Besitzern/Ownern anging, und prompt waren eine Menge Hacks die sich auf undokumentierte Systeminterna verlassen haben plötzlich buggy. Windows hat sich darauf verlassen dass die Owner richtig angegeben wurden, und man nicht mehrere TopLevel-Fenster hat.

Die bekannten plötzlich verstecken Fenster bei Delphianwendungen die dann auch nicht mehr aktiviert werden können (weil das falsch platzierte Fenster modal war) hatten eben solch einen Grund: verlassen auf Interna, die so nicht dokumentiert waren und sich ändern können. Das fing glaube ich auch erst bei XP an ein Problem zu werden, vorher ging alles gut.

Dann kann es noch Probleme geben wenn der Fokus sich ändert oder z.B. eine andere Anwendung in den Vordergrund kommt, oder Mousecapture verloren geht (gibt es auch viele Gründe warum das regulär passieren kann), usw.

Der Grundsätzlich Denkfehler ist hier: Systemweites Flag wird gesetzt, aber es soll nur lokale Auswirkungen haben. Kann nicht gut gehen, da Windows ein nebenläufiges System ist und daher während das SPI_GETDRAGFULLWINDOWS-Flag "falsch" ist, auch andere Anwendungen davon betroffen sein können.
Das mag häufig/bei üblichen Szenarien funktionieren, aber wie bei race conditions im Allgemeinen hin und wieder unerklärliche Bugs hervorrufen.
HxD, schneller Hexeditor:
http://mh-nexus.de/hxd

Geändert von mael (14. Sep 2016 um 19:07 Uhr)
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#5

AW: SPI_SETDRAGFULLWINDOWS, aber nur für eigene Anwendung

  Alt 14. Sep 2016, 19:01
Zitat:
Wie setzt man eine systemweite Einstellung zurück wenn die eigene Anwendung abstürzt?
Na ja dafür gibt es Fehler Behandlungen. Ein Absturz hat immer einen Grund mit den richtigen Fehler Behandlungs Routinen dürfte das kein Problem sein.

Na sei's drum ich verwende das in meinem Mediaplayer schon mehr als 10 Jahre und habe keine nennenswerte Probleme damit.
Legitim ist es auch diese Funktion zu verwenden warum sonst hat MS diese veröffentlicht.

Zitat:
weiterleiten um somit den Windows-eigenen Drag-Drop-Prozess zu verhindern.
Mit Drag-Drop habe ich auch bei der Verwendung meiner Funktion genauso wenig ein Problem.

Gruss

Geändert von EWeiss (14. Sep 2016 um 19:03 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von mael
mael

Registriert seit: 13. Jan 2005
391 Beiträge
 
Delphi XE3 Professional
 
#6

AW: SPI_SETDRAGFULLWINDOWS, aber nur für eigene Anwendung

  Alt 14. Sep 2016, 19:15
Zitat:
Na ja dafür gibt es Fehler Behandlungen. Ein Absturz hat immer einen Grund mit den richtigen Fehler Behandlungs Routinen dürfte das kein Problem sein.
Schon, und zugegeben ist es unwahrscheinlich. Aber es gibt Abstürze die man nicht abfangen kann. Speicher und andere Ressourcen werden dann automatisch freigegeben, weil sie nur dem Prozess gehören. Darum kümmert sich das BS/Windows. Aber woher soll Windows wissen, dass es Systemeinstellungen rückgängig machen soll? Man hat ja keine Transaktion oder sowas definiert. Aber selbst wenn, löst das immernoch nicht das Problem der race conditions.

Zitat:
Legitim ist es auch diese Funktion zu verwenden warum sonst hat MS diese veröffentlicht.
Für Systemtools die systemweite Einstellungen ändern (wie die Systemsteuerung) und vielleicht noch Setup-Programme. Normale Programme verwenden SystemParametersInfo() nur zum Abfragen der Systemeinstellungen.

Zitat:
Zitat:
weiterleiten um somit den Windows-eigenen Drag-Drop-Prozess zu verhindern.
Mit Drag-Drop habe ich auch bei der Verwendung meiner Funktion genauso wenig ein Problem.
Das mag sein, ich habe mich nur gegen den Vorwurf gewehrt, dass meine Aussage falsch war, was sie offensichtlich nicht war.
HxD, schneller Hexeditor:
http://mh-nexus.de/hxd

Geändert von mael (14. Sep 2016 um 19:23 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:16 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz