Autor Beitrag
Steve1024
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 141

Windows 2K, XP, 7 & Server 2003 - 2008; Linux (Ubuntu, Fedora)
D7, D05, D06, D09, DXE
BeitragVerfasst: Mi 15.06.11 22:02 
ausblenden volle Höhe 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:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
uses
  SysUtils, Classes, Forms, Messages, Controls, Windows;

type
  TExternalForm = class(TWinControl)
  private
    FExternalHWND: HWND;
  private // old data values
    FOldParent: HWND;
    FOldStyle,
    FOldExStyle: DWORD;
    FOldWndProc: Pointer;
  protected
    procedure CreateWnd; override;
    procedure DestroyWindowHandle; override;
    procedure SetParent(AParent: TWinControl); override;
  public
    constructor Create(AOwner: TComponent; AExternalHWND: HWND); reintroduce;
    procedure DefaultHandler(var Message); override;
    procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
    property ExternalHWND: HWND read FExternalHWND;
  end;

implementation

function OnEnumChildProc(hwWindow: HWND; lpParam: Integer): Bool; stdcall;
var vOwner: TExternalForm;
begin
  try
    vOwner := TExternalForm(Pointer(lpParam));
    with TExternalForm.Create(vOwner, hwWindow) do
    begin
      Parent := vOwner;
      TabOrder := 0;
    end;
  except (* do nothing on error *) end;
  Result := TRUE;
end;

{ TExternalForm }

constructor TExternalForm.Create(AOwner: TComponent; AExternalHWND: HWND);
begin
  inherited Create(AOwner);
  FExternalHWND := AExternalHWND;

  if (Windows.GetWindowLong(FExternalHWND, GWL_STYLE) AND WS_CLIPCHILDREN) <> 0 then
    ControlStyle := [csAcceptsControls, csDoubleClicks, csNoStdEvents]
  else ControlStyle := [csDoubleClicks, csNoStdEvents];
  TabStop := (Windows.GetWindowLong(FExternalHWND, GWL_STYLE) AND WS_TABSTOP) <> 0;
end;

procedure TExternalForm.CreateWnd;
var vParams: TCreateParams;
begin
  if FExternalHWND = 0 then
    raise Exception.Create('No external window found.');

  // backup current properties
  FOldParent := Windows.GetParent(FExternalHWND);
  FOldWndProc := Pointer(GetWindowLong(WindowHandle, GWL_WNDPROC));
  FOldStyle := Windows.GetWindowLong(FExternalHWND, GWL_STYLE);
  FOldExStyle := Windows.GetWindowLong(FExternalHWND, GWL_EXSTYLE);

  // set new mandatory values
  CreateParams(vParams);
  Windows.SetParent(FExternalHWND, GetParentHandle);
  Windows.SetWindowLong(FExternalHWND, GWL_STYLE,
    ((FOldStyle OR vParams.Style OR WS_CHILD) AND
    NOT (WS_POPUP OR WS_CAPTION)));
  Windows.SetWindowLong(FExternalHWND, GWL_EXSTYLE,
    ((FOldExStyle OR vParams.ExStyle OR WS_EX_TOOLWINDOW)));

  // control operations
  WindowHandle := FExternalHWND;
  DefWndProc := Pointer(GetWindowLong(WindowHandle, GWL_WNDPROC));
  CreationControl := Self;
  SetWindowLong(WindowHandle, GWL_WNDPROC, Longint(@InitWndProc));
  SendMessage(WindowHandle, WM_NULL, 00);

  // apply visibility
  if not Visible and IsWindowVisible(Handle) then
    ShowWindow(Handle, SW_HIDE);

  // do this for all child items too
  EnumChildWindows(FExternalHWND, @OnEnumChildProc, NativeInt(Self));
end;

const
  OCM_BASE = $2000;

