Скрытие 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, но я искал весь день и не могу найти альтернативу.

Я также пытался установить this->Visible = false; но тогда я не могу понять, как вызвать его обратно к видимому из DLL (злоупотребление sendmessage?).

Я не программист на C++, обычно я программирую только на управляемых языках, поэтому любая помощь (и терпение приветствуются.

Спасибо,

Ник.

N.B.

Одна странная вещь, которую я не могу объяснить, заключается в том, что я не могу вызвать 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() может завершиться ошибкой и вернет указатель NULL. Будет, функция не экспортируется под именем "hideme". В 32-битной сборке он будет экспортирован как «_hideme», обратите внимание на подчеркивание. Это было добавлено, чтобы указать, что функция использует соглашение о вызовах __cdecl. Ошибка компоновщика в ShowWindow демонстрирует украшение имени C++, вы забыли #include windows.h и составили собственное, неправильное объявление для ShowWindow.

Это неправильный способ сделать это, вы должны просто установить для свойства Visible значение false. Как ты пытался. Почему вы не можете установить его обратно в true, совершенно непонятно.

То, что вы сказали, не имеет для меня никакого смысла по нескольким причинам.

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 будет (в С#):

Материал PInvoke просто не имеет никакого смысла, как говорили комментаторы.

Что касается DLL, это должна быть DLL, потому что мне нужен глобальный хук, чтобы реагировать на мои горячие клавиши и WH_CBT. В этом случае я хочу, чтобы программа запускалась скрыто и просто показывала экран настроек при нажатии комбинации клавиш.

Все в программе работает как положено, горячая клавиша работает как шарм, единственная тонкость, которую я не могу понять, показывает приложение, запускаемое из DLL. [/EDIT2]

[EDIT3] Пример кода по адресу: http://www.nickkusters.com/CPP_PROBLEM_Demo-NOBIN.zip [/EDIT3]


person NKCSS    schedule 28.05.2011    source источник
comment
Это странно на многих уровнях. Нет необходимости в прямом win32, чтобы скрыть форму. В любом случае нет необходимости в DLL, можно использовать Pinvoke. Из управляемого C++ вы все равно можете вызывать win api напрямую. Наконец, вы не отправляете это сообщение, оно отправляется вам. Прочтите документацию еще раз. Чтобы скрыть окно в Win API, вызовите ShowWindow.   -  person David Heffernan    schedule 28.05.2011
comment
Я бы с удовольствием это сделал, но вызов ShowWindow с this-›Handle.ToPointer() не работает.   -  person NKCSS    schedule 28.05.2011
comment
Похоже, мы не можем вам помочь. Удачи.   -  person David Heffernan    schedule 28.05.2011
comment
Источник демо @ nickkusters.com/CPP_PROBLEM_Demo-NOBIN.zip   -  person NKCSS    schedule 28.05.2011


Ответы (2)


Сообщение об ошибке компоновщика, которое вы получили при попытке ShowWindow(), также является подсказкой, почему ваш текущий код не работает. Вы забыли добавить код проверки ошибок, GetProcAddress() может завершиться ошибкой и вернет указатель NULL. Будет, функция не экспортируется под именем "hideme". В 32-битной сборке он будет экспортирован как «_hideme», обратите внимание на подчеркивание. Это было добавлено, чтобы указать, что функция использует соглашение о вызовах __cdecl. Ошибка компоновщика в ShowWindow демонстрирует украшение имени C++, вы забыли #include windows.h и создали собственное, неверное объявление для ShowWindow.

Это неправильный способ сделать это, вы должны просто установить для свойства Visible значение false. Как ты пытался. Почему вы не можете установить его обратно в true, совершенно непонятно.

person Hans Passant    schedule 28.05.2011
comment
Отредактировал мой пост, чтобы добавить ваш комментарий и ответ, чтобы было понятно. Не удалось отформатировать комментарии. - person NKCSS; 28.05.2011
comment
Экстраординарные утверждения требуют экстраординарных доказательств. Выложите исходный код на файлообменник или вставьте bin. Нет необходимости в DLL для реализации горячих клавиш, вы можете использовать RegisterHotKey. Подойдет даже низкоуровневый клавиатурный хук, не требующий DLL. Вы найдете много совпадений, если наберете «registerhotkey» в поле поиска в правом верхнем углу этой страницы. - person Hans Passant; 28.05.2011
comment
Почему вы считаете, что вам нужно изменить дизайн? Вы никак не решаете проблему. Пожалуйста, просто ответьте на заданный вопрос. - person NKCSS; 28.05.2011
comment
Это, безусловно, не является обязательным для SO. Нет смысла понижать ответ, потому что вам не понравился комментарий. Что ж, удачи с ним. Пока. - person Hans Passant; 28.05.2011
comment
Ну, ваш комментарий содержал информацию, которая была просто неверной (как я объяснил в посте), но спасибо за попытку. - person NKCSS; 28.05.2011

Зачем вам нужна дополнительная 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);
person Uwe Keim    schedule 28.05.2011
comment
Существует очень мало смысла в использовании pinvoke в программе C++/CLI. - person Hans Passant; 28.05.2011
comment
Отредактировал мой пост, чтобы добавить ваш комментарий и ответ, чтобы было понятно. Не удалось отформатировать комментарии. - person NKCSS; 28.05.2011