Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: disassembler от Январь 13, 2011, 19:31



Название: Создание окна в DLL
Отправлено: 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()


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


Название: Re: Создание окна в DLL
Отправлено: _govorilka от Январь 14, 2011, 09:45
ftp://ftp.qt.nokia.com/qt/solutions/qtbrowserplugin-2.3-opensource.tar.gz  (http://ftp://ftp.qt.nokia.com/qt/solutions/qtbrowserplugin-2.3-opensource.tar.gz)
Посмотри вот этот пример, возможно он подскажет тебе верные пути решения.


Название: Re: Создание окна в DLL
Отправлено: disassembler от Январь 14, 2011, 11:04
Создание QApplication для gui приложения в Qt обязательно.
т.е. считает нет никакого способа чтобы создать окно в длл и отображать его другом приложении?
в принципе главное приложение править тоже можно. но есть ограничение! оно не должно быть завязано на определенную библиотеку типа QT или любую другую, максимум WinAPI. это для того чтобы тесты можно было разрабатывать не только на QT


Название: Re: Создание окна в DLL
Отправлено: _govorilka от Январь 14, 2011, 15:22
Посмотри, пример. Там как раз создается окно в Dll (плагин для браузера, это как вы думаете что?).


Название: Re: Создание окна в DLL
Отправлено: disassembler от Январь 14, 2011, 17:49
Как раз смотрю пример...


Название: Re: Создание окна в DLL
Отправлено: ax от Январь 14, 2011, 18:06
В похожей ситуации просто делал
Код:
	
if (!qApp) {
    int argc = 0;
    new QApplication(argc, 0);
}

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


Название: Re: Создание окна в DLL
Отправлено: disassembler от Январь 14, 2011, 19:11
В похожей ситуации просто делал
Код:
	
if (!qApp) {
    int argc = 0;
    new QApplication(argc, 0);
}

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

это вы делали в длл? qApp->exec() в отдельный поток посадили?


Название: Re: Создание окна в DLL
Отправлено: disassembler от Январь 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 но при этом перестает работать обработчик кнопки которая находится на окне из длл. Если сетпарент закомитить, то обработчик работает но окно болтается само по себе  :(


Название: Re: Создание окна в DLL
Отправлено: disassembler от Январь 14, 2011, 19:26
Посмотри, пример. Там как раз создается окно в Dll (плагин для браузера, это как вы думаете что?).
сложно понять как он там работает не зная как браузер вообще работает с плагинами. изначально пример вообще не хотел компилиться, но после не большой правки собрался. такое впечатление что его только под никсами собирали до этого.
Если вы разобрались, то может покажите, то место где создается окно и как с ним надо работать из приложения?!


Название: Re: Создание окна в DLL
Отправлено: _govorilka от Январь 14, 2011, 21:59
сложно понять как он там работает не зная как браузер вообще работает с плагинами. изначально пример вообще не хотел компилиться, но после не большой правки собрался. такое впечатление что его только под никсами собирали до этого.
Если вы разобрались, то может покажите, то место где создается окно и как с ним надо работать из приложения?!

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


Название: Re: Создание окна в DLL
Отправлено: disassembler от Январь 17, 2011, 15:59

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

расковырял на сколько смог, таже беда: как только меняю предка у окна из ДЛЛ сразу перестает работать обработчик кнопки, но при этом если просто наводиться на PushButton то обрабатывается событие "наезда мыши"


Название: Re: Создание окна в DLL
Отправлено: disassembler от Январь 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.