Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Как узнать hInstance приложения?


Автор: regis 11.7.2006, 11:49
Subj -- можно как-нибудь это сделать (если входной точкой программы является не WinMain)?
Есть какой-нибудь API для этого или нет?

 

Автор: _hunter 11.7.2006, 12:04
а для чего но тебе нужно?

P.S.
API для нету потому как это работа загрузчика 

Автор: regis 11.7.2006, 13:00
Знать hInstance требуется для множества функций --  RegisterClass, например.

А проблема в том, что я разрабатываю программу на MinGW. Стандартная точка входа -- не WinMain, а обычная main (argc, argv). То есть, видимо, где-то в стандартных библиотеках все-равно вызывается WinMain -- но вот как оттуда извлечь параметр hInstance, не представляю...
 

Автор: _hunter 11.7.2006, 13:26
так ты консольное приложение собираеш (потому и простой main)
там, по-идее, какой-то ключ должен быть... 

Автор: 586 11.7.2006, 13:31
GetModuleHandle(0); 

Автор: Wolf 11.7.2006, 15:02
586 прав, всё простенько очень определяется hInst=GetModuleHandle(NULL); 

Автор: regis 13.7.2006, 11:00
586 и Wolf, огромное спасибо! Это именно то, что было надо.

По поводу приложения: да, оно у меня консольное -- но вместе с тем, иногда возникает необходимость работать с окнами. Желательно как-то совместить консольный и оконный интерфейсы. В связи с этим плавно переходим к следующему вопросу -- как это лучше сделать.  smile 

Поясню вопрос. Пока что все работает примерно так: нормальный режим -- консольный, но в определенные моменты входим в "оконный режим": открываем одно (2, 3, N...) окошек и запускаем традиционный цикл обработки сообщений (while (GetMessage (...) { TranslateMessage (...); DispatchMessage (...); })) Когда закрывается последнее окно, покидаем цикл и возвращаемся в консольный режим. Все работает, но хотелось бы сделать как-нибудь поизящнее, что ли... Если будут какие-нибудь идеи, буду благодарен.

 

Автор: Exekutor 13.7.2006, 12:33
Просто создавай окна из консоли с помощью CreateWindowExA 

Автор: 586 13.7.2006, 12:45
Код
#include <windows.h>
#include <stdio.h>

char* GetErrDscr()
{
    char *p;
    FormatMessage(0x1100, 0, GetLastError(), 0, (char*)&p, 0, 0);
    return p;
}

int _stdcall MainWndProc(HWND, UINT, WPARAM, long);
long pMainWndProc;

int width=640, height=480;
HWND hMainWnd;
HINSTANCE hinst;

int __cdecl main(int argc, char** argv)
{
 MSG msg;
 hinst=GetModuleHandle(0);
 hMainWnd=CreateWindowEx(0, (char*)32770, "Test application", WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_SIZEBOX, 
     (GetSystemMetrics(SM_CXSCREEN)-width)/2, (GetSystemMetrics(SM_CYSCREEN)-height)/2, width, height, 0, 0, hinst, 0);
 if(!hMainWnd){MessageBoxA(0, GetErrDscr(), "Failed to create main window", 16); return 1;}
 pMainWndProc=SetWindowLong(hMainWnd, GWL_WNDPROC, (long)MainWndProc);

 while(IsWindow(hMainWnd))
 {
    if(!GetMessage(&msg, hMainWnd, 0, 0)) break;
    TranslateMessage(&msg);
    DispatchMessage(&msg);
 }
 return 0;
}

int _stdcall MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, long lParam)
{
 switch(uMsg)
 {
    case WM_CLOSE: DefWindowProc(hWnd, WM_CLOSE, 0, 0); break;
 }
 return CallWindowProc((WNDPROC)pMainWndProc, hWnd, uMsg, wParam, lParam);
}
 
Если окно диалоговое - юзай DialogBoxParam или CreateDialogParam

Автор: regis 20.7.2006, 11:34
586, спасибо. Идея насчет использования IsWindow неплохая...
 

