Russian Qt Forum
Ноябрь 18, 2024, 19:15 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Создание окна в DLL  (Прочитано 11619 раз)
disassembler
Гость
« : Январь 13, 2011, 19:31 »

Здраствуйте! У меня тут задачка есть одна, никак не могу решить ее, может вы сможете помочь?!
Суть следующая: есть оконное приложение под винду, которое может подгружать dll и вызывать функцию
TTest* __declspec(dllexport) CreateObject();
Возвращает функция указатель на объект "Тест". В конструкторе теста создается окно, что бы потом HANDLE его передать главному приложению и оно отобразило его в нужном местечке окна приложения.
class CommandWindow : public QWidget
{
    Q_OBJECT
public:
    explicit CommandWindow(QWidget *parent = 0);
    ~CommandWindow();
private:
    Ui::CommandWindow *ui;
};

так вот при вызове конструктора класса CommandWindow вылетает SEGMENTATION FAULT и ругается так:
"QWidget: Must construct a QApplication before a QPaintDevice"
Разумеется в DLL у меня никакого QApplication нет. Как обойти данную проблемы и создать окно, что бы можно было его отображать в нужном месте главного приложения. Главное приложение использует WinAPI функции и класс TTest имеет метод получения хендла окна void* GetHWND()
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #1 : Январь 14, 2011, 09:06 »

Цитировать
Разумеется в DLL у меня никакого QApplication нет. Как обойти данную проблемы и создать окно, что бы можно было его отображать в нужном месте главного приложения. Главное приложение использует WinAPI функции и класс TTest имеет метод получения хендла окна void* GetHWND()
Создание QApplication для gui приложения в Qt обязательно.
Записан

Qt 5.11/4.8.7 (X11/Win)
_govorilka
Гость
« Ответ #2 : Январь 14, 2011, 09:45 »

ftp://ftp.qt.nokia.com/qt/solutions/qtbrowserplugin-2.3-opensource.tar.gz
Посмотри вот этот пример, возможно он подскажет тебе верные пути решения.
Записан
disassembler
Гость
« Ответ #3 : Январь 14, 2011, 11:04 »

Создание QApplication для gui приложения в Qt обязательно.
т.е. считает нет никакого способа чтобы создать окно в длл и отображать его другом приложении?
в принципе главное приложение править тоже можно. но есть ограничение! оно не должно быть завязано на определенную библиотеку типа QT или любую другую, максимум WinAPI. это для того чтобы тесты можно было разрабатывать не только на QT
« Последнее редактирование: Январь 14, 2011, 11:30 от disassembler » Записан
_govorilka
Гость
« Ответ #4 : Январь 14, 2011, 15:22 »

Посмотри, пример. Там как раз создается окно в Dll (плагин для браузера, это как вы думаете что?).
Записан
disassembler
Гость
« Ответ #5 : Январь 14, 2011, 17:49 »

Как раз смотрю пример...
Записан
ax
Чайник
*
Offline Offline

Сообщений: 60


Просмотр профиля
« Ответ #6 : Январь 14, 2011, 18:06 »

В похожей ситуации просто делал
Код:
	
if (!qApp) {
    int argc = 0;
    new QApplication(argc, 0);
}

Есть нюанс, что для некоторых классов необходима обработка сообщений - можно периодически вызывать
Код:
QCoreApplication::processEvents
или через
Код:
QTimer::singleShot
запустить слот с вызовом qApp->exec()
Записан
disassembler
Гость
« Ответ #7 : Январь 14, 2011, 19:11 »

В похожей ситуации просто делал
Код:
	
if (!qApp) {
    int argc = 0;
    new QApplication(argc, 0);
}

Есть нюанс, что для некоторых классов необходима обработка сообщений - можно периодически вызывать
Код:
QCoreApplication::processEvents
или через
Код:
QTimer::singleShot
запустить слот с вызовом qApp->exec()

это вы делали в длл? qApp->exec() в отдельный поток посадили?
Записан
disassembler
Гость
« Ответ #8 : Январь 14, 2011, 19:16 »

Сделал вот так и кое что заработало:
Код ДДЛ:
Код:
void TThread::run()
{
    pApp->exec();
}
void TThread::stop()
{
    pApp->quit();
}

TTestCommand::TTestCommand()
    :TTest()
{
    int argc=1;
    char *argv[1];
    argv[0]="templatedll.dll";
    pApp = new QApplication(argc, argv);

    thread = new TThread();
    thread->start();

    // for c/p : templatedll.dll
    wnd = new CommandWindow();
    wnd->show();
    //wnd->setVisible(false);
}
TTestCommand::~TTestCommand()
{
    thread->stop();
    thread->wait();
    delete pApp;
}

