Pb avec CreateWindow - Programmation
Marsh Posté le 15-07-2002 à 08:49:59
tu dois mettre le hInstance passé en paramètre à WinMain :
int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
Marsh Posté le 15-07-2002 à 09:46:39
J'en sais rien du tout !
Ce que je sais, c'est que sous 2000/XP, ce champ est désormais inutile.
Marsh Posté le 15-07-2002 à 14:48:34
Harkonnen a écrit a écrit : J'en sais rien du tout ! Ce que je sais, c'est que sous 2000/XP, ce champ est désormais inutile. |
Dés que tu fais une application win32 hinstance vaut NULL tout le temps...
Marsh Posté le 15-07-2002 à 16:43:28
oui, ils ont conservé ceci afin de rester compatible avec les applications écrites pour 3.11
Marsh Posté le 15-07-2002 à 16:49:26
Harkonnen a écrit a écrit : oui, ils ont conservé ceci afin de rester compatible avec les applications écrites pour 3.11 |
Je m'en doutais un peu mais c tjrs bon à signaler
Marsh Posté le 15-07-2002 à 19:32:09
Ok, pas la peine de s'emmerder a conserver la valeur dans un HINSTANCE alors!
Marsh Posté le 15-07-2002 à 21:09:11
boaf, garde le quand meme, il ressert. par ex, la je vins de faire un LoadBitmap(). Avec hInstance = NULL ca passe pas, avec celui donné par win ca marche. donc bon.....
Marsh Posté le 16-07-2002 à 09:43:01
Y'a aucun autre moyen de récuperer cette valeur? Une fonction dans le style GetModuleHandle par exemple
Marsh Posté le 16-07-2002 à 10:59:39
letoII a écrit a écrit : Dés que tu fais une application win32 hinstance vaut NULL tout le temps... |
C'est pas plutot hPrevInstance qui est toujours à NULL
Marsh Posté le 16-07-2002 à 11:04:05
autant pour moi, c bien le hPrevInstance. petite confusion.
Marsh Posté le 16-07-2002 à 12:40:12
Ace17 a écrit a écrit : Y'a aucun autre moyen de récuperer cette valeur? Une fonction dans le style GetModuleHandle par exemple |
tu peux préssuposer qu'il a 0x4000000 comme valeur (je suis pas sur du nb de 0
)
Marsh Posté le 16-07-2002 à 15:06:54
0x00400000
Mais bon ca c'est l'addresse virtuelle du début du programme mappé en mémoire... Je crois que ce n'est pas la meme chose qu'un HINSTANCE
Marsh Posté le 16-07-2002 à 15:17:30
c'est du moins la valeur qui transite généralement par le winmain au param hInstance
Marsh Posté le 16-07-2002 à 15:18:34
Ah ouais? Autant pour moi, je sais donc maintenant enfin ce que représente un HINSTANCE!
Marsh Posté le 16-07-2002 à 15:24:29
C'est tout con. Un hInstance est un handle d'instance, comme un hWnd est un handle de fenêtre. Comme un programme peut être lancé plusieurs fois, le hInstance permet d'identifer l'instance en cours d'éxécution.
Marsh Posté le 16-07-2002 à 15:27:45
OUais sauf que je vois pas trop comment une addresse mémoire virtuelle permettrait d'identifier une instance d'application!
Marsh Posté le 16-07-2002 à 15:28:51
Ben moi non plus ! Qu'est ce que ça vient foutre ici ça ???
Marsh Posté le 16-07-2002 à 15:30:55
chrisbk a écrit a écrit : c'est du moins la valeur qui transite généralement par le winmain au param hInstance |
(en parlant de 0x400000, qui est la VA standard d'un programme)
Marsh Posté le 16-07-2002 à 15:36:42
Attention hein !
GetModuleHandle retourne un HMODULE, pas un HINSTANCE !
De toute façon, un hInstance n'a strictement rien à voir avec la VA, il s'agit d'une valeur interne utilisée uniquement à des fins d'identification de l'instance en cours.
Je vois vraiment pas ce que la VA vient foutre ici, ça n'a rien à voir !
Marsh Posté le 16-07-2002 à 15:40:02
Harkonnen a écrit a écrit : Attention hein ! GetModuleHandle retourne un HMODULE, pas un HINSTANCE ! De toute façon, un hInstance n'a strictement rien à voir avec la VA, il s'agit d'une valeur interne utilisée uniquement à des fins d'identification de l'instance en cours. Je vois vraiment pas ce que la VA vient foutre ici, ça n'a rien à voir ! |
ah ben moi, je dis pas, néanmoins c ca que je recois, hein?
Non coupable, votre honneur
Marsh Posté le 16-07-2002 à 15:40:28
MDR j'avais compris Harko t'inquiete pas c'est juste que cette histoire de 0x400000 introduite par chrisbk m'avait troublé
Marsh Posté le 16-07-2002 à 15:43:47
T'es sur que tu la recois dans le winmain? T'as pas utilisé GetModuleHandle plutot?
Marsh Posté le 16-07-2002 à 15:46:46
Oui, je suis sur comme toi qu'il a utilisé GetModuleHandle.
Marsh Posté le 16-07-2002 à 17:04:19
Si si, le hInstance est lié au format PE ...
C'est l'adresse à laquelle le programme souhaite etre charge. (y'a un champ dans les header PE qui le précise)
Il ne vaut pas forcement 0x400000, un exe pouvant vouloir etre charge a une autre adresse. Il est aussi different pour les dll.
Il est utile parce qu'il permet de localiser l'emplacement en mémoire de l'executable.
Ainsi, quand tu fais un LoadCursor ou n'importe quel Load qui a va charger une ressource depuis ton fichier executable cette valeur est nécessaire afin de localiser le debut de l'exe en mémoire et a partir de la trouver les ressources (l'exe du disque est betement charge t(el quel en memoire). Tu peux utiliser cette valeur pour te ballader dans les header du PE de ton exe loadé ... tu peux ainsi trouver la version du linker et plein d'autres trucs ...
c'est ce que fait la lib CRT pour les curieux.
Et ce hInstance est bien obtenu via GetModulHandle ...
C'est le hPrevInstance qui vaut nul est qui est hérité de Win31
harkonnen > ou as tu vu que c'etait inutile ?
J'avais pose la question sur un new car je m'etais appercu suite a un bug tout con que je pasais NULL et que ca marchait quand meme ... on m'a pas dit que c'etait normal mais plutot que j'ai eu de la chance ... (je faisais pas d'appel a LoadXXX etc ...)
Car dans ce cas comment fait on pour distinguer les ressources standards de Windows (LoadIcon(NULL, IDI?APPLICATION)) de celles de mon exe (LoadIcon(hInstance, XXX))
Marsh Posté le 16-07-2002 à 17:36:15
HelloWorld a écrit a écrit : harkonnen > ou as tu vu que c'etait inutile ? |
http://msdn.microsoft.com/library/ [...] window.asp
Citation : |
je viens de faire un test sur la valeur de hInstance : la VA de mon programme et hInstance sont totalement différents ! je tourne sous XP
Marsh Posté le 16-07-2002 à 18:35:58
Un truc qui cloche dans la distinction des instances par leur addresse virtuelle, c'est que c'est virtuel justement... cad que chaque instance se verra a l'addresse 400000...donc pour la distinction pas terrible quoi
Marsh Posté le 16-07-2002 à 18:43:48
Harkonnen a écrit a écrit : Oui, je suis sur comme toi qu'il a utilisé GetModuleHandle. |
que nenni, break point a l'entrée du winmain et quickwatch sur le hinstance
(merci de me prendre pour un con )
Marsh Posté le 16-07-2002 à 19:22:21
on ne te prends pas pour un con, on essaie de comprendre!
Marsh Posté le 16-07-2002 à 19:48:14
Ace17 a écrit a écrit : Un truc qui cloche dans la distinction des instances par leur addresse virtuelle, c'est que c'est virtuel justement... cad que chaque instance se verra a l'addresse 400000...donc pour la distinction pas terrible quoi ![]() |
Peut être que le hInstance n'est pas l'identifiant, mais l'adresse de l'identifiant (dans le processus)
Je dis ca, je dis rien, hein, c'est juste une hypothèse
Marsh Posté le 16-07-2002 à 22:44:14
Je suis sur qu'on se prend la tete pour pas gd chose avec ce hInstance...
De toute façon, CreateWindow n'en a plus besoin sous 2000/XP, et comme les softs seront tous développés dessus à l'avenir, moi je dis : ON S'EN TAPE !!!
Marsh Posté le 17-07-2002 à 09:07:35
Non faux! Ca c'est la solution de facilité! Moi je veux comprendre
Marsh Posté le 17-07-2002 à 09:43:55
Apres quelques expériences, HINSTANCE correspond bien a la base d'image ( 0x00400000 ), mais dans ce cas, pourquoi donner ce parametre a WinMain alors qu'on peut tres bien récuperer ca avec GetModuleHandle?
Marsh Posté le 17-07-2002 à 09:50:56
Et surtout, comme tu le disais, comment différencier les différentes instances ?
Marsh Posté le 17-07-2002 à 10:00:50
Ben peut etre que ca ne sert qu'a différencier les différentes instances mais du point de vue de cette instance la!
Marsh Posté le 17-07-2002 à 14:57:09
J'avais posé cette question sur un newsgroup.
On m'avais un peu pris pour un newbie à demander a quoi servait ce paramètre et personne ne m'a vraiment dit pourquoi il fallait le passer.
Ce qu'on m'a dit c'est que le terme d'instance n'avait plus de sens sous Win32. On a gardé ce nom mais il a un autre sens. Instance de quoi ?
Ce n'est pas une instance mais l'adresse virtuelle a laquelle est chargée le programme en mémoire.
0x400000 = 4 Mo.
L'executable est chargé à partie du 4° Mo.
Le 1° Mo c'est pas touche a cause du DOS et des ROM BIOS et tout ca, les 3 autres Mo il me semble que c'est plus ou moins réservé (perdu ?) pour les programmes Win31.
Le programme dispose ensuite de 2Go.
Le 3° Go, ce sont les dll qui sont chargées (zone de mémoire partagée) et le dernier Go c'est pour le système (VXD, ...)
On m'a aussi dit que supposer que hInstance valait toujours 0x400000 était mal car cela peut varier en fonction des plateformes (Alpha, Win64 ?)
Pour l'histoire du champ PE, je persiste à dire que cela correspond a l'adresse de base a laquelle est chargé l'exe / dll. Cette adresse est fixée par le linker et peut etre modifiée via l'option /REBASE.
Consulte la doc du linker.
Citation : Provides a beginning address for reassigning base addresses to the files. Specify address in decimal or C-language notation. If BASE is not specified, the default starting base address is 0x400000. If DOWN is used, BASE must be specified, and address sets the end of the range of base addresses. |
Pour un exe faut pas y toucher, mais pour une dll cela peut etre utile. En effet, si ton programme charge beaucoup de dll, celles ci ne pourront pas etre chargées a la même adresse et Windows effectura une rellocation et cela prend du temps et rallentit le chargement du programme (ou plutot des dll qu'il utilise).
cf la doc sur l'utilitaire REBASE
Rebase is a command-line tool that you can use to specify the base addresses for the DLLs that your application uses.
Citation : The base address of a DLL is the location in virtual memory where the loader attempts to place the DLL. It is generally specified at link time. If a DLL cannot load at its base address because the memory is already occupied, the loader places the DLL elsewhere in virtual memory, then updates all calls into the DLL to reflect the new base address. Making these changes can be time consuming, because the image must be copied to the pagefile and modified for the new address. If you have a large application that uses many DLLs, it is important for each DLL to have a different base address to minimize load time. You will receive the following warning from the loader if a DLL is relocated. |
Citation : pourquoi donner ce parametre a WinMain alors qu'on peut tres bien récuperer ca avec GetModuleHandle? |
Ce paramètre n'est pas passé à WinMain par Windows ... La seule chose qui se trouve sur la pile d'un exe lorsqu'il est lancé par kernel32 c'est l'adresse de retour dans kernel32, ce qui est utilise par des bidouilleurs pour se substituer à GetProcAdress.
Aucun paramètre ...
En fait, ton programme ne commence pas à WinMain ...
Il y a une routine qui se charge d'appeler WinMain. En C, le code de cette routine est souvent contenu dans crt0.c
Installe les sources des la lib CRT et farfouille.
Il y a plein de "statup routines" différentes ... Une pour le WinMain, une pour le main dans le cas d'un programme console, une pour un wWinMain (UNICODE).
C'est ce startup code qui se charge de récupérer les paramètre de la ligne de commande, de récupérer hInstance via GetModuleHandle ... qui se charge aussi d'initialiser la lib CRT (préparation pour les malloc et autres ...), peut aussi en cpp initialiser le traitement des exceptions ...
Enfin cette routine appelle WinMain avec les paramètres ...
C'est pour cela que l'on a des fois l'erreur "unresolved external symbol WinMain" quand on créé un projet Win32 et que l'on utilise main.
Parce que ce n'est pas la bonne "startup" routine qui est utilisée.
C'est comme en assembleur. Un programme en assembleur (bien écrit) sous Windows commence par retrouver les paramètres et appeler une fonction WinMain ...
Code :
|
Je pense que si Microsoft procède ainsi (laisser une startup routine faire ca au lieu d'empiler les paramètres comme cela est fait pour une dll) c'est parce qu'un programme peut etre nativement UNICODE ou ANSI.
Ainsi un programme peut choisir entre GetCommandLineA et GetCommandLineW ...
C'est la seule explication que j'ai trouvé. On peut aussi rajouter la compatibilité avec Win31 ... surement qu'avant le hInstance etait tres utile ... ca doit etre la raison principale en fait.
Marsh Posté le 17-07-2002 à 16:11:36
Ok, donc le hInstance n'est qu'une addresse mémoire virtuelle, et on récupere la meme chose avec GetModuleHandle...
Donc on ne peut pas distinguer différentes instances du meme programme avec ca
Marsh Posté le 15-07-2002 à 02:08:02
Salut à tout le monde. J'ai un petit problème avec la fonction :
HWND CreateWindow( LPCTSTR lpClassName,
LPCTSTR lpWindowName,
DWORD dwStyle,
int x,
int y,
int nWidth,
int nHeight,
HWND hWndParent,
HMENU hMenu,
HINSTANCE hInstance,
LPVOID lpParam
);
Je sais pas ce qu'il faut mettre comme paramètre dams HINSTANCE, sur msdn ils disent que c'est une instance mais je sais pas à quoi ça correspond.
Merci