Автор: GremlinProg 20.7.2006, 12:54
только не используй GetModuleHandle(NULL) в DLL, она вернет дескриптор программного модуля, а не самой библиотеки. 

Автор: SeregaLBN 20.7.2006, 17:09
В длл пользуйтесь HINSTANCE GetCurrentInstance()
Код

inline HINSTANCE __stdcall GetInstanceFromAddress(PVOID pEip) { // возвращает HINSTANCE модуля, из которого была вызвана эта функция (© Alex Fedotov rsdn)
   _ASSERTE(pEip != NULL);

   MEMORY_BASIC_INFORMATION mem;
   if (VirtualQuery(pEip, &mem, sizeof(mem)))
   {
      _ASSERTE((mem.Type == MEM_IMAGE) || (mem.Type == MEM_PRIVATE));
      _ASSERTE(mem.AllocationBase != NULL);
      return (HINSTANCE)mem.AllocationBase;
   }
   return NULL;
}

inline __declspec(naked) HINSTANCE __stdcall GetCurrentInstance() // возвращает HINSTANCE модуля, из которого была вызвана эта функция (© Alex Fedotov rsdn)
{
   /** / // VC 7.0 поддерживат intrinsic-функцию с именем _ReturnAddress, которая возвращает адрес возврата из текущей функции.
         // С ее помощью можно обойтись и без ассемблера.
         // Но самое интересное в том, что на VC 6.0 она тоже поддерживается (уж не знаю, начиная с какого SP),
         // так что вот этот код без проблем компилируется и работает на моем VC 6.0 SP5
   MEMORY_BASIC_INFORMATION mem;
   if (VirtualQuery(_ReturnAddress(), &mem, sizeof(mem))) {
      _ASSERTE((mem.Type == MEM_IMAGE) || (mem.Type == MEM_PRIVATE));
      _ASSERTE(mem.AllocationBase != NULL);
      return (HINSTANCE)mem.AllocationBase;
   }
   return NULL;
   /**/
   __asm {
#ifdef _M_IX86
      mov   eax, [esp]
      push  eax
      jmp   GetInstanceFromAddress
#else
      #error This machine type is not supported.
#endif
   }
}



самому ещё не довелось проверить... 

Автор: GremlinProg 20.7.2006, 17:28
я пробовал VirtualQuery в DLL, mem.AllocationBase вернет все тот же программный модуль, а не DLL. Ассемблер можно даже не использовать, просто указать адрес любого локального метода.

Чтобы получить реальный дескриптор нужно пройтись по всем модулям текущего процесса(используя EnumProcessModules из апешки Psapi), затем получить их стартовые точки(EntryPoint) и сравнить их с DllMain для текущей библиотеки. чтобы получить EntryPoint нужно вызвать GetModuleInformation.

Мороки много а толку мало, поэтому проще обработать hinstDLL в DllMain и сохранить глобально, это не так уж и накладно. 

Автор: Damarus 21.7.2006, 08:54
Цитата(SeregaLBN @  20.7.2006,  18:09 Найти цитируемый пост)
В длл пользуйтесь HINSTANCE GetCurrentInstance()


За чем smile В длл пользуйтесь GetModuleHandle(TEXT("name.dll"));. 

Автор: GremlinProg 21.7.2006, 09:06
Цитата

В длл пользуйтесь GetModuleHandle(TEXT("name.dll"));

Тогда для каждой длл нужно отдельно писать такую вещь, или заводить макрос с именем длл, т.е. для методов, использующих hInstance в длл придется писать отдельный от exe код. Муторно. 

Автор: 586 21.7.2006, 10:43
Цитата(Damarus @  21.7.2006,  09:54 Найти цитируемый пост)
В длл пользуйтесь GetModuleHandle(TEXT("name.dll"));.  

Damarus, а что, если модуль с таким именем уже загружен. База какого модуля будет получена? 

Автор: Damarus 21.7.2006, 12:19
586, да, об этом я не подумал.  

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)