Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Nicht modales Fenster reagiert nicht mehr (https://www.delphipraxis.net/70236-nicht-modales-fenster-reagiert-nicht-mehr.html)

Luckie 27. Mai 2006 13:06


Nicht modales Fenster reagiert nicht mehr
 
Ich zeige in einem Thread ein nicht modales Fenster an:

Delphi-Quellcode:
function Thread(p: PThreadParams): Integer;
var
  Info             : PWaitInfo;
  hDlg             : THandle;
begin

  New(Info);
  Info.hParent := p.hParent;
  Info.InfoText := rsWaitPrivileges;

  EnableWindow(p.hParent, False);
  hDlg := CreateDialogParam(hInstance, MAKEINTRESOURCE(500), p.hParent, @waitdlgproc, Integer(Info));
  try
    FillLVGroups(p.hParent, hDlg, ID_LV_GROUPS);
    FillLVPrivileges(p.hParent, hDlg, ID_LV_PRIVILEGES);
  except
    on E: Exception do
      DisplayExceptionMsg(p.hParent, E.Errorcode, E.Message, rsErrorGetPrivilegesCap);
  end;

  sleep(5000);
  EnableWindow(p.hParent, True);
  DestroyWindow(hDlg);
  Dispose(Info);

  Dispose(p);
  result := 0;
end;
Der Code zu CreateDialogParam sieht so aus:
Delphi-Quellcode:
(******************************************************************************
 *                                                                            *
 *  Usermanager                                                              *
 *  WaitDlg -- WaitDialog                                                    *
 *                                                                            *
 *  Copyright (c) 2006 Michael Puff [url]http://www.michael-puff.de[/url]              *
 *                                                                            *
 ******************************************************************************)

unit WaitDlg;

interface

uses
  Windows,
  Messages;

const
  ID_STC_INFO      = 501;

type
  TWaitInfo = record
    hParent: THandle;
    InfoText: WideString;
  end;
  PWaitInfo = ^TWaitInfo;

function waitdlgproc(hDlg: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): bool; stdcall;

implementation

function waitdlgproc(hDlg: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): bool; stdcall;
var
  rect, rect1       : TRect;
  x, y             : Cardinal;
  hParent          : THandle;
  Text             : WideString;
begin
  Result := true;

  case uMsg of
    WM_INITDIALOG:
      begin
        hParent := PWaitInfo(lParam)^.hParent;
        Text := PWaitInfo(lParam)^.InfoText;
        GetWindowRect(hParent, rect);
        GetWindowRect(hDlg, rect1);
        x := rect.Left - ((rect.Left - rect.Right) div 2) - ((rect1.Right - rect1.Left) div 2);
        y := rect.Top - ((rect.Top - rect.Bottom) div 2) - ((rect1.Bottom - rect1.Top) div 2);
        SetWindowPos(hDlg, 0, x, y, 0, 0, SWP_NOSIZE);
        SetWindowPos(GetDlgItem(hDlg, 299), 0, 0, 0, 305, 2, SWP_NOMOVE or SWP_SHOWWINDOW);
        SetDlgItemTextW(hDlg, ID_STC_INFO, PWideChar(Text));
      end;
  else
    Result := false;
  end;
end;

end.
Jetzt habe ich aber festgestellt, dass es, trotz dass es nicht modal, ist einfriert. Woran liegt das? Oder anderes gefargt, was mache ich falsch? :gruebel:

Luckie 27. Mai 2006 14:13

Re: Nicht modales Fenster reagiert nicht mehr
 
Ich denke, ich habe da Problem erkannt: Der Dialog hat keine Nachrichtenschleife. In einer dpr-Datei steht die Nachrichtenschleife im Hauptprogramm, dort habe ich auch eine für das Hauptfenster. Nur wo bringe ich die Nachrichtenchleife in einer Unit unter?

Zur Zeit sieht es so aus: Hauptfenster wird erzeugt mit CreateDialog und einer Nachrichtenschleife. Dann wird ein weiteres Fenster mit DialogBoxParam modal erzeugt und dann eben das besagte Fenster nicht modal mit CreateDialogParam. Also drei Fenster übereinander. Ich habe auch schon versucht, das zweite, modale Fenster, nicht modal zu erzeugen, so dass die Nachrichtenschleife vom Hauptfenster noch arbeitet, aber das hat auch nichts geholfen.

Olli 27. Mai 2006 14:22

Re: Nicht modales Fenster reagiert nicht mehr
 
Zitat:

Zitat von Luckie
Nur wo bringe ich die Nachrichtenchleife in einer Unit unter?

Ist doch deine Sache, oder?

Manchmal frage ich mich wo die Grundlagen bleiben :gruebel: :zwinker: :mrgreen:

Jeder Thread hat kann eine Nachrichtenschleife haben. Und wo ist der Startpunkt des Hauptthreads üblicherweise? Genau. Und wo ist dann der Startpunkt deines neuen Threads in dem jetzt der Dialog angezeigt werden soll? Genau. Siehste, jetzt haste es doch schon .... Grundlagen, Luckie. Grundlagen!

Übrigens: ob der nun modal oder nicht-modal ist, ist solange egal, wie nicht ein weiterer Dialog (auch Messageboxen) im selben Thread angezeigt wird.

Luckie 27. Mai 2006 14:54

Re: Nicht modales Fenster reagiert nicht mehr
 
Der letzte Satz war der entscheidende, denke ich.

Delphi-Quellcode:
        EnableWindow(hDlg, False);
        New(Info);
        Info.hParent := hDlg;
        Info.InfoText := rsWaitPrivileges;
        hWaitDlg := CreateDialogParam(hInstance, MAKEINTRESOURCE(500), hDlg, @waitdlgproc, Integer(Info));
        //Dispose(Info);

        New(ThreadParams);
        ThreadParams.hParent := hDlg;
        ThreadParams.hWaitDlg := hWaitDlg;
        CloseHandle(BeginThread(nil, 0, @Thread, ThreadParams, 0, ThreadID));
Jetzt erstelle ich das Fenster außerhalb des Threads. Allerdings klappt das Zerstören innerhalb des Threads nicht mehr:

Delphi-Quellcode:
function Thread(p: PThreadParams): Integer;
begin
  try
    FillLVGroups(p.hParent, ID_LV_GROUPS);
    FillLVPrivileges(p.hParent, ID_LV_PRIVILEGES);
  except
    on E: Exception do
      DisplayExceptionMsg(p.hParent, E.Errorcode, E.Message, rsErrorGetPrivilegesCap);
  end;

  sleep(5000);
  DestroyWindow(p.hWaitDlg);
  EnableWindow(p.hParent, True);

  Dispose(p);
  result := 0;
end;
GetLastError liefert mir "Zugriff verweigert". Darf ich DestroyWindow nicht in einem anderen Thread aufrufen?

Da hebn wirs:
Zitat:

A thread cannot use DestroyWindow to destroy a window created by a different thread.
Und nu? :gruebel:

Luckie 27. Mai 2006 15:59

Re: Nicht modales Fenster reagiert nicht mehr
 
Habe eine Lösung gefunden:
Delphi-Quellcode:
procedure WaitThread(ThreadFunc: TThreadFunc; Params: Pointer; Info: TWaitInfo);
var
  hWaitDlg         : THandle;
  hThread          : THandle;
  ThreadID         : Cardinal;
  ExitCode        : DWORD;
begin
  EnableWindow(Info.hParent, False);
  hWaitDlg := CreateDialogParam(hInstance, MAKEINTRESOURCE(500), Info.hParent, @waitdlgproc, Integer(@Info));

  hThread := BeginThread(nil, 0, @ThreadFunc, Params, 0, ThreadID);
  repeat
    GetExitCodeThread(hThread, ExitCode);
    ProcessMessages(hWaitDlg);
    ProcessMessages(info.hParent);
    sleep(1);
  until ExitCode = 0;
  DestroyWindow(hWaitDlg);
  EnableWindow(info.hParent, True);
end;

Olli 27. Mai 2006 17:25

Re: Nicht modales Fenster reagiert nicht mehr
 
Sind Parent und Child in verschiedenen Threads? Bin nicht sicher, daß das so gut ist ...

Vjay 27. Mai 2006 17:43

Re: Nicht modales Fenster reagiert nicht mehr
 
Ui, eine solche Frage hätte ich von einem Luckie nicht erwartet.

Implementiere doch eine temporäre nachrichtenschleife in den Thread, die solange läuft, wie das Fenster / der Thread existiert.

Und denke bitte immer daran deine Nachrichten an die DefWindowProc weiterzuleiten. Bill Gates wird es dir danken ;)

