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/)
-   -   Delphi CreateWindowEx, Parent + Child erzeugen (https://www.delphipraxis.net/137009-createwindowex-parent-child-erzeugen.html)

schwa226 12. Jul 2009 11:29


CreateWindowEx, Parent + Child erzeugen
 
Hi,

ich habe da so meine Probleme mit CreateWindowEx.

Ich kann ein Fenster erzeugen, aber ich kann kein Child dazu machen!?

Variante 1:
Delphi-Quellcode:
Procedure CreateWindows;
var
  wa, wb, wc, wd: TWndClass;
  hWindowParent, hWindowChild : Thandle;
  hMyChild : THandle;
begin

  if FindWindow('MyParent','') = 0 then
    begin

      with wa do begin
        lpszClassName := 'MyParent';
        lpfnWndProc  := @MainWndProc;
        Style        := CS_VREDRAW or CS_HREDRAW;
        hInstance    := hInstance;
        hIcon        := LoadIcon(0, IDI_APPLICATION);
        hCursor      := LoadCursor(0, IDC_ARROW);
        hbrBackground := (COLOR_WINDOW + 1);
        lpszMenuName := nil;
        cbClsExtra   := 0;
        cbWndExtra   := 0;
      end;

      with wb do begin
        lpszClassName := 'MyChild';
        lpfnWndProc  := @ChildWndProc;
        Style        := CS_VREDRAW or CS_HREDRAW;
        hInstance    := hMyChild;
        hIcon        := LoadIcon(0, IDI_APPLICATION);
        hCursor      := LoadCursor(0, IDC_ARROW);
        hbrBackground := (COLOR_WINDOW + 1);
        lpszMenuName := nil;
        cbClsExtra   := 0;
        cbWndExtra   := 0;
      end;

      Windows.RegisterClass(wa);


  //create main hwnd:
      hWindowParent := CreateWindowEx(WS_EX_TOPMOST Or WS_EX_TOOLWINDOW,
        'MyParent',
        nil,
        WS_POPUP,
        CW_USEDEFAULT, 0,
        0, 0,
        0,
        0,
        hInstance,
        nil);

  Windows.RegisterClass(wb);

  hWindowChild := CreateWindowEx(WS_EX_TOPMOST Or WS_EX_TOOLWINDOW,
    'MyChild',
    nil,
    WS_CHILD,
    CW_USEDEFAULT, 0,
    0, 0,
    hWindowParent,
    0,
    hMyChild,
    nil);

  end;
end;
Hier wird das Parent erzeugt, aber das Handle meines Childs bleibt 0!

Komisch ist auch, wenn ich aus der Prozedure ein Function mache dann gibt mir der Parent auch immer 0!? :wiejetzt:

Apollonius 12. Jul 2009 11:35

Re: CreateWindowEx, Parent + Child erzeugen
 
Es gibt diese tolle Funktion GetLastError, mit deren Hilfe man Forenmitglieder mit einer sinnvollen Fehlermeldung beglücken kann. Mir fällt an deinem Code auf, dass du eine WndClass, aber CreateWindowEx verwendest - möglicherweise klappt es mit WndClassEx.

schwa226 12. Jul 2009 11:41

Re: CreateWindowEx, Parent + Child erzeugen
 
Nach erzeugen des Parents gibt es keine Fehlermeldung!

Error nach dem Versuch das Child zu erzeugen:
Zitat:

ERROR_CANNOT_FIND_WND_CLASS
1407 (0x57F)

turboPASCAL 12. Jul 2009 11:45

Re: CreateWindowEx, Parent + Child erzeugen
 
Füge mal folgendes hinzu:

Delphi-Quellcode:
 //...
      zeromemory(@wa, sizeof(wa)); // <--<<
      with wa do begin
        lpszClassName := 'MyParent';
        lpfnWndProc  := @MainWndProc;
        Style        := CS_VREDRAW or CS_HREDRAW;
        hInstance    := hInstance;
        hIcon        := LoadIcon(0, IDI_APPLICATION);
        hCursor      := LoadCursor(0, IDC_ARROW);
        hbrBackground := (COLOR_WINDOW + 1);
        lpszMenuName := nil;
        cbClsExtra   := 0;
        cbWndExtra   := 0;
      end;

      zeromemory(@wb, sizeof(wb)); // <--<<
      with wb do begin
        lpszClassName := 'MyChild';
        // ...

schwa226 12. Jul 2009 11:49

Re: CreateWindowEx, Parent + Child erzeugen
 
Leider immer noch der gleiche Fehler 1407!

Apollonius 12. Jul 2009 11:54

Re: CreateWindowEx, Parent + Child erzeugen
 
Was gibt denn RegisterClass zurück?

turboPASCAL 12. Jul 2009 12:04

Re: CreateWindowEx, Parent + Child erzeugen
 
Mach es so:
Delphi-Quellcode:
Procedure CreateWindows;
var
  wa, wb, wc, wd: TWndClass;
  hWindowParent, hWindowChild : Thandle;
  hMyChild : THandle;
begin

  if FindWindow('MyParent','') = 0 then
    begin
      zeromemory(@wa, sizeof(wa)); // <--<<
      with wa do begin
        lpszClassName := 'MyParent';
        lpfnWndProc  := @MainWndProc;
        Style        := CS_VREDRAW or CS_HREDRAW;
        hInstance    := hInstance;
        hIcon        := LoadIcon(0, IDI_APPLICATION);
        hCursor      := LoadCursor(0, IDC_ARROW);
        hbrBackground := (COLOR_WINDOW + 1);
        lpszMenuName := nil;
        cbClsExtra   := 0;
        cbWndExtra   := 0;
      end;

      zeromemory(@wb, sizeof(wb)); // <--<<
      with wb do begin
        lpszClassName := 'MyChild';
        lpfnWndProc  := @ChildWndProc;
        Style        := CS_VREDRAW or CS_HREDRAW;
        hInstance    := hMyChild;
        hIcon        := LoadIcon(0, IDI_APPLICATION);
        hCursor      := LoadCursor(0, IDC_ARROW);
        hbrBackground := (COLOR_BTNFACE + 1); // <--<<
        lpszMenuName := nil;
        cbClsExtra   := 0;
        cbWndExtra   := 0;
      end;

      if Windows.RegisterClass(wa) = 0 then // <--<<
        MessageBox(0, 'Kann Fensterklasse nicht registrieren.', 'MyParent', MB_OK);

      if Windows.RegisterClass(wb) = 0 then // <--<<
        MessageBox(0, 'Kann Fensterklasse nicht registrieren.', 'MyChild', MB_OK);

      //create main hwnd:
      hWindowParent := CreateWindowEx(WS_EX_TOPMOST Or WS_EX_TOOLWINDOW,
       'MyParent',
        '',
        WS_POPUP or windows.ws_visible, // <--<<
        CW_USEDEFAULT, 0,
        100, 100, // <--<<
        0,
        0,
        hInstance,
        nil);

    if hWindowParent <> 0 then // <--<<
      hWindowChild := CreateWindowEx(0, // <--<<
        'MyChild',
        nil,
        WS_CHILD or ws_visible, // <--<<
        CW_USEDEFAULT, 0,
        40, 40, // <--<<
        hWindowParent,
        0,
        hMyChild,
      nil);

  end;
end;
das funkltioniert mit sicherheit.

schwa226 12. Jul 2009 12:06

Re: CreateWindowEx, Parent + Child erzeugen
 
Also RegisterClass gibt mir ein Word <> 0 zurück was ja bedeutet das es funktioniert hat, oder?

Jedoch bekomme ich mit GetLastError:
Zitat:

ERROR_FILE_NOT_FOUND
2 (0x2)
Wenn ich
Delphi-Quellcode:
  Windows.RegisterClass(wb);
Showmessage(IntToStr(GetLastError));

  hWindowChild := CreateWindowEx(WS_EX_TOPMOST Or WS_EX_TOOLWINDOW,
    'MyChild',
    nil,
    WS_CHILD,
    CW_USEDEFAULT, 0,
    0, 0,
    hWindowParent,
    0,
    hMyChild,
    nil);

Showmessage(IntToStr(GetLastError));
mache bekomme ich beim ersten Error 2, beim zweiten Error 0 obwohl hWindowChild 0 ist!?

Apollonius 12. Jul 2009 12:09

Re: CreateWindowEx, Parent + Child erzeugen
 
GetLastError sagt nichts aus, wenn der Rückgabewert der Funktion Erfolg anzeigt.

schwa226 12. Jul 2009 12:13

Re: CreateWindowEx, Parent + Child erzeugen
 
@turboPASCAL:

Zitat:

ERROR_CALL_NOT_IMPLEMENTED
120 (0x78)
Das bekomme ich nach dem CreateWindowEx Parent.
CreateWindowEx Child bleibt bei 1407.

Jetzt habe ich es nocheinmal in einem neuen Projekt versucht.

Beim ersten mal wurde ein Parent erzeugt. Will ich es nun nocheinmal starten bleibt das Parent auf 0!
Last Error auch 0.

Wenn ich mein Programm beende muss ich wa oder sonst etwas anderes deregistrieren. Oder wird das Automatisch beim beenden meiner App gemacht?

turboPASCAL 12. Jul 2009 12:28

Re: CreateWindowEx, Parent + Child erzeugen
 
Wie und wo rufst du das auf ?
Ist oder wird das eine nonVCL oder eine VCL Application ?

oder hänge das Projekt mal als zip an.

schwa226 12. Jul 2009 12:42

Re: CreateWindowEx, Parent + Child erzeugen
 
Es ist eine VCL Anwendung!

Habe es jetzt aber geschafft! Habe nochmal deinen Code komplett kopiert und neu eingefügt.

Auch waren meine Funktionen wie MainWndProc nicht Global erreichbar.

Ich bekomme zwar immer noch den Error 120 nach dem erzeugen des Parents, aber es werden Parent und Child erzeugt!

Auch kann ich nun eine Funktion statt der Prozedur verwenden!

Danke! :lol:

Anscheinend hat es auch etwas mit dem zu tun:
Delphi-Quellcode:
function ChildWndProc(hWindow: HWND; Msg: UINT;
    wParam: wParam; lParam: lParam): HRESULT; stdcall;
begin
  Result := 1;
end;
Wenn ich Result := 0 zurück gebe werden Childs nicht erzeugt!

turboPASCAL 12. Jul 2009 12:51

Re: CreateWindowEx, Parent + Child erzeugen
 
Sehe gerade noch einen Fehler:
Delphi-Quellcode:
// ...
      with wb do begin
        lpszClassName := 'MyChild';
        lpfnWndProc  := @ChildWndProc;
        Style        := CS_VREDRAW or CS_HREDRAW;
        //hInstance    := hMyChild; // <--<< das wird nix
        hInstance    := hInstance;

schwa226 15. Jul 2009 07:19

Re: CreateWindowEx, Parent + Child erzeugen
 
Hi,

also das mit
Zitat:

//hInstance := hMyChild; // <--<< das wird nix
hInstance := hInstance;
habe ich probiert. Da bleibt mir dann das Parent leer. Letzten Error habe ich jetzt noch nicht überprüft.

Bei RegisterClass habe ich auch hMyChild.

Habe jetzt bei 4 Windows 4 verschiedene hInstance und es geht.

Jedoch habe ich noch eine kleine Frage:

Wie schließe ich das Fenster wieder, dass mit CreateWindowEx eruegt wurde?

Habe es versucht mit FindWindow das Handle zu bekommen und mit:
Zitat:

SendMessage(h, WM_SYSCOMMAND, SC_CLOSE, 0);
das Handle zu schließen.

Es wird auch geschlossen, aber leider auch meine Anwendung!?

schwa226 4. Jan 2010 12:06

Re: CreateWindowEx, Parent + Child erzeugen
 
Hallo,

ich habe zu RegisterClass und Unregister nochmal eine Frage:

Ich erzeuge so mein Fenster:
Delphi-Quellcode:
      zeromemory(@wa, sizeof(wa)); // <--<<
      with wa do begin
        lpszClassName := 'Mein_Fenster';
        lpfnWndProc  := @MainWndProc;
        Style        := CS_VREDRAW or CS_HREDRAW;
        hInstance    := hInstance;//hMain;
        hIcon        := 0;//LoadIcon(0, IDI_APPLICATION);
        hCursor      := 0;//LoadCursor(0, IDC_ARROW);
        hbrBackground := (COLOR_WINDOW + 1);
        lpszMenuName := nil;
        cbClsExtra   := 0;
        cbWndExtra   := 0;
      end;

Windows.RegisterClass(wa);

      hMainFenster := CreateWindowEx(WS_EX_TOPMOST Or WS_EX_TOOLWINDOW,
        wa.lpszClassName,
        '',
        WS_POPUP or windows.ws_visible, // <--<<
        0, 0,
        0, 0, // <--<<
        0,
        0,
        hInstance,
        nil);
Das Fenster wird erzeugt und ich bekomme Aufrufe in der angegebenen Funktion: MainWndProc.

Wie beende ich das nun wieder.

Ich habe es so versucht:
Delphi-Quellcode:
  if hMainFenster <> 0 then
    DestroyWindow(hMainFenster);

  if GetClassInfo(HInstance, wa.lpszClassName, TempClass) then
    Windows.UnregisterClass(wa.lpszClassName,hInstance);
zeromemory(@wa, sizeof(wa));
Jedoch scheint es so das immer noch Aufrufe in meine MainWndProc Funktion rein kommen.

Wie kann ich das verhindern, oder ist wenn ich das Fenster schließe auch sichergestellt das die Funktion MainWndProc nicht mehr verfügbar ist?

Luckie 4. Jan 2010 12:19

Re: CreateWindowEx, Parent + Child erzeugen
 
Zitat:

Zitat von schwa226
Es ist eine VCL Anwendung!

Und warum mischt du dann VCL und nonVCL? Das geht meistens schief.

schwa226 4. Jan 2010 14:05

Re: CreateWindowEx, Parent + Child erzeugen
 
Weil das erzeugte "unsichtbare" Fenster für einen Shell-Ersatz dient.


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:01 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 by Thomas Breitkreuz