void* TTestCommand::GetHWND()

{
    return wnd->winId();
}

TTest* __declspec(dllexport) CreateObject()
{
    return new TTestCommand();
}

Код Приложения:
Код:
typedef TTest* (*TCreateObject)();

HINSTANCE hUiiDrv_ID;
TCreateObject CreateObject;

    try{
        hUiiDrv_ID = LoadLibrary( Edit1->Text.c_str() );
    }
    catch(...)
    {
        return;
    }

    if( (CreateObject  = (TCreateObject) GetProcAddress(hUiiDrv_ID, "CreateObject"))==NULL )  return;
    TTest* tst = CreateObject();
    hwnd = tst->GetHWND();
    ::SetParent(hwnd, (HWND)(Panel1->Handle));
но вот проблема, когда делаю

    ::SetParent(hwnd, (HWND)(Panel1->Handle));
окно благополучно перемещается в область Panel1 но при этом перестает работать обработчик кнопки которая находится на окне из длл. Если сетпарент закомитить, то обработчик работает но окно болтается само по себе  Грустный
Записан
disassembler
Гость
« Ответ #9 : Январь 14, 2011, 19:26 »

Посмотри, пример. Там как раз создается окно в Dll (плагин для браузера, это как вы думаете что?).
сложно понять как он там работает не зная как браузер вообще работает с плагинами. изначально пример вообще не хотел компилиться, но после не большой правки собрался. такое впечатление что его только под никсами собирали до этого.
Если вы разобрались, то может покажите, то место где создается окно и как с ним надо работать из приложения?!
Записан
_govorilka
Гость
« Ответ #10 : Январь 14, 2011, 21:59 »

сложно понять как он там работает не зная как браузер вообще работает с плагинами. изначально пример вообще не хотел компилиться, но после не большой правки собрался. такое впечатление что его только под никсами собирали до этого.
Если вы разобрались, то может покажите, то место где создается окно и как с ним надо работать из приложения?!

В этом solutions есть файл qtbrowserplugin_win.cpp. Его стоит поковырять....
Записан
disassembler
Гость
« Ответ #11 : Январь 17, 2011, 15:59 »


В этом solutions есть файл qtbrowserplugin_win.cpp. Его стоит поковырять....

расковырял на сколько смог, таже беда: как только меняю предка у окна из ДЛЛ сразу перестает работать обработчик кнопки, но при этом если просто наводиться на PushButton то обрабатывается событие "наезда мыши"
Записан
disassembler
Гость
« Ответ #12 : Январь 25, 2011, 13:34 »

нашел решение!
чтобы все нормально работало, надо скачать библиотеку с сайта QT
в которой есть класс QWinWidget и им заменить в программе класс QWidget.
dll-ка грузится и корректно отображает окно и отрабатывает события в приложениях
написаных в Builder, QT, MSVS.

h-файл:
Код:
#include <QWinWidget>

class SignalsWindow : public QWinWidget
{
    Q_OBJECT

public:
    explicit SignalsWindow(HWND parent = 0);
    ~SignalsWindow();


private:
    Ui::SignalsWindow *ui;
};


cpp-файл
Код:
bool Init(HINSTANCE hInstance)
{
    // Под Windows устанавливаем кодировку cp1251
#ifdef Q_WS_WIN
    QTextCodec::setCodecForTr(QTextCodec::codecForName("Windows-1251"));
    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("Windows-1251"));
    // Под остальными ОС - utf8
#else
    QTextCodec::setCodecForTr(QTextCodec::codecForName("utf-8"));
    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("utf-8"));
#endif

    ownApplication = QMfcApp::pluginInstance( hInstance );
    return TRUE;
}
//---------------------------------------------------------
bool Close()
{
    if(ownApplication)
        delete qApp;
    delete TestSignals;
    return TRUE;
}
//---------------------------------------------------------
HWND __declspec(dllexport) CreateObject(HWND hParent)
{
    TestWnd = new SignalsWindow(hParent)
    TestWnd->setWindowState(Qt::WindowMaximized);
    TestWnd->show();
    return TestWnd->winId();
}

В приложении после загрузки длл вызываем функцию Init, перед выгрузкой Close, для отображения окна из dll, CreateObject и передаем ему HWND окна в котором хотим отобразить окно из dll.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.051 секунд. Запросов: 23.