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 Ich finde keine ChildHandles beim TSaveDialog ... (https://www.delphipraxis.net/51835-ich-finde-keine-childhandles-beim-tsavedialog.html)

FriFra 19. Aug 2005 21:45


Ich finde keine ChildHandles beim TSaveDialog ...
 
Ich versuche nun schon eine ganze weile irgendwie an das Handle das Filename-Edit des Savedialogs zu kommen...

Ich habe es mit dieser unit versucht: http://www.delphipraxis.net/internal...hlight=fenster

wlist.EnumChildWindows(SaveDialog1.Handle); liefert jedoch immer nichts... es werden einfach keine Childs gefunden...

P.S.: Ich hab auch schon div. andere Beispielcodes getestet, alle mit dem gleichen Effekt :gruebel:

Luckie 19. Aug 2005 23:06

Re: Ich finde keine ChildHandles beim TSaveDialog ...
 
Such dir mit einem Tool die ID des Edits und dann benutzt du MSDN-Library durchsuchenGetDlgItem, um dir das Handle zu holen. Ist am einfachsten.

FriFra 20. Aug 2005 07:21

Re: Ich finde keine ChildHandles beim TSaveDialog ...
 
Zitat:

Zitat von Luckie
Such dir mit einem Tool die ID des Edits

Welches Tool ist denn dafür geeignet? Bisher hab ich meistens XSpy verwendet, aber das hilft mir hier leider nicht :roll:

FriFra 20. Aug 2005 07:35

Re: Ich finde keine ChildHandles beim TSaveDialog ...
 
:oops: jetzt hab ich die ID doch mit XSpy gefunden :) ...

FriFra 20. Aug 2005 08:13

Re: Ich finde keine ChildHandles beim TSaveDialog ...
 
:x Zu früh gefreut...

Das Handle bekomme ich trotz ItemId nicht :roll:
Delphi-Quellcode:
  wnd := GetDlgItem(SaveDialog1.Handle, 1148);
  if wnd <> 0 then
  begin
    showmessage(IntToStr(wnd));
  end;

SirThornberry 20. Aug 2005 08:59

Re: Ich finde keine ChildHandles beim TSaveDialog ...
 
hast du schon mal geschaut welchen Wert das Handle deines SaveDialogs hat? Ich hab mal das ganze mit dem Opendialog probieren wollen und musste feststellen das, das Handle vom Dialog 0 war.
Es kommt also darauf an, zu welchem Zeitpunkt du das ganze versuchst zu performane. Wenn du es zum Beispiel im OnShow des Dialogs machst ist ein Handle vorhanden, wenn der Dialog jedoch nicht mehr eingeblendet ist, so ist auch das handle wieder 0.

FriFra 20. Aug 2005 09:04

Re: Ich finde keine ChildHandles beim TSaveDialog ...
 
Mein SaveDialog hat ein Handle, denn ich mache das ganze OnSelectionChange ;)

SirThornberry 20. Aug 2005 09:08

Re: Ich finde keine ChildHandles beim TSaveDialog ...
 
habs grad beim probieren mitbekommen das es irgendwie bei mir auch nicht geht. Was mir aber auch aufgefallen ist - das handle von Dialog.Handle ist nicht das gleiche Handle wie das des sichtbaren Dialog-Fensters.

toms 20. Aug 2005 09:09

Re: Ich finde keine ChildHandles beim TSaveDialog ...
 
Hallo,


Mein WinSpy liefert folgenden Code und findet das File Name Edit:

Delphi-Quellcode:
var
  wnd: HWND;
begin
  wnd := FindWindow('#32770',nil); // oder was auch immer...
  wnd := FindWindowEx(wnd, 0, 'ComboBoxEx32', nil);
  wnd := FindWindowEx(wnd, 0, 'ComboBox', nil);
  wnd := FindWindowEx(wnd, 0, 'Edit', nil);
  if wnd <> 0 then
  begin
    // ....gefunden!
  end;
end.

Edit: Ansonsten mal hier schauen: http://groups.google.ch/group/borlan...2969077?hl=de&

SirThornberry 20. Aug 2005 09:11

Re: Ich finde keine ChildHandles beim TSaveDialog ...
 
@toms: Zum problem wird es nur wenn es noch einen weiteren Dialog gibt, denn dann ist nicht mehr sicher das man auch den eigenen findet. Daher finde ich den Lösungsversuch über das Handle des Dialogs zu gehen bedeutend besser.

FriFra 20. Aug 2005 09:19

Re: Ich finde keine ChildHandles beim TSaveDialog ...
 
So, jetzt hab ich die verschiednen Tips kombiniert und hab die IMHO beste Lösung gewfunden ;)