procedure TExternalForm.DefaultHandler(var Message);
begin
  if HandleAllocated then
    with TMessage(Messagedo
    begin
      if (Msg >= CN_BASE) and (Msg < CN_BASE + WM_USER) then
        Msg := Msg - (CN_BASE - OCM_BASE);
      if not (csAcceptsControls in ControlStyle) then
      begin
        Result := CallWindowProc(DefWndProc, Handle, Msg, WParam, LParam);
        exit;
      end;
    end;

  inherited DefaultHandler(Message);
end;

procedure TExternalForm.DestroyWindowHandle;
begin
  inherited;
  // control operations
  SetWindowLong(WindowHandle, GWL_WNDPROC, Longint(DefWndProc));
  WindowHandle := 0;

  // restore backed-up properties
  Windows.SetWindowLong(ExternalHWND, GWL_WNDPROC, Longint(FOldWndProc));
  Windows.SetParent(ExternalHWND, FOldParent);
  Windows.SetWindowLong(ExternalHWND, GWL_STYLE, FOldStyle);
  Windows.SetWindowLong(ExternalHWND, GWL_EXSTYLE, FOldExStyle);

  CallWindowProc(FOldWndProc, ExternalHWND, WM_SYSCOMMAND, SC_CLOSE , 0);
  DestroyWindow(ExternalHWND);

  FExternalHWND := 0;
end;

procedure TExternalForm.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
begin
  inherited;
  SetWindowPos(FExternalHWND, 0, ALeft, ATop, AWidth, AHeight,
    SWP_NOZORDER OR SWP_NOACTIVATE );
end;

procedure TExternalForm.SetParent(AParent: TWinControl);
var
  LRecreate: Boolean;
begin
  LRecreate := HandleAllocated;
  if LRecreate then
    UpdateRecreatingFlag(True);
  try
    if (Parent = niland LRecreate then
      DestroyHandle;
    inherited;
    if Parent <> nil then
      Windows.SetParent(ExternalHWND, GetParentHandle);
  finally
    if LRecreate then
      UpdateRecreatingFlag(False);
  end;
end;


Guten Abend Liebe Community,

ich hab mal wieder ein Anliegen. Nachdem ich nun die letzten zwei Tage folgenden Code zusammengestellt habe, bin ich nun in der Lage jede x-beliebige Windows Fenster in mein Programm einzubinden. Sogar TAB finkioniert eins A.

Allerdings muss ich dabei folgendes festellen:

a) DestroyWindow funktioniert nicht mehr, ebenso CloseWindow etc
b) Viselle Themes werden nicht angewendet. Trotz XPMan usw. Wenn ich das Fenster nicht einbinde, bzw das Control freigebe, wird das Fenster so angezeigt wie es sollte

Ansonsten funktioniert das sehr gut. Notepad oder gar Cmd hab ich schon in ein GroupBox eingebunen.
Jetzt hätte ich aber noch gerne, dass es so aussieht wie es soll und dass DestroyWindow klappt.

Hat mir von euch bitte einer eine Idee zu Verbesserung?
Danke!

_________________
- posted with HTC HD2 -


Zuletzt bearbeitet von Steve1024 am Mo 20.06.11 14:48, insgesamt 1-mal bearbeitet
Steve1024 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 141

Windows 2K, XP, 7 & Server 2003 - 2008; Linux (Ubuntu, Fedora)
D7, D05, D06, D09, DXE
BeitragVerfasst: Fr 17.06.11 19:11 
Weiss wirklich keiner Rat?

_________________
- posted with HTC HD2 -
trm
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 491
Erhaltene Danke: 19

Windows 7x64
Delphi 7
BeitragVerfasst: Fr 17.06.11 20:33 
Sendmessage sollte funktionieren.

SendMessage(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0);

Tipp für Win x64: www.delphipraxis.net...-64bit-sc_close.html

Gruß Mathias :)

_________________
In Erfurt gibt es eine Pension, in der es gemütlich ist, Google einfach nach Pension Fiege ;)
Steve1024 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 141

Windows 2K, XP, 7 & Server 2003 - 2008; Linux (Ubuntu, Fedora)
D7, D05, D06, D09, DXE
BeitragVerfasst: Fr 17.06.11 22:10 
Hallo Mathias,
danke für deinen Tipp. Zum Einen habe ich Win7 64bit und zum Anderen funktioniert leider gar nichts.
Weder SendMessage, PostMessage noch der bereits vorhandene Code CallWindowProc(FOldWndProc, ExternalHWND, WM_SYSCOMMAND, SC_CLOSE , 0);.
Ich kann das Fenster nicht schließen und/oder zerstören. Ich bekomme auch keinen Fehlercode zurück. Erst beim zweiten Aufruf bekomme ich die Meldung, dass das Handle ungültig sei, zurück. Das wäre ja, wenn der erste Aufruf so funktioniert hätte wie er soll, auch richtig. Das Fenster wird durch eine DLL aus meinem eignen Programm erzeugt und kann daher wohl weniger ein Berechtigungsproblem sein.

Im Moment habe ich zudem kein 32bit System um es da zu testen.
Dennoch: Unter 64bit sollte es doch auch gehen, oder nicht?

PS: Das Ding ist in XE entwickelt. Ich hoffe daher doch, dass das HWND 64bit kompatibel ist, oder?
PS*: Zu Guter Letzt noch die Frage bzgl der Themes... Warum werden die Controls immer Nativ dargestellt?

Danke für die Hilfe!

_________________
- posted with HTC HD2 -
trm
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 491
Erhaltene Danke: 19

Windows 7x64
Delphi 7
BeitragVerfasst: Fr 17.06.11 22:19 
Probier Dein Tool mal als Admin zu starten.

