responsabilità: Io non sono un esperto di IDL (Interface Definition Language, che è il linguaggio utilizzato per definire tipi COM) o il compilatore Microsoft IDL (MIDL), ma sono venuto a conclusioni di seguito dopo aver giocato in giro con la libreria dei tipi per scrrun.dll, che ha un problema simile con enum. Alcune di queste informazioni sono state raccolte da un rapido sguardo a questo articolo DevX su IDL e VB6: IDL for VB Tutorial
VB6 si aspetta che l'enum reale di avere un nome, non solo un enum che è typedef
'd a un nome. Il nome __MIDL___MIDL_itf_autosvcs_0469_0002
è un segnaposto, poiché il typelib originale non ha definito il nome enum nello stesso typedef
in cui sono definite le costanti enum.
Quando si visualizza la libreria dei tipi nel Visualizzatore OLE, il enum
probabilmente assomiglia a questo:
typedef [public] __MIDL___MIDL_itf_autosvcs_0469_0002 LockModes;
typedef enum {
LockSetGet = 0,
LockMethod = 1
} __MIDL___MIDL_itf_autosvcs_0469_0002;
La prima typedef
crea il nome pubblico LockModes
come alias per il MIDL___MIDL_itf_autosvcs_0469_0002
nome generato automaticamente che è stato dato a il enum
. Quando è stata compilata la libreria di tipi originali, il compilatore midl
ha generato il nome lungo e ha creato automaticamente un alias typedef
che punta ad esso.
L'IDL originale probabilmente definito l'enumerazione in questo modo:
typedef enum {
LockSetGet = 0,
LockMethod = 1
} LockModes;
Quando il compilatore midl
elabora un enum
definizione scritta in questo modo, si auto-genera un nome per il enum
(dal momento che manca - dovrebbe appare dopo la parola chiave enum
). Questo è il nome __MIDL
che viene visualizzato quando si visualizza la libreria dei tipi in OLE Viewer. Il compilatore midl
genera inoltre automaticamente un secondo typedef
che alias il nome typedef
al nome generato automaticamente enum
.
Il problema è che VB6 non può comprendere enum che vengono creati in questo modo. Si aspetta di tutto per essere in un unico typedef
(cioè si dà il nome enum
, nonché nominare il typedef
):
typedef enum LocksMode {
LockSetGet = 0,
LockMethod = 1
} LocksMode;
IDL ossequi typedef
's allo stesso modo in cui C o C++ fa: si don' Devo dare all'enum stesso un nome, perché lo typedef
ha già un nome, ma tu puoi dare all'enumerazione un nome se lo desideri. In altre parole, lo typedef
e lo enum
sono in realtà due entità separate. VB6 capita di riconoscere il e il enum
come due cose distinte, ma vagamente correlate, quindi nel tuo caso vede une vede che questo è un alias di un enum senza nome, e vede anche un typedef
per LockModes
, che è un alias pubblico per l'altro typedef
.
Dal primo typedef
è pubblica, si vedrà una voce per LockModes
nel Visualizzatore oggetti, sia perché è un alias per un enum, vedrete le costanti enum nel Visualizzatore oggetti pure. Tuttavia, l'enum stesso non ha un nome (quindi ottiene il nome auto-generato funky assegnato ad esso nel browser), e VB6 non può usare l'enumerazione perché il nome generato automaticamente è illegale in VB6 (i nomi con caratteri di sottolineatura doppio vengono automaticamente nascosti in VB6).
Per dimostrare quest'ultimo punto, se si digita questo nel codice VB6, Intellisense funzionerà e sarà la compilazione, ma ovviamente, non è molto ideale:
MsgBox COMSVCSLib.[__MIDL___MIDL_itf_autosvcs_0469_0002].LockMethod
Il motivo per cui questo codice funziona è perché si è possibile inserire nomi che normalmente causano errori di sintassi (come i nomi che iniziano con caratteri di sottolineatura) tra parentesi per consentire a VB6 di accettare il nome normalmente non valido. Inoltre, il prefisso delle costanti con il nome generato automaticamente funziona con Intellisense perché è il nome effettivo che VB6 associa allo enum
(ricorda che l'altro typedef
è solo un alias di questo "reale", ma il nome generato automaticamente, e Apparentemente VB6 non può mettere insieme tutti i pezzi per realizzare entrambi i nomi riferiti allo stesso enum
).
Piuttosto che digitare il nome ridicolmente lungo come sopra, è possibile anche accedere alle costanti enum
inserendo il prefisso con il nome della libreria, ad esempio, COMSVCSLib.LockMethod
dovrebbe funzionare. Non mi è chiaro perché funzioni effettivamente, e non sono sicuro di cosa succederebbe se due diverse costanti di tipo enum
definissero lo stesso nome.
Infine, si potrebbe risolvere questo problema un modo diverso utilizzando l'IDL dal Visualizzatore OLE per creare un file IDL personalizzato, in cui si sostituiscono le attuali enum
typedef con un singolo typedef
per ogni enum
che dà semplicemente sia la enum
e lo typedef
lo stesso nome (ovvero typedef enum LockModes { ... } LockModes;
), ma dal momento che OLE Viewer non genera necessariamente IDL valido, probabilmente lo si dovrà modificare ulteriormente per farlo compilare. Se riesci a far funzionare tutto questo, puoi fare riferimento alla tua .tlb
personalizzata dal progetto VB6 (invece della libreria COMSVCSLib
) e gli enum
funzioneranno come ti aspetteresti.
Se si vuole seguire questa strada, ci sono altri due strumenti necessari, che dovrebbero già stato installato sul computer di sviluppo (ma potrebbe essere necessario per la ricerca di loro):
midl.exe
: Questo lo strumento può generare un file typelib (* .tlb) da un file .idl
. Così si potrebbe copiare l'IDL dal Visualizzatore OLE in Blocco note, modificare le definizioni enum come descritto sopra, salvarlo come file .idl
, e passarlo al midl.exe
di fare una nuova libreria dei tipi:
midl my-custom-typelib.idl
regtlib.exe
: Questo strumento può registrare un file tLB, che è necessario se si vuole essere in grado di aggiungerlo come un riferimento al progetto VB6:
regtlib.exe my-custom-typelib.tlb
Tuttavia, la creazione di una libreria dei tipi personalizzata per questo è probabilmente eccessivo e, come già accennato, potrebbe essere difficile ottenere un file IDL compilabile basato sull'output dal Visualizzatore OLE, poiché visualizza IDL con reverse engineering per la libreria dei tipi, non l'IDL originale.
@wqw: Non sono sicuro di tutti i dettagli tecnici - questa risposta è basata su test empirici. Ad esempio, se si esegue l'IDL per scrrun.dll che OLE Viewer genera e lo compila in una nuova libreria di tipi con 'midl.exe', VB6 può vedere l'enum correttamente se si assegna il nome e il typef dell'enumerazione a un nome in l'IDL. Altrimenti, vedrai il nome 'enum' nel Browser degli oggetti, ma IntelliSense non funzionerà correttamente, e se guardi le costanti enum nel Browser degli oggetti, dirà che l'enum è membro di un enum con un'auto -generazione –
Non è nemmeno necessario creare una nuova libreria di tipi per vedere questo: basta aggiungere un riferimento a 'scrrun.dll' in un nuovo progetto VB6, quindi aprire il Visualizzatore oggetti e osservare l'enumerazione' SpecialFolderConst'. Sì, viene visualizzato nel Visualizzatore oggetti e sì le costanti sono elencate per esso, ma se si fa clic sulla costante 'SystemFolder', ad esempio, il Visualizzatore oggetti dice che è un membro di' Scripting .__ MIDL ___ MIDL_itf_scrrun_0001_0000_0002'. Dovrebbe dire che la costante è un membro di 'Scripting.SpecialFolderConst', ma il modo in cui è definita la libreria dei tipi non è compatibile al 100% con VB6. –
Inoltre, sto dicendo di provare a dire che la mia risposta è perfetta (questo è il motivo per cui ho messo un disclaimer lì), ma per quanto posso dire, questa spiegazione si adatta ai test effettivi. Ho creato una nuova libreria dei tipi per sccrun.dll e ho modificato enum typedef per includere i nomi enum oltre ai nomi typedef e quando aggiungo la libreria dei tipi a VB6, l'enum si visualizza correttamente nel Browser degli oggetti, le costanti enum sono elencati come membri dell'enumerazione corretta e IntelliSense funziona correttamente.Se, tuttavia, i dettagli tecnici effettivi sono errati, potresti fornire una risposta con le informazioni corrette? –