Delphi-Quellcode:
  wnd := FindWindow('#32770',PChar(SaveDialog1.Title));
  wnd := GetDlgItem(wnd, 1148);
  if wnd <> 0 then
  begin
    showmessage('// ....gefunden!');
  end;
Der Vorteil wenn man über die ItemID geht liegt darin, dass man jetzt sogar die Captions der Buttons und Labels ändern kann ;)

SirThornberry 20. Aug 2005 09:23

Re: Ich finde keine ChildHandles beim TSaveDialog ...
 
@Frifra: Wer sagt dir aber dass, das handle was dir findwindow zurück gibt auch wirklich von deinem dialog ist und nicht das handle eines fensters aus einer anderen anwendung?

wenn ich folgendes auf meinem Rechner ausführe bekomme ich 4 handles in meiner Listbox was also auch heißt das es 4 Fenster mit dem Classname gibt. Somit wäre deine Variante nicht sehr zuverlässig.
Delphi-Quellcode:
var LHandle: Cardinal;
    LStr: PChar;
begin
  LStr := StrAlloc(255);
  LHandle := FindWindow('#32770', nil);
  while (LHandle <> 0) do
  begin
    GetClassName(LHandle, LStr, 254);
    if LStr = '#32770' then
      ListBox1.Items.Add(inttostr(LhANDLE));
    LHandle := GetWindow(LHandle, GW_HWNDNEXT);
  end;
  StrDispose(LStr);
end;
bei der variante von Toms ist es auch nicht anders, da kann es ganauso passieren das man entweder kein handle zurück bekommt oder das von einem anderen dialog.

Wenn du das ganze wie folgt erweiterst kannst du wenigstens sicherstellen dass, das gefundene Fenster zu deiner Anwendung gehört:
Delphi-Quellcode:
var LHandle: Cardinal;
    LStr: PChar;
begin
  LStr := StrAlloc(255);
  LHandle := FindWindow('#32770', nil);
  while (LHandle <> 0) do
  begin
    GetClassName(LHandle, LStr, 254);
    if LStr = '#32770' then
    begin
      if GetWindow(LHandle, GW_OWNER) = Application.Handle then
        EnumChildWindows(LHandle, @EnumProc, 0);
    end;
    LHandle := GetWindow(LHandle, GW_HWNDNEXT);
  end;
  StrDispose(LStr);
end;

FriFra 20. Aug 2005 10:10

Re: Ich finde keine ChildHandles beim TSaveDialog ...
 
Zitat:

Zitat von SirThornberry
@Frifra: Wer sagt dir aber dass, das handle was dir findwindow zurück gibt auch wirklich von deinem dialog ist und nicht das handle eines fensters aus einer anderen anwendung?

Das es tatsächlich "mein" Dialog ist, ist durch die Angabe der Caption im FindWindow sichergestellt, da diese Caption bei mir eindeutig ist ;)
Delphi-Quellcode:
wnd := FindWindow('#32770',PChar(SaveDialog1.Title));
Ich hab aber gerade festgestellt, das es beim Überschreiben der Buttoncaptions Probleme gibt...
Delphi-Quellcode:
var
  wnd: HWND;
  Tmp: string;
  Buffer: array[0..MAX_PATH] of Char;
  n: integer;
begin
  wnd := FindWindow('#32770', PChar(SaveDialog1.Title));
  wnd := GetDlgItem(wnd, 1);
  if wnd <> 0 then
  begin
    GetWindowText(wnd, Buffer, MAX_PATH);
    Tmp := 'Teest';
    if StrPas(Buffer) <> Tmp then
      SetWindowText(wnd, PChar(Tmp));
  end;
Mache ich das ganze im onShow, wird die Caption von Windows sofort wieder überzeichnet... lagere ich das ganze in einen Timer mit kurzem Interval aus, so hat mam bei jeder Dateiauswahl (-> Neuzeichnen des gesamten Dialoges) ein "lustiges Blinkespiel", weil jedesmal wieder kurz die Originalcaption zu sehen ist :roll:

SirThornberry 20. Aug 2005 10:14

Re: Ich finde keine ChildHandles beim TSaveDialog ...
 
reicht es nicht das du einmal die caption setzt und dann den timer abschaltest?

FriFra 20. Aug 2005 10:22

Re: Ich finde keine ChildHandles beim TSaveDialog ...
 
Nein, sobald man z.B. eine Datei auswählt, werden alle Buttoncaptions neu gezeichnet... natürlich wieder mit den originalwerten :x

SirThornberry 20. Aug 2005 10:25

Re: Ich finde keine ChildHandles beim TSaveDialog ...
 
da du die handles der Buttons hast könntest du die Windowproc umlenken und die messages zum setzen der Caption einfach verwerfen

FriFra 20. Aug 2005 10:29

