Entwickler-Ecke

Windows API - TFolderBrowser (SHBrowseForFolder) - Fensterbreite & Caption


SuperDaniel - Fr 15.04.11 13:05
Titel: TFolderBrowser (SHBrowseForFolder) - Fensterbreite & Caption
Hi, erstmal Danke für die klasse Hilfe hier und entschuldigung wenn Ich hier vielleicht im falschen Forenbreich sein sollte.


Ich nutze TFolderBrowser (SHBrowseForFolder) hier aus dem Forum, und wollte nun mal fragen ob man die Fensterbreite beim Start ändern kann, da mein Caption zugroß ist und mehrzeilig dagestellt wird, schöner wäre einzeilig

Außerdem würde Ich gerne wissen ob man das Caption, also in meinem Fall den Fontsize oder Fontsytle ändern könnte, größer oder fett


Moderiert von user profile iconNarses: Topic aus Dateizugriff verschoben am Fr 15.04.2011 um 16:29


neuling321 - Sa 04.03.17 05:58

Hallo

Ich krame das Thema noch mal raus, gibt es eine Möglichkeit beim TFolderBrowser,
die Fensterbreite und Höhe anzupassen?


Delphi-Laie - Sa 04.03.17 09:57

user profile iconneuling321 hat folgendes geschrieben Zum zitierten Posting springen:
gibt es eine Möglichkeit beim TFolderBrowser,
die Fensterbreite und Höhe anzupassen?


In der Klassendefinition finde ich keine Funktion dazu, dementsprechend bietet auch die automatische Codevervollständigung nichts dergleichen an.

Ggf. ist es aber möglich, diese Klasse entsprechend zu ergänzen (wovon ich aber leider keine Ahnung habe).

Edit: Gräbt man in den Tiefen der fldbrows.pas und sucht die Ursache für die Placierung (etwas mit der Fenstergröße "verwandtes"), stößt man in der windows.pas auf "SetWindowPos", eine Windows-Api-Funktion, die dafür aufgerufen wird. Nur finde ich keine "SetWindowWidth" bzw. "SetWindowHeight".

Edit 2: Unter https://msdn.microsoft.com/en-us/library/windows/desktop/ms633545(v=vs.85).aspx steht "Changes the size, position, and Z order of a child, pop-up, or top-level window.". Der dritte und vierte Parameter dienen der Eingabe der Fensterbreite und -höhe. Ist also alles gewünschte in dieser Funktion vorhanden, muß "nur" von Delphi aus aufgerufen werden.

Edit 3: Dem Konstruktur TFolderBrowser.Create können allerdings keine Fensterparameter übergeben werden. SetWindowPos wird nur in FolderCallback, also nicht beim erstmaligen Erscheinen des Formulares, aufgerufen.

Edit 4: FolderCallback wird bei der Erzeugung auch aufgerufen, allerdings nicht SetWindowsPos, da fb.FPosChanged false ist.


t.roller - Sa 04.03.17 11:00

Allein das Fenster zu ändern bringt kein schönes Ergebnis - siehe Anhang - man muss mehr ändern...
Ich schaue mir das morgen genauer an - muss jetzt weg.


t.roller - Sa 04.03.17 19:04

Ich habe eine andere Version gefunden:
How to browse for a folder: http://www.cryer.co.uk/brian/delphi/howto_browseforfolder.htm

