Скрытие winform и возвращение его из DLL
В моем DDL я определил следующую функцию:
extern "C" __declspec(dllexport) void hideme(HWND h) {
//ShowWindow(h, SW_HIDE);
SendMessage(h, WM_SHOWWINDOW, FALSE, 0);
}
Как видите, я пробовал несколько вещей, чтобы это работало...
Я объявил это в моей winform следующим образом:
typedef void (*HideMe)(HWND);
В моем событии System::Windows::Forms::Form Load у меня есть следующий код:
...
HINSTANCE hinst = LoadLibrary(_T("My.dll"));
if (hinst == NULL)
System::Diagnostics::Debug::WriteLine("null hinst");
else
hideme = (HideMe) GetProcAddress(hinst, "hideme");
...
В моем событии System::Windows::Forms::Form Shown у меня есть следующий код:
...
hideme((HWND)this->Handle.ToPointer());
...
Я думаю, что проблема должна заключаться в том, как я отправляю через HWND, но я искал весь день и не могу найти альтернативу.
Я также попытался установить это->Visible = false; но тогда я не могу понять, как вызвать его обратно, чтобы увидеть из DLL (злоупотребление sendmessage?).
Я не программист C++, я обычно программирую только на управляемых языках, поэтому любая помощь (и терпение приветствуется.
Спасибо,
Ник.
NB
Одна странная вещь, которую я не могу объяснить, это то, что я не могу вызвать ShowWindow из самой WinForm. Это бросит этот драгоценный камень:
Error 2 error LNK2028: unresolved token (0A00001E) "extern "C" int __stdcall ShowWindow(struct HWND__ *,int)" (?ShowWindow@@$$J18YGHPAUHWND__@@H@Z) referenced in function "private: void __clrcall CheckMSNCpp::frmMain::frmMain_Shown(class System::Object ^,class System::EventArgs ^)" (?frmMain_Shown@frmMain@CheckMSNCpp@@$$FA$AAMXP$AAVObject@System@@P$AAVEventArgs@4@@Z)
Error 3 error LNK2019: unresolved external symbol "extern "C" int __stdcall ShowWindow(struct HWND__ *,int)" (?ShowWindow@@$$J18YGHPAUHWND__@@H@Z) referenced in function "private: void __clrcall CheckMSNCpp::frmMain::frmMain_Shown(class System::Object ^,class System::EventArgs ^)" (?frmMain_Shown@frmMain@CheckMSNCpp@@$$FA$AAMXP$AAVObject@System@@P$AAVEventArgs@4@@Z)
Error 4 error LNK1120: 2 unresolved externals
[EDIT1]
Ханс Пассант сказал:
Сообщение об ошибке компоновщика, которое вы получили при попытке ShowWindow(), также является сильной подсказкой, почему ваш текущий код не работает. Вы забыли добавить код проверки ошибок, GetProcAddress() может завершиться ошибкой и вернет нулевой указатель. Да, функция не экспортируется именем "hideme". В 32-битной сборке он будет экспортирован как "_hideme", обратите внимание на подчеркивание. Который был добавлен, чтобы указать, что функция использует соглашение о вызовах __cdecl. Ошибка компоновщика в ShowWindow демонстрирует оформление имени в C++, вы забыли #include windows.h и создали собственное, неправильное объявление для ShowWindow.
Это неправильный способ сделать это, вы должны просто установить для свойства Visible значение false. Как ты и пытался. Почему вы не можете установить его обратно в истину, совершенно невозможно понять.
То, что вы сказали, не имеет никакого смысла для меня по нескольким причинам.
1)
Импорт для winform:
#include "stdafx.h"
#include <windows.h>
#include <iostream>
#include <stdio.h>
Как вы можете сказать, windows.h там.
2) Ошибка ShowWindor отсутствует в DLL, там я могу назвать это нормально, это в коде WinForm.
3) Я никогда не экспортировал ShowWindow, только мои собственные функции.
[/ EDIT1]
[EDIT2] Уве Кейм сказал:
Зачем вам нужна дополнительная DLL, которая является просто оболочкой для другой функции DLL?
Я бы сделал это, например, в C#, используя PInvoke из вашего управляемого приложения C++. Подпись для SendMessage будет (в C#):
Вещи PInvoke просто не имеют никакого смысла, как сказали комментаторы.
Что касается DLL, она должна быть DLL, потому что мне требуется глобальный хук для ответа на мои горячие клавиши & WH_CBT. В этом случае я хочу, чтобы программа запускалась скрытой и просто показывала экран настроек при нажатии комбинации клавиш.
Все в программе работает, как и ожидалось, горячая клавиша работает как шарм, единственное слабое место, которое я не могу получить, показывает приложение, запущенное из DLL. [/ EDIT2]
[EDIT3] Пример кода по адресу: http://www.nickkusters.com/CPP_PROBLEM_Demo-NOBIN.zip[/ EDIT3]
2 ответа
Сообщение об ошибке компоновщика, которое вы получили при попытке ShowWindow(), также является сильной подсказкой, почему ваш текущий код не работает. Вы забыли добавить код проверки ошибок, GetProcAddress() может завершиться ошибкой и вернет нулевой указатель. Да, функция не экспортируется именем "hideme". В 32-битной сборке он будет экспортирован как "_hideme", обратите внимание на подчеркивание. Который был добавлен, чтобы указать, что функция использует соглашение о вызовах __cdecl. Ошибка компоновщика в ShowWindow демонстрирует оформление имени в C++, вы забыли #include windows.h и создали собственное, неправильное объявление для ShowWindow.
Это неправильный способ сделать это, вы должны просто установить для свойства Visible значение false. Как ты и пытался. Почему вы не можете установить его обратно в истину, совершенно невозможно понять.
Зачем вам нужна дополнительная DLL, которая является просто оболочкой для другой функции DLL?
Я бы сделал это, например, в C#, используя PInvoke из вашего управляемого приложения C++. Подпись для SendMessage
будет (в C#):
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(
IntPtr hWnd,
UInt32 Msg,
IntPtr wParam,
IntPtr lParam);