Autor Beitrag
goose
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 93



BeitragVerfasst: Fr 26.08.05 20:53 
Hallo,

folgendes Problem :

Es gibt den FS2004 von Microsoft.
Dafür kann man sogenannte Module schreiben. Das sind ganz normale *.DLL die in das Modules Verzeichnis des FS
kopiert werden und dann automatisch beim starten des FS geladen werden.
Ich bin nun dabei so ein Modul zu schreiben und brauch ein bischen hilfe.

Hier erst mal die DLL, so wie sie initialisiert werden muss, damit der FS nicht gleich rummeckert, denn das tut
er wenn in der DLL nicht bestimmte Records enthalten sind.

Hier der Ursprüngliche Code dafür :

ausblenden volle Höhe 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:
 library Project1;

uses
  Windows, Messages, module;

const
  cMenuEntryCaption = 'My Mo&dule';
  cMenuEntryItemCaption = 'My &First Menu Entry';
  cMenuEntryID = 40001;

var
  ImportTable: MODULE_IMPORT;
  Linkage: MODULE_LINKAGE;
  OldWndProc: TFarProc;

procedure ModuleInit; stdcall;
begin
end;

procedure ModuleDeinit; stdcall;
begin
end;

function FSimWindowProc(Wnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;

  procedure AddMenu;
  var
    I: Integer;
    Menu, MyMenu: HMENU;
    Buffer: array [0..128] of Char;
  begin
    Menu := GetMenu(Wnd);
    if Menu <> 0 then
    begin
      // Look for our menu entry in the main menu.
      I := 0;
      while I < GetMenuItemCount(Menu) do
      begin
        GetMenuString(Menu, I, Buffer, SizeOf(Buffer), MF_BYPOSITION);
        if Buffer = cMenuEntryCaption then
          // It is already here, we do not need to add it again
          Break;
        Inc(I);
      end;
      if I < GetMenuItemCount(Menu) then
        // It is already here, we do not need to add it again
        Exit;
      {* Create new menu. NOTE: It seems that this will be
       * reached more times, so we cannot save the handle, because
       * in such case it could be destroyed and we will not have
       * any access to it in the simulator.
       *}
      MyMenu := CreateMenu;
      AppendMenu(MyMenu, MF_STRING or MF_ENABLED, cMenuEntryID, cMenuEntryItemCaption);
      AppendMenu(Menu, MF_STRING or MF_POPUP, UINT(MyMenu), cMenuEntryCaption);
    end;
  end;

  procedure DoMenu;
  begin
    // Add your code here
    MessageBox(Wnd, 'It works!', 'HURRAY', MB_OK or MB_ICONEXCLAMATION);
  end;

begin
  case uMsg of
    WM_NCPAINT:
      AddMenu;
    WM_COMMAND:
      if LOWORD(wParam) = cMenuEntryID then
      begin
        DoMenu;
        Result := 0;
        Exit;
      end;
  end;
  Result := CallWindowProc(OldWndProc, Wnd, uMsg, wParam, lParam);
end;

procedure SubClassFlightSim;
var
  HFSimWindow: HWND;
begin
  HFSimWindow := FindWindow('FS98MAIN', nil);
  OldWndProc := TFarProc(SetWindowLong(HFSimWindow, GWL_WNDPROC, Longint(@FSimWindowProc)));
end;

exports
  Linkage,
  ImportTable;

begin
  Linkage.ModuleInit := @ModuleInit;
  Linkage.ModuleDeinit := @ModuleDeinit;
  Linkage.ModuleVersion := $0900; // FS2004 version (use 0x0800 for FS2002)
  SubClassFlightSim;
end.



In der Uses Klausel der library wird auch ein unit namens module eingebunden.
Hier der code der module.pas :

ausblenden volle Höhe 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:
 {* Microsoft Flight Simulator 2004 Module Example.
 *
 * Copyright (c) 2004, Cyril Hruscak.
 * You may freely redistribute and/or modify this code provided this copyright
 * notice remains unchanged. Usage of the code is at your own risk. I accept
 * no liability for any possible damage using this code.
 *
 * It shows how to create a module dll ("Modules" directory of the main
 * FS directory) that can be loaded by the FS2004. It also shows how to add
 * a new menu entry to the main flight simulator menu.
 *}

unit module;

interface

{**
 * This is the module's import table definition.
 *}
type
  TIMPORTSentry = packed record
    fnID: Integer;
    fnptr: Pointer;
  end;

  MODULE_IMPORT = packed record
    IMPORTSentry: TIMPORTSentry;
    nullentry: TIMPORTSentry;
  end;

{**
 * This is the module's export table definition
 *}
  TModuleInit = procedure; stdcall;
  TModuleDeinit = procedure; stdcall;

  MODULE_LINKAGE = packed record
    ModuleID: Integer;
    ModuleInit: TModuleInit;
    ModuleDeinit: TModuleDeinit;
    ModuleFlags: Cardinal;
    ModulePriority: Cardinal;
    ModuleVersion: Cardinal;
    ModuleTable: Pointer
  end;

implementation

end.



So, das compiliert und funktioniert.
Nun macht das ganze aber nix weiter als ein neues Menü 'My Mo&dule' im FS zu erstellen mit einem Eintrag
namens 'My &First Menu Entry'.
Klickt man im FS nun darauf, dann kommt nur eine MessageBox

ausblenden Quelltext
1:
2:
3:
4:
5:
   procedure DoMenu;
  begin
    // Add your code here
    MessageBox(Wnd, 'It works!', 'HURRAY', MB_OK or MB_ICONEXCLAMATION);
  end;




und das wars schon.

Das ganze versuche ich zu erweitern und hab in der uses klausel folgende Unit ( u_main in 'u_main.pas' {Form1} )
eingebunden :

ausblenden volle Höhe 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:
 unit u_main;

interface

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

type
  TForm1 = class(TForm)
    procedure FormShow(Sender: TObject);
    procedure FormDeactivate(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}


procedure TForm1.FormShow(Sender: TObject);
begin
  SetWindowPos(Form1.Handle, hwnd_topmost,0,0,0,0, SWP_NOSIZE or SWP_NOMOVE);
end;

procedure TForm1.FormDeactivate(Sender: TObject);
var
  HFSimWindow: HWND;
begin
  HFSimWindow := FindWindow('FS98MAIN', nil);
  SetWindowLong(Form1.Handle, GetWindowLong(HFSimWindow, GWL_EXSTYLE),GetWindowLong(HFSimWindow, GWL_EXSTYLE));
end;

end.



Das ganze macht auch nix weiter als eine Form anzuzeigen und das wars dann auch schon. Würde aber als Bsp. recihen.
Soweit funktioniert das ganze ja auch schon mal .
Das Problem ist das das Fenster ( und jetzt wirds kompliziert ) immer im Fordergrund bleiben soll wenn es angezeigt wird.
Jedoch wenn es deaktiviert wird ( also wenn man auf das FS Fenster klickt ) soll mein Fenster zwar im Fordergrund bleben,
also weiterhin angezeigt werden und nicht hinter dem FS Fenster verschwinden, aber wenn man dann in dem FS Fenster
einen Button klickt ( z.B. Landelichter anschalten ) dann bewegt sich dieser Button nicht mehr.
( Hoffe das war verständlich ? )
Ich weiss aber genau das das funktioniert, denn bei IVAO ( online fliegen gemeinschaft ) gibt es einen sogenannten Pilot Client
IVAP genannt. Bei dem geht das !
Weiterhin ist es so, das wenn der IVAP angezeigt wird und man den FS minimiert, dann verschwindet auch das IVAP Fenster.
Maximiert man den FS wieder ist auch der IVAP wieder mit da.

Derzeit ist es so das mein Fenster zwar im Fordergrund bleibt, jedoch tut es das auch wenn der FS minimiert wird und ausserdem
gehen die Buttons ( Schalter für Lichter z.B. ) im FS nicht mehr wenn mein Fenster angezeigt wird.

Hat vielleicht jemand einen Plan wie man das lösen könnte ?
Ich hoffe ja.
Falls die erklärung irgendwie unverständlich sein sollte bitte einfach fragen !

Danke
Matthias