Das DIALOG-Window lässt sich beliebig verändern: Position, Grösse, Titel.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Memo1: TMemo;
    Timer1: TTimer;
    procedure Button2Click(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button2Click(Sender: TObject);
begin
Timer1.Enabled:= TRUE;
Memo1.Text:=
BrowseForFolder('myTitle','F:\',0,FALSE);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Timer1.Enabled:= FALSE;
  Timer1.Interval:= 500;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var Fo1 : HWND;
begin
  fo1:= FindWindow('#32770',nil);
  if fo1<>0 then BEGIN
    Timer1.Enabled:= FALSE;
    caption:= 'TEST1';
    SetWindowText(fo1, 'TEST2');
    SetWindowPos(fo1, 050004505000);
  END;
end;

end.
//---------------------------
unit BrowseForFolderU;

interface

function BrowseForFolder(const browseTitle: String;
const initialFolder: String = '';
const appHWND: THandle = 0;
mayCreateNewFolder: Boolean = False): String;

implementation

uses
  Winapi.Windows, Winapi.Shlobj;

var
  lg_StartFolder: String;

// With later versions of Delphi you may not need these constants.
const
  BIF_NEWDIALOGSTYLE=$40;
  BIF_NONEWFOLDERBUTTON=$200;

////////////////////////////////////////////////////////////////////////
// Call back function used to set the initial browse directory.
////////////////////////////////////////////////////////////////////////
function BrowseForFolderCallBack(Wnd: HWND; uMsg: UINT; lParam,
lpData: LPARAM): Integer stdcall;
begin
  if uMsg = BFFM_INITIALIZED then
    SendMessage(Wnd,BFFM_SETSELECTION, 1, Integer(@lg_StartFolder[1]));
  result := 0;
end;

////////////////////////////////////////////////////////////////////////
// This function allows the user to browse for a folder
//
// Arguments:-
//         browseTitle : The title to display on the browse dialog.
//       initialFolder : Optional argument. Use to specify the folder
//                       initially selected when the dialog opens.
//  mayCreateNewFolder : Flag indicating whether the user can create a
//                       new folder.
//
// Returns: The empty string if no folder was selected (i.e. if the user
//          clicked cancel), otherwise the full folder path.
////////////////////////////////////////////////////////////////////////
function BrowseForFolder(const browseTitle: String;
const initialFolder: String = '';
const appHWND: THandle = 0;
mayCreateNewFolder: Boolean = False): String;
var
  browse_info: TBrowseInfo;
  folder: array[0..MAX_PATH] of char;
  find_context: PItemIDList;
begin
  //--------------------------
  // Initialise the structure.
  //--------------------------
  FillChar(browse_info,SizeOf(browse_info),#0);
  lg_StartFolder := initialFolder;
  browse_info.pszDisplayName := @folder[0];
  browse_info.lpszTitle := PChar(browseTitle);
  browse_info.ulFlags := BIF_RETURNONLYFSDIRS or BIF_NEWDIALOGSTYLE;
  if not mayCreateNewFolder then
    browse_info.ulFlags := browse_info.ulFlags or BIF_NONEWFOLDERBUTTON;

  browse_info.hwndOwner := appHWND; //Application.Handle;
  if initialFolder <> '' then
    browse_info.lpfn := BrowseForFolderCallBack;
  find_context := SHBrowseForFolder(browse_info);
  if Assigned(find_context) then
  begin
    if SHGetPathFromIDList(find_context,folder) then
      result := folder
    else
      result := '';
    GlobalFreePtr(find_context);
  end
  else
    result := '';
end;

end.


Delphi-Laie - Sa 04.03.17 20:08

Diese Funktion / Unit gefällt mir, sie hätte glatt mein Freund werden können. Leider ist sie nicht so universell wie TFolderBrowser (SHBrowseForFolder), mit der man Verzeichnisse und / oder Dateien einlesen kann. Wenn man aber vorher weiß, daß man nur Verzeichnisse einlesen möchte, dann ist sie erste Wahl, zumal man sie auch an Delphi<4 anpassen könnte. Schade, daß solche Selbstverständlichkeiten (wie auch TrayIcons) erst im Laufe der Jahre in die offiziellen Delphi-Versionen Einzug hielten, so daß selbstprogrammierte Lösungen im Internet die Runde machten und wohl bei anderen Dingen auch immer noch machen.


t.roller - Sa 04.03.17 20:44

Wenn man eine Kleinigkeit ändert, kann man auch Files suchen:

Delphi-Quelltext
1:
2:
3:
4:
...
//  browse_info.ulFlags := BIF_RETURNONLYFSDIRS or BIF_NEWDIALOGSTYLE;
  browse_info.ulFlags := BIF_BROWSEINCLUDEFILES  or BIF_NEWDIALOGSTYLE;
...


Delphi-Laie - Sa 04.03.17 21:26

Vielen Dank, das funktioniert wie gewünscht!

Es läuft - mit geringen Anpassungen - auf/mit Delphi 3 und ohne weitere Anpassungen sogar noch auf/mit Delphi 2, mithin wurde diese Unit doch noch mein Freund.


t.roller - So 05.03.17 14:06

Ich habe heute mal etwas experimentiert.
Im folgenden Code-Abschnitt kann man viel ändern:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
// Call back function used to set the initial browse directory.
function BrowseForFolderCallBack(Wnd: HWND; uMsg: UINT; lParam,
lpData: LPARAM): Integer stdcall;
var bh : hWnd;
begin
  if uMsg = BFFM_INITIALIZED then
  BEGIN
    SendMessage(Wnd,BFFM_SETSELECTION, 1, Integer(@lg_StartFolder[1]));

    SetWindowText(GetDlgItem(Wnd, IDOK), PChar('Mach mal'));
    SetWindowText(GetDlgItem(Wnd, IDCANCEL), PChar('Verschwinde'));
    SetWindowText(GetDlgItem(Wnd, 14150), PChar('Mach ein Dingens'));
// 14146
    SetWindowText(GetDlgItem(Wnd, 14146), PChar('NEIN - Das ist mein Titel'));
// Nach Dateien oder Ordnern suchen
    SetWindowText(Wnd, 'LOS: Suche nach Dateien oder Ordnern');
    SetWindowPos(Wnd, 0500000, SWP_NOSIZE);
  END;
  result := 0;
end;
// Die Grösse lässt sich leider nur mit dem Timer ändern - der läuft aber nur 500 msec.
procedure TForm1.Timer1Timer(Sender: TObject);
var BfF : HWND;
begin
  BfF:= FindWindow('#32770',nil);
  if BfF<>0 then BEGIN
    Timer1.Enabled:= FALSE;
    SetWindowPos(BfF, 050004505000);
  END;
end;


neuling321 - Di 07.03.17 13:16

Hallo

Vielen Dank
Das mit dem "nur" Fenster grösser machen im TFolderBrowse habe ich auch gefunden, aber das nützt ja nichts wenn
der Inhalt klein bleibt :-(
Ich werde mal den anderen "Browser" einbinden und schauen. Ich weiss definitiv das nur Folder ausgewählt werden,
deshalb dürfte das kein Problem sein.

Danke


neuling321 - Di 07.03.17 18:07

Ich bekomme das leider nicht zum laufen.
Ich scheitere an dem Timer
Ich habe das als Unit eingebunden, wo muss ich jetzt den Timer setzen? im Haubt-Formular?

Und wie ist das mit dem Memo1? muss ich da ein Memo erstellen?

So nun läuft es doch noch :-)

Ich verstehe nicht was Du damit meinst.

"// Die Grösse lässt sich leider nur mit dem Timer ändern - der läuft aber nur 500 msec."


neuling321 - Mi 08.03.17 14:34

Wie bekomme ich den jetzt das Ergebnis von der einen Unit in eine andere Unit ins Textfeld?


Delphi-Laie - Mi 08.03.17 15:08

user profile iconneuling321 hat folgendes geschrieben Zum zitierten Posting springen:
Wie bekomme ich den jetzt das Ergebnis von der einen Unit in eine andere Unit ins Textfeld?


Es muß im Interface der jeweiligen Unit veröffentlicht bzw. aufgeführt werden, damit andere Units darauf zugreifen können bzw. von anderen Units aus darauf zugegriffen werden kann.

Bei gleichen Bezeichnern verschiedener Units so konkretisieren: Ein (z.B. etwas gewünschtes aus der Unit 2) "unit2." voranstellen, sonst wird das in der eigenen Unit immer bevorzugt.