_________________
In Erfurt gibt es eine Pension, in der es gemütlich ist, Google einfach nach Pension Fiege ;)
Steve1024 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 141

Windows 2K, XP, 7 & Server 2003 - 2008; Linux (Ubuntu, Fedora)
D7, D05, D06, D09, DXE
BeitragVerfasst: Fr 17.06.11 22:28 
Bringt leider auch nichts. Es geht einfach nicht :(

_________________
- posted with HTC HD2 -
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Sa 18.06.11 11:23 
Moin!

Bitte ändere den Titel des Topics, da er wenig über das eigentlich Thema verrät. Hier der entsprechende Absatz aus den Richtlinien:
1.2 Beiträge:
Bitte formuliere den Betreff Deiner Beiträge so, dass andere Mitglieder anhand dieser bereits das eigentliche Thema festmachen können. Beiträge wie etwa "Eine Anfängerfrage" oder "Weiß jemand, wie das geht?" lassen den Leser im Unklaren darüber, was das Thema der Diskussion ist.[...]
Einfach oben bei Deinem ersten Beitrag auf user defined image oder user defined image klicken und den Titel ändern. Danke Dir!

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Delphi-Laie
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1600
Erhaltene Danke: 232


Delphi 2 - RAD-Studio 10.1 Berlin
BeitragVerfasst: Sa 18.06.11 17:05 
user profile iconSteve1024 hat folgendes geschrieben Zum zitierten Posting springen:
bin ich nun in der Lage jede x-beliebige Windows Fenster in mein Programm einzubinden.


Wozu?

Ich fändes es hilfreich, wenn Du wenigstens kurz den Zweck Deines Programmes nennen/vorstellen könntest/würdest.

user profile iconSteve1024 hat folgendes geschrieben Zum zitierten Posting springen:
Sogar TAB finkioniert eins A.


Dito: Wozu und außerdem noch: inwiefern?
Steve1024 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 141

Windows 2K, XP, 7 & Server 2003 - 2008; Linux (Ubuntu, Fedora)
D7, D05, D06, D09, DXE
BeitragVerfasst: Mo 20.06.11 15:19 
Der Zweck ist eigentlich, PlugIns zu entwickeln.
Dabei sollen diese in der Lage sein ein Fenster zu erzeugen was ich dann mittels des HWND in meine Anwenung integriere (zB PageControl).

Dabei ist es wichtig, dass ein Tastatur-Begeisteter User (zB ich) mittels Tab von einem Control zum nächsten springen kann. In der Verganhenheit konnte ich zwar ein Fenster einbinden, aber die TAB Taste hat sich dann immer nur im lokalen Fenster bewegt und nicht auf dem ganzen Fenster Breich (zB TabControl etc).

Dennoch: Schöner Nebenerffekt aktuell ist zB, die CMD in ein Fenster von meiner Anwendung einbinden zu können.
Ich hoffe das war verständlich - und auch dass der Zweck nun klarer ist :-)

Danke!

---Moderiert von user profile iconNarses: Beiträge zusammengefasst---

Achja: Hab das mit dem Fenster schließen und SC_Close nun hinbekommen. Bitte nicht fragen wie, denn ich weiss es nicht. Auf einmal ging es.

Auch mit dem Themes bin ich ein wenig weiter gekommen.
Allerdings reagieren die Steuerelemnte immer noch falsch auf Mausereignisse etc. Hat mir da noch einer einen Tipp?
Bis jetzt habe ich: ControlStyle := [csNeedsBorderPaint, csParentBackground] hinzugefügt. Damit geht es schon halb :-)

Danke für die Hilfe!

_________________
- posted with HTC HD2 -
Steve1024 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 141

Windows 2K, XP, 7 & Server 2003 - 2008; Linux (Ubuntu, Fedora)
D7, D05, D06, D09, DXE
BeitragVerfasst: Mi 29.06.11 20:32 
So... nun hab ich fast alles komplett.
Ich nun nur noch ein Problem: Wenn ich eine TForm einbinde, dann hab ich das Problem, dass ich jedes Control auswählen kann - auch TAB geht - aber, wenn ich direkt auf die Form klicke (nicht der Parent oder ein Child davon (zb. Edit); sondern die eigebunde Form bzw Controls die eigentlich nichts machen sollen (zB. Label)), dann spinnt alles.

Das ganze Fenster reagiert dann nicht mehr. Kein Minimieren, Maximieren, Schließen oder jegliche andere Eingabe. Wenn ich dann den Fokus auf eine andere Anwendung/anderes Fenster lege (durch klick) geht das Fenster wieder.

Hat von euch einer eine Idee warum das so ist?

Danke!

_________________
- posted with HTC HD2 -