Olli 27. Mai 2006 19:20

Re: Nicht modales Fenster reagiert nicht mehr
 
Zitat:

Zitat von Vjay
Ui, eine solche Frage hätte ich von einem Luckie nicht erwartet.

Erwähnte ich ja schon. Aber tun wir mal so, als hätte er nur nen schwachen Moment gehabt ... :mrgreen:

Zitat:

Zitat von Vjay
Bill Gates wird es dir danken ;)

Echt? Hat der nen weltweiten Message-Hook installiert? Und wie heißt die Konstante zum Installieren? WH_...

Luckie 28. Mai 2006 00:13

Re: Nicht modales Fenster reagiert nicht mehr
 
Zitat:

Zitat von Olli
Sind Parent und Child in verschiedenen Threads? Bin nicht sicher, daß das so gut ist ...

hWaitDlg ist dieses Fenster mit der Animation und hParent ist zum Beispiel das Hauptfenster.


Zitat:

Zitat von Vjay
Ui, eine solche Frage hätte ich von einem Luckie nicht erwartet.

Ich hatte echt einen Blackout.

Zitat:

Implementiere doch eine temporäre nachrichtenschleife in den Thread, die solange läuft, wie das Fenster / der Thread existiert.
Das macht ja ProcessMessages.

Zitat:

Und denke bitte immer daran deine Nachrichten an die DefWindowProc weiterzuleiten. Bill Gates wird es dir danken ;)
Bei einem Dialog gibt man in diesem Fall als Result False zurück.


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:14 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz