|
| Fsmodule Fra : Rasmus |
Dato : 17-02-04 18:24 |
|
Hejsa...
Jeg bruger Borland C++ Builder 6.
Jeg prøver på at lave noget der hedder et fsmodule.
Det er kort sagt en dll fil som automatisk loades ind i Microsoft
Flightsimulator når det startes, hvis den ligger i module mappen.
Jeg har fået et stykke kode, se neden under, som gør en dll kombitabel med
flightsimulatoren. Jeg kompiler koden i BCPPB6 og får min dll,
lægger den i mappen. Men flightsimulator vil ikke godtage den.
Hvis jeg prøver at kompile samme kode i MSVC6 og lægger dll'en i mappen
bliver den loadet i flightsimulator uden problemer.
Mit spørgsmål går på, hvordan kan det være den ikke vil kendes ved bcppb
dll'en? Er der så stor forskel på hvordan den færdige dll er?
Er der nogen måde man kan gøre borland dll'en MSVC kombitabel, eller bare
kombitabel med fs? Gætter på det er det MS har brugt på at udvikle
flightsimulator.
Jeg har også et andet problem. Hvis jeg bruger dll wizard dialogen og vælger
C++, Use of VCL og VC++ Styled DLL og sætter min kode ind kommer
BCPPB med en fejl når jeg kompiler. Multiple decleration for 'Linkage'.
Hvordan undgår jeg det?
------ H Filen (fsmodule.h) ------
//
// Example Micosoft Flight Simulator 2002 Module
//
// Copyright 2001-2002 Joel M. DeYoung
// This code may be freely distributed and modified provided this notice
// remains unchanged.
//
// This is the minimal amount of code required to get Microsoft Flight
Simulator
// to load a DLL that is placed in the modules subdirectory under the main
// FS directory.
//
#ifndef FSMODULE_H_
#define FSMODULE_H_
#include <windows.h>
// We must specify this alignment directive
//
#pragma pack(4)
// Some defines
//
typedef int ID;
typedef unsigned int VAR32;
typedef VAR32 FLAGS32;
#define FSAPI __stdcall
// These are the functions called when loading and unloading the module
//
extern void FSAPI module_init ();
extern void FSAPI module_deinit ();
// These are the two structs that are exported from the DLL
//
typedef struct IMPORTTABLE
{
struct
{
ID fnID;
PVOID fnPtr;
} dummy;
} IMPORTTABLE;
__declspec (dllexport) IMPORTTABLE ImportTable;
typedef struct LINKAGE
{
ID ModuleID;
void (FSAPI *ModuleInit) ();
void (FSAPI *ModuleDeInit) ();
FLAGS32 ModuleFlags;
UINT32 ModulePriority;
UINT32 ModuleVersion;
LPVOID* Table[];
} LINKAGE;
__declspec (dllexport) LINKAGE Linkage;
#pragma pack ()
#endif
------ C filen (fsmodule.c)------
//
// Example Micosoft Flight Simulator 2002 Module
//
// Copyright 2001-2002 Joel M. DeYoung
// This code may be freely distributed and modified provided this notice
// remains unchanged.
//
// This is the minimal amount of code required to get Microsoft Flight
Simulator
// to load a DLL that is placed in the modules subdirectory under the main
// FS directory.
//
#include "fsmodule.h"
#include <windows.h>
// The global exported LINKAGE object
//
LINKAGE Linkage =
{
0x000002d9,
module_init,
module_deinit,
0,
0,
0x800,
{ 0 }
};
// The global exported IMPORTTABLE object
//
IMPORTTABLE ImportTable =
{
{
0x00000000, NULL
}
};
// This function is called by MSFS when the module is initialized
//
void FSAPI module_init ()
{
}
// This function is called by MSFS when the module is unloaded
//
void FSAPI module_deinit ()
{
}
På forhånd tak!
Mvh. Rasmus Steffensen
| |
Bertel Brander (17-02-2004)
| Kommentar Fra : Bertel Brander |
Dato : 17-02-04 21:03 |
|
Rasmus wrote:
> Hejsa...
>
Ikke fordi jeg ved noget om fly simulatorer, men
sidst jeg "legede" med dll'er på borland builer
havde jeg problemer med _
Prøv at sætte/fjene kryds i "Generate Underscores"
i Project Options -> Advanced Compiler.
/b
| |
Ivan Johansen (17-02-2004)
| Kommentar Fra : Ivan Johansen |
Dato : 17-02-04 23:33 |
|
Rasmus wrote:
> Jeg har også et andet problem. Hvis jeg bruger dll wizard dialogen og vælger
> C++, Use of VCL og VC++ Styled DLL og sætter min kode ind kommer
> BCPPB med en fejl når jeg kompiler. Multiple decleration for 'Linkage'.
> Hvordan undgår jeg det?
Med mindre du har tænkt dig at bruge VCL er der ingen grund til at tage
det med.
> __declspec (dllexport) IMPORTTABLE ImportTable;
Her burde der stå:
extern __declspec (dllexport) IMPORTTABLE ImportTable;
> __declspec (dllexport) LINKAGE Linkage;
Her burde der stå:
extern __declspec (dllexport) LINKAGE Linkage;
Derudover tror jeg også det er nødvendigt at følge Bertels råd og slå
"Generate Underscores" fra.
Ivan Johansen
| |
Rasmus (18-02-2004)
| Kommentar Fra : Rasmus |
Dato : 18-02-04 09:38 |
|
Hej...
Tak for svarene!
Jeg har nu fået den til at compile, og fs godtager min dll.
Jeg har videre fået fat i noget mere kode til VC++, den går ud på at finde
flightsimulator vinduet, og i det lave et nyt "sub" vindue.
Mit vindue er en normal VCL form.
Det meste af koden kan jeg godt oversætte, tror jeg, men jeg har nogle
problemer.
Koden hedder:
//search for main FS window
HWND hWndFsMain=FindWindow("FS98MAIN",NULL);
if (hWndFsMain == NULL)
return;
//subclass the FS window
MyWindow* MyWnd = new MyWindow;
if(MyWnd)
{
if(MyWnd->SubClassWindow(hWndFsMain)) //Hvad betyder SubClassWindow?
Jeg kan heller ikke finde funktionen i BCPPB.
{
if(MyWnd->InitialInit()) //create sub windows : InitialInit()
hvad gør den? Er det det samme som Form->Show()?
return;
MyWnd->UnsubclassWindow(); //Den hænger vel sammen med
SubClassWindow? Men den kan jeg heller ikke finde i BCPPB.
} delete MyWnd;
}
På forhånd tak!
Mvh. Rasmus Steffensen
| |
Rasmus (18-02-2004)
| Kommentar Fra : Rasmus |
Dato : 18-02-04 17:00 |
|
Hejsa!
Jeg har prøvet at sætte disse linier ind i min kode:
Form1 = new TForm1(Application);
Form1->Show();
delete Form1;
Men fordi jeg har valgt ikke at lave underscores, kommer linkeren med denne
fejl (Der er faktisk flere, men forsaget af samme):
[Linker Error] Unresolved external '_BeforeDestruction'
Så vidt jeg har forstået er, det noget med at jeg ikke har sat underscores
til, og for at undgå den fejl skal man bruge implib, men jeg kan ikke lige
gennemskue hvordan det gøres?
På forhånd tak!
Mvh. Rasmus Steffensen
| |
Ivan Johansen (18-02-2004)
| Kommentar Fra : Ivan Johansen |
Dato : 18-02-04 18:39 |
|
Rasmus wrote:
> Så vidt jeg har forstået er, det noget med at jeg ikke har sat underscores
> til, og for at undgå den fejl skal man bruge implib, men jeg kan ikke lige
> gennemskue hvordan det gøres?
I stedet for at slå underscores fra globalt kan du lave en def-fil
fsmodule.def med følgende indhold:
LIBRARY FSMODULE.DLL
EXPORTS
ImportTable = _ImportTable
Linkage = _Linkage
Når du tilføjer def-filen til projektet vil de to symboler blive
eksporteret uden underscores.
Ivan Johansen
| |
Rasmus (18-02-2004)
| Kommentar Fra : Rasmus |
Dato : 18-02-04 21:46 |
|
Hejsa...
Takker, nu virker det fint igen!
(har også fået DataModulet til at virke)
Men tilbage til SubclassWindow. Jeg har fundet denne funktion i windowsx.h.
Jeg bruger så denne kode:
HWND hWndFsMain=FindWindow("FS98MAIN",NULL);
Form1 = new TForm1(Application);
Form1->Show();
SubclassWindow(Form1, hWndFsMain);
Hvis jeg compiler det og starter fs, sker der ingen ting, i hvert fald ikke
det jeg forventede.
Så vidt jeg har forstået gør SubclassWindow at min form bliver en slags
MDIChild i vinduet(FS98MAIN), er det rigtigt forstået?
Hvad gør jeg forkert?
Har jeg overhovedet fat i den rigtige funktion? Eller har bcppb en
bedre/lignende funktion?
På forhånd tak!
mvh. Rasmus Steffensen
| |
Ivan Johansen (18-02-2004)
| Kommentar Fra : Ivan Johansen |
Dato : 18-02-04 23:26 |
|
Rasmus wrote:
> Takker, nu virker det fint igen!
> (har også fået DataModulet til at virke)
> Men tilbage til SubclassWindow. Jeg har fundet denne funktion i windowsx.h.
> Jeg bruger så denne kode:
> HWND hWndFsMain=FindWindow("FS98MAIN",NULL);
> Form1 = new TForm1(Application);
> Form1->Show();
> SubclassWindow(Form1, hWndFsMain);
>
> Hvis jeg compiler det og starter fs, sker der ingen ting, i hvert fald ikke
> det jeg forventede.
> Så vidt jeg har forstået gør SubclassWindow at min form bliver en slags
> MDIChild i vinduet(FS98MAIN), er det rigtigt forstået?
Jeg har aldrig lavet noget lignende, men jeg tror nok at det man gør med
SubclassWindow er at du angiver en funktion som skal kaldes hver gang
der sendes en message til det pågældende vindue.
Jeg tror at følgende kan bruges. Funktionen WindowProc kaldes hver gang
der modtages en message. I øjeblikket kalder den bare den oprindelige
funktion, men det kan du selv prøve at tilpasse.
DLGPROC OldWindowProc = NULL;
LRESULT CALLBACK WindowProc(
HWND hwnd, // handle of window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
)
{
return CallWindowProc(OldWindowProc, hwnd, uMsg, wParam, lParam);
}
void FSAPI module_init ()
{
HWND hWndFsMain = FindWindow("FS98MAIN", NULL);
OldWindowProc = SubclassDialog(hWndFsMain, &WindowProc);
}
void FSAPI module_deinit ()
{
HWND hWndFsMain = FindWindow("FS98MAIN", NULL);
SubclassDialog(hWndFsMain, OldWindowProc);
OldWindowProc = NULL;
}
Ivan Johansen
| |
Rasmus (20-02-2004)
| Kommentar Fra : Rasmus |
Dato : 20-02-04 17:21 |
|
Hej igen!
Jeg er ikke helt sikker på jeg forstår koden helt rigtigt. Men efter hvad
jeg har læst i bcppb hjælp tror jeg det er det rette spor. Det subclass gør,
er at den sender messages fra mit FS98MIAN vindue til min Form1, korrekt?
Det jeg håber på er, at få min form til at ligge inde i flightsimulator, og
ikke ligge som et item i taskbaren, som den gør nu.
For det første kan jeg ikke gennemskue hvor min form skal komme ind i koden?
Og hvad betyder WindowProc? Er det WindowProcedure, og i så fald, hvad er
det, og hvad gør det? Så vidt jeg forstod ud af din kode er det en funktion
som bliver kaldet hver gang der sendes en messages til mit vindue?
Et sidste spørgsmål:
MyWnd->InitialInit(), er det det samme som f.eks. Form1->Show()? Hvis ikke,
hvad gør den funktion så?
På forhånd tak!
Mvh. Rasmus Steffensen
| |
Ivan Johansen (22-02-2004)
| Kommentar Fra : Ivan Johansen |
Dato : 22-02-04 22:36 |
|
Rasmus wrote:
> Jeg er ikke helt sikker på jeg forstår koden helt rigtigt. Men efter hvad
> jeg har læst i bcppb hjælp tror jeg det er det rette spor. Det subclass gør,
> er at den sender messages fra mit FS98MIAN vindue til min Form1, korrekt?
Subclass fanger messages som bliver sendt til et eksisterende vindue, i
dette tilfælde et som hedder FS98MAIN hvilket nok er hovedvinduet i
Flight Simulator. På den måde kan du håndtere messages internt i FS.
Hvad det skal bruges til ved jeg ikke.
> Det jeg håber på er, at få min form til at ligge inde i flightsimulator, og
> ikke ligge som et item i taskbaren, som den gør nu.
> For det første kan jeg ikke gennemskue hvor min form skal komme ind i
> koden?
Så tror jeg bare du skal sætte FS vinduet som parent:
HWND hWndFsMain=FindWindow("FS98MAIN",NULL);
Form1 = new TForm1(Application);
Form1->ParentWindow = hWndFsMain;
Form1->Show();
> Og hvad betyder WindowProc? Er det WindowProcedure, og i så fald, hvad er
> det, og hvad gør det? Så vidt jeg forstod ud af din kode er det en funktion
> som bliver kaldet hver gang der sendes en messages til mit vindue?
Nej, det er en funktion som bliver kaldt når der sendes messages til FS
vinduet. På den måde kan du reagere på det brugeren laver i FS vinduet.
Det har i princippet intet med dit vindue at gøre.
> Et sidste spørgsmål:
> MyWnd->InitialInit(), er det det samme som f.eks. Form1->Show()? Hvis ikke,
> hvad gør den funktion så?
Jeg ved det ikke. Jeg har ikke kunne slå den op. Jeg tror at det er en
hjemmelavet funktion.
Ivan Johansen
| |
Rasmus (23-02-2004)
| Kommentar Fra : Rasmus |
Dato : 23-02-04 11:04 |
|
Hejsa...
>HWND hWndFsMain=FindWindow("FS98MAIN",NULL);
>Form1 = new TForm1(Application);
>Form1->ParentWindow = hWndFsMain;
>Form1->Show();
Ja, dette stykke kode virker. Men alligevel ikke helt, min form ligger ikke
mere i taskbaren og er "inde" i flightsimulator nu. Men den er gennemsigtig.
Når jeg starter fs op kan jeg lige hurtig se form'en, men så forsvinder den.
Hvis jeg husker på hvor min form ligger i fs, kan jeg godt flytte rundt på
den. Jeg har også lavet en knap på form'en, og hvis jeg også ved hvor den
ligger, kan jeg trykke på den.
Hvordan får jeg min form visuel, så man kan se den ordentligt?
På forhånd tak!
Mvh. Rasmus Steffensen
| |
Ivan Johansen (23-02-2004)
| Kommentar Fra : Ivan Johansen |
Dato : 23-02-04 18:23 |
|
Rasmus wrote:
> Ja, dette stykke kode virker. Men alligevel ikke helt, min form ligger ikke
> mere i taskbaren og er "inde" i flightsimulator nu. Men den er gennemsigtig.
> Når jeg starter fs op kan jeg lige hurtig se form'en, men så forsvinder den.
> Hvis jeg husker på hvor min form ligger i fs, kan jeg godt flytte rundt på
> den. Jeg har også lavet en knap på form'en, og hvis jeg også ved hvor den
> ligger, kan jeg trykke på den.
> Hvordan får jeg min form visuel, så man kan se den ordentligt?
Jeg ved desværre ikke hvad du skal gøre ved det. Det kunne lyde som om
FS selv vil tegne på hele skærmen, men det lyder lidt mærkeligt. Du
bliver nok nødt til at se i dokumentationen.
Ivan Johansen
| |
Rasmus (18-02-2004)
| Kommentar Fra : Rasmus |
Dato : 18-02-04 20:29 |
|
Hejsa...
Jeg er igang med at lave programkoden til at tilføje et menu item i fs. Til
det skal jeg bruge GetMenu()... Men indtil man har gjort nogle valg i fs er
der ingen menu. Derfor skal jeg bruge en windows timer til at finde ud af
hvornår der er en menu.
Jeg har derfor lavet et DataModule, selvom jeg ikke ved meget om dem. I den
har jeg placeret en TTimer.
Men det er som om datamodulet ikke starter, eller bliver lavet af sig selv
når dll'en bliver loadet.
Hvad er koden for at lave DataModulet? Lidt ligesom når man laver en Form
som ikke er auto-created ( Form1 = new TForm1(Application); ).
På forhånd tak!
Mvh. Rasmus Steffensen
| |
Ivan Johansen (18-02-2004)
| Kommentar Fra : Ivan Johansen |
Dato : 18-02-04 21:18 |
|
Rasmus wrote:
> Hvad er koden for at lave DataModulet? Lidt ligesom når man laver en Form
> som ikke er auto-created ( Form1 = new TForm1(Application); ).
Ja, jeg vil tro at du kan gøre det på samme måde:
TDataModule1 *Data = new TDataModule1(Application);
Hvis Application ikke er tilgængelig, hvilket jeg ikke er klar over om
den er i en DLL, så kan du bruge NULL i stedet og selv nedlægge modulet
når du er færdig med det:
delete Data;
Ivan Johansen
| |
|
|