Re: Ich finde keine ChildHandles beim TSaveDialog ...
 
Und wie mach ich das?

Wenn ich das hinbekäme könnte ich endlich mal alle Captions der Standardialoge ändern, was für mehrsprachige Anwendungen sehr gut ist ;)

SirThornberry 20. Aug 2005 10:31

Re: Ich finde keine ChildHandles beim TSaveDialog ...
 
komich, ich hab grad mal die buttoncaption für "öffnen" geändert und diese wurde nicht zurück geändert als ich eine Datei gewählt habe oder den Ordner gewechselt. Wie man die Windowproc umbiegt - ich bastels mal schnell zamm

[Edit]
So wirds gemacht
Delphi-Quellcode:
//variable für die alte windowproc
var GOldProc: function(AHandle: Cardinal; uMsg: Cardinal; AWPARAM: wParam; ALPARAM: lParam): LResult; Stdcall;

//unsere neue Windowproc
function NewWindowProc(AHandle: Cardinal; uMsg: Cardinal; AWPARAM: wParam; ALPARAM: lParam): LResult; Stdcall;
begin
  result := GOldProc(AHandle, uMsg, AWParam, ALParam);
end;

[...]
//umbiegen auf neue windowproc und sichern der alten für inherited call
Integer(@GOldProc) := SetWindowLong(LHandle, GWL_WNDPROC, Integer(@NewWindowProc));
[...]
in der NewWindowProc kannst du dann wm_settext verwerfen bzw. abändern

FriFra 20. Aug 2005 11:05

Re: Ich finde keine ChildHandles beim TSaveDialog ...
 
Bei "Integer(@NewWindowProc)" kommt bei mir immer der Fehler "Variable erforderlich"...

SirThornberry 20. Aug 2005 11:08

Re: Ich finde keine ChildHandles beim TSaveDialog ...
 
dann versuch mal ob es geht wenn du das "@" wegmachst, unter d5 ging es ohne "@" wenn ich mich recht entsinne, mein Delphi7 hingegen meckert rum. Ansonsten kannst du den Cast auch um den anderen Teil machen (also auf den Proceduretype casten)

also so:
Delphi-Quellcode:
type
  TWindowproc = function(AHandle: Cardinal; uMsg: Cardinal; AWPARAM: wParam; ALPARAM: lParam): LResult; Stdcall;
[...]
var GOldProc: TWindowProc;
[...]
GOldProc := TWindowProc(SetWindowLong(LHandle, GWL_WNDPROC, Integer(@NewWindowProc)));

FriFra 20. Aug 2005 16:10

Re: Ich finde keine ChildHandles beim TSaveDialog ...
 
:roll: Hm... irgendwas mach ich wohl falsch...
http://www.frifra.de/Temp/varerf.jpg

SirThornberry 20. Aug 2005 17:54

Re: Ich finde keine ChildHandles beim TSaveDialog ...
 
also in meinem D2005 funktionierts. Hier mal die komplette unit:
Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TWindowproc = function(AHandle: Cardinal; uMsg: Cardinal; AWPARAM: wParam; ALPARAM: lParam): LResult;
  TForm1 = class(TForm)
    Button1: TButton;
    SaveDialog1: TSaveDialog;
    procedure Button1Click(Sender: TObject);
    procedure SaveDialog1Show(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

var GOldProc: TWindowProc;

function NewWindowProc(AHandle: Cardinal; uMsg: Cardinal; AWPARAM: wParam; ALPARAM: lParam): LResult; Stdcall;
begin
  result := GOldProc(AHandle, uMsg, AWParam, ALParam);
end;

procedure TForm1.SaveDialog1Show(Sender: TObject);
begin
  GOldProc := TWindowProc(SetWindowLong(SaveDialog1.Handle, GWL_WNDPROC, Integer(@NewWindowProc)));
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  SaveDialog1.Execute();
end;

end.

himitsu 22. Apr 2006 10:13

Re: Ich finde keine ChildHandles beim TSaveDialog ...
 
Liste der Anhänge anzeigen (Anzahl: 2)
Ist schon pracktisch solch ein Thema zu finden, welches gleich in doppelter Hinsicht passt :)

eigentlich wollte ich ja erst sowas sagen,
Delphi-Quellcode:
Ich würde mal versuchen rauszubekommen, wie das z.B. Notepad macht, denn der hat auch seine eigene Beschriftung und ohne das es flackert.

Bei meinem Notepad steht [b]Dateiname[/b] und [b]Dateityp[/b], aber in den originalen Open-/Save-Dialogen steht bei mir [b]Objektname[/b] und [b]Objekttyp[/b] (im SaveDialog allerdings [b]Dateityp[/b] :gruebel: )
aber inzwischen hat sich hier einiges geändert, bei mir funktionier das mit dem Übersetzen auch ganz gut und ich benötige dafür nur eine Zeile ^^
Delphi-Quellcode:
SendMessageW(GetDlgItem(hWnd, 1), WM_SETTEXT, 0, Integer(PChar('abc123')));
Im Brunde bräuchtet ihr euch nur in den ExplorerHook des Dialogs einschalten, bei Msg = WM_NOTIFY und POFNotifyExW(LParam)^.hdr.code = CDN_INITDONE.
Oder, wenn's reicht ins onShow-Ereignis (wird über's ExplorerHook aufgerufen).

Ich persönlich hab hier meinen eigenen ExplorerHook, daher isses wohl etwas einfacher :mrgreen:



Zu dem Handle-Problem:
Dat hab'sch aus'm MSDN - das über GetOpenFileName/GetSaveFileName-Fenster enthält seit Win2K/NT vermutlich sowas wie ein Explorer-Fenster, welches wohl jetzt die WindowsMessages an den ExplorerHook versendet, muß also erst das Handle auf das Dialog-Fenster geholt werden.
Zitat:

Zitat von MSDN
[in] Handle to the child dialog box of the Open or Save As dialog box. Use the GetParent function to get the handle to the Open or Save As dialog box.

Luckie hat das inzwischen auch schon "irgendwie" mitbekommen und holt sich jetzt per
Delphi-Quellcode:
hWnd := GetParent(hWnd);
das richtige Fenster, mit den gesuchten Controls, herran.



Ach ja, hab auch etwas gebraucht und diese Fenster bisher entziffert.
(bis auf 0 und 1088 ... keine Ahnug was das ist)
Code:
#32770 DialogName
0        ?
1      Öffnen-Button
2      Abbrechen-Button
1038   Hilfe-Button
1040   Schreibgeschützt-CheckBox
1088     ?
1089   Typ-Label
1090   Dateiname-Label
1091   SuchenIn-Label
1120   Datei-ListBox
1136   Typ-Edit
1137   SuchenIn-ComboBox
1148   Dateiname-Edit
1184   PlacesBar
Und Luckie ... WinSight hilft irgendwie auch nicht viel weiter :gruebel:
bei mir hat das nur die beiden SuchenIn-Controls entdeckt :gruebel:
(hab dann einfach mal in 'ner Schleife eines per GetDlgItem testen lassen)

himitsu 24. Apr 2006 07:48

Re: Ich finde keine ChildHandles beim TSaveDialog ...
 
So, die letzten Contros wurden endlich entschlüsselt :)
Code:
#32770 » DialogName
0 » OpenDialog-ClientBereich
1 » Öffnen-Button
2 » Abbrechen-Button
1038 » Hilfe-Button
1040 » Schreibgeschützt-CheckBox
1088 » Control-Butons (at top-right)
1089 » Typ-Label
1090 » Dateiname-Label
1091 » SuchenIn-Label
1120 » Datei-ListBox
1136 » Typ-Edit
1137 » SuchenIn-ComboBox
1152 » Dateiname-Edit
1184 » PlacesBar

himitsu 28. Apr 2006 11:43

Re: Ich finde keine ChildHandles beim TSaveDialog ...
 
Gleiches Problem ... neue Ursache :shock:

Dachte erst ich hätte mich beim Dateiname-Edit (ID 1148) verschrieben, aber als ich jetzt wieder daheim weiterproggen wollte ging es plötzlich nicht mehr (falsche ID), also nochmal gesucht und siehe da, ich hatte es richtig aufgeschrieben nur da ist es die ID 1152 :wall:

Also ich hab für das selbe Editfeld bisher 2 IDs (WinXP mit und ohne SP)

Wie soll ich denn jetzt vorgehen ... kann ja schließlich nicht alle IDs, für alle Windowsversionen ermitteln und dann die passende verwenden? :stupid:

Es ist zwar einfach an alle IDs der vorhanden Controls ranzukommen, aber wie kann ich mit Sicherheit feststellen welche ID welches Control darstellt?

himitsu 1. Mai 2006 08:30

Re: Ich finde keine ChildHandles beim TSaveDialog ...
 
Zitat:

Zitat von FriFra
Der Vorteil wenn man über die ItemID geht liegt darin, ....

Tja, leider verändern sich ja anscheinend die IDs von Windows zu Windows :cry:

Aber zumindestens hab ich inzwischen alles so hinbekommen, daß jetzt die meißten Beschriftungen über ResourceStrings geladen und erfolgreich gesetzt werden (solange die DlgItemIDs stimmen)

Drüben der entsprechende QuellCode
http://www.delphipraxis.net/internal...=541243#541243


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:29 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