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 :
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 :
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
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 :
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