Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Помогите выборать на чём писать утилиту.

414
04 января 2013 года
CassandraDied
763 / / 24.05.2012
Хай.
Нужен какой-нибудь фреймворк или ЯП, чтобы можно было сделать следующее:
скомпилировать dll;
в dll вызывать native API без сложностей;
в dll создать GUI(не через CreateWindowEx) формочку, которая может быть cо static размещением в памяти;
чтобы создание формочки не требовало создания каких-то иных объектов или обработчиков сообщений, если только эти объекты и обработчики не умеют возвращать управление сразу же после своего создания и вообще никогда не уходят в бесконечный цикл в основном потоке.
Ну, вот, как-то так.
277
04 января 2013 года
arrjj
1.7K / / 26.01.2011
1) всё в винде, что создает окна создает их через CreateWindow/CreateDialog, static окон не бывает.
2) функции создания окон неблокирующие (в винде по крайней мере) - т.е. тебе достаточно создать окно и WNDPROC (это минимум без использования фреймворков)
3) почти все фреймворки содержат в себе event-loop'ы, которые запускаются блокирующими функциями - это решается запуском в потоке (winapi/pthread etc).

Вывод - можешь писать на чем угодно, что скомпилируется в dll
414
04 января 2013 года
CassandraDied
763 / / 24.05.2012
Цитата: arrjj
1) всё в винде, что создает окна создает их через CreateWindow/CreateDialog, static окон не бывает.
2) функции создания окон неблокирующие (в винде по крайней мере) - т.е. тебе достаточно создать окно и WNDPROC (это минимум без использования фреймворков)
3) почти все фреймворки содержат в себе event-loop'ы, которые запускаются блокирующими функциями - это решается запуском в потоке (winapi/pthread etc).

Вывод - можешь писать на чем угодно, что скомпилируется в dll


1) Имел в виду, чтобы мне не пришлось руками создавать окно через CreateWindow. А static - это Сишный модификатор(как знал, что меня могут не понять). Например, в clr не получается создать статический класс ссылочного типа. Или как там это будет всё правильно называться.
2) Использование фреймворков - хорошо. Писать обработку сообщений окна руками - не кавай. Вот, у Qt не получится так из-за того, что нужно создавать QApplication и вызывать exec. А вот MFC получилось создать окно и без вызова обработчика своими руками.
Мне бы как-нибудь соединить возможности QT и CLR.
Про CLR и MFC мог спутать, не особо хорошо знаком с технологиями МС.
Вот ещё что хочу добавить: с потоками работать не хочется, потому что, если создать форму в потоке, то не представляю, как к ней обращаться из другого потока. Вернее, не представляю, как это можно сделать просто. Суть в том, что программа, использующая мою dll вызывает из неё две функции - init т quit. Вызывает их в момент своего запуска и в момент завершения работы. В init необходимо создать моё окно и сабклассить окно той программы, которая подгрузила мою dll. Хочется как-то попроще это всё сделать, без потоков и большого количества объектов, и кода поменьше. :)

1
04 января 2013 года
kot_
7.3K / / 20.01.2000
Цитата: CassandraDied

Вот, у Qt не получится так из-за того, что нужно создавать QApplication и вызывать exec.


надо ж. Я и не знал. создавал себе длл, и ничего работало :) аказывается не должно было.
или может быть все таки дело не во фреймворке? :)

414
04 января 2013 года
CassandraDied
763 / / 24.05.2012
Цитата: kot_
Цитата: CassandraDied

Вот, у Qt не получится так из-за того, что нужно создавать QApplication и вызывать exec.


надо ж. Я и не знал. создавал себе длл, и ничего работало :) аказывается не должно было.
или может быть все таки дело не во фреймворке? :)


А виджет какой-нибудь в dll создавать пробовал? Если с виджетом и без QApplication всё работало, то даже и не знаю к чему эта строка в QtGuid4 - "QWidget: Must construct a QApplication before a QPaintDevice".

7
04 января 2013 года
@pixo $oft
3.4K / / 20.09.2006
Да давай я тебе эту DLL напишу, ежели влом! Только объясни, что надо делать
277
04 января 2013 года
arrjj
1.7K / / 26.01.2011
Цитата: CassandraDied

1) Имел в виду, чтобы мне не пришлось руками создавать окно через CreateWindow. А static - это Сишный модификатор(как знал, что меня могут не понять). Например, в clr не получается создать статический класс ссылочного типа. Или как там это будет всё правильно называться.
2) Использование фреймворков - хорошо. Писать обработку сообщений окна руками - не кавай. Вот, у Qt не получится так из-за того, что нужно создавать QApplication и вызывать exec. А вот MFC получилось создать окно и без вызова обработчика своими руками.
Мне бы как-нибудь соединить возможности QT и CLR.
Про CLR и MFC мог спутать, не особо хорошо знаком с технологиями МС.
Вот ещё что хочу добавить: с потоками работать не хочется, потому что, если создать форму в потоке, то не представляю, как к ней обращаться из другого потока. Вернее, не представляю, как это можно сделать просто. Суть в том, что программа, использующая мою dll вызывает из неё две функции - init т quit. Вызывает их в момент своего запуска и в момент завершения работы. В init необходимо создать моё окно и сабклассить окно той программы, которая подгрузила мою dll. Хочется как-то попроще это всё сделать, без потоков и большого количества объектов, и кода поменьше. :)


1) не, я понял что ты имел ввиду модификатор static, но чтоб использовать static переменную её всёравно надо гдето инициализировать правильно, да и системе нужно сообщить чтоб зарегистрировала окно. ну а что у тебя не получилось хз.
2) mfc - фреймворк

Ну а по третьему пункту я забыл, что есть же DLLMain :) - инициализируй в нем всё что угодно при DLL_PROCESS_ATTACH

414
04 января 2013 года
CassandraDied
763 / / 24.05.2012
Цитата: @pixo $oft
Да давай я тебе эту DLL напишу, ежели влом! Только объясни, что надо делать


Да мне не влом...Хотя после трёхдневного секса и неудачного результата потерял все надежды на успех с теми инструментами, что владею.
Давай тебе сначала обрисую, что вообще должно быть.
Итак: есть один Winamp и есть плагин к нему. Суть в том, чтобы, когда сменяется воспроизводимый трек, то появлялось небольшое окошко в правом нижнем краю, модальное, и показывало тайтл нового трека и кто его исполняет. Весь код уже есть: и получение имени исполнителя, и сабклассинг. Нет только окошка и места, где его можно создать.

7
04 января 2013 года
@pixo $oft
3.4K / / 20.09.2006
Цитата: arrjj
Ну а по третьему пункту я забыл, что есть же DLLMain :) - инициализируй в нем всё что угодно при DLL_PROCESS_ATTACH

Если мне память ни с кем не изменяет, именно это (создание окна) там делать не стоит. Есть в MSDN статья «Что не стоит делать в DLLMain», а также целый .doc-файлик, в котором это подробно расписано

414
04 января 2013 года
CassandraDied
763 / / 24.05.2012
arrjj
Не вкурю, где у меня DLLMain должен находиться. По-моему, ничего такого не было при создании проекта.
Можешь глянуть в исходники и сказать, что за технологии использую?:) Забыл, как проект созадвал.
277
05 января 2013 года
arrjj
1.7K / / 26.01.2011
Цитата: CassandraDied
arrjj
Не вкурю, где у меня DLLMain должен находиться. По-моему, ничего такого не было при создании проекта.
Можешь глянуть в исходники и сказать, что за технологии использую?:) Забыл, как проект созадвал.



это .net assembly (clr/c++) а не dll

414
05 января 2013 года
CassandraDied
763 / / 24.05.2012
А это тогда к чему?
277
05 января 2013 года
arrjj
1.7K / / 26.01.2011
уберешь clr - будет тебе обычная длл, а так ты будешь делать "mixed assembly" - чтоб объявить DllMain тебе нужно объявлять его в блоке #pragma unmanaged, откуда ты с .net работать не можешь. http://msdn.microsoft.com/en-us/library/ms173266%28v=vs.80%29.aspx
414
05 января 2013 года
CassandraDied
763 / / 24.05.2012
Как мне потом из неуправляемого кода достучаться до "управляемой формы"? Без извращений.
277
05 января 2013 года
arrjj
1.7K / / 26.01.2011
Цитата: CassandraDied
Как мне потом из неуправляемого кода достучаться до "управляемой формы"? Без извращений.


ты запутался, зачем тебе это? DllMain я имел ввиду только чтоб например QApplication проинициализировать

Код:
#include <QApplication>
#include <windows.h>

static DWORD WINAPI launcher(void* h)
{
   QApplication app;
    return app.exec();
}
extern "C" BOOL APIENTRY DllMain(HMODULE h, DWORD reasonForCall, void* resv)
{
    if (reasonForCall == DLL_PROCESS_ATTACH)
    {
        CreateThread(0, 0, launcher, h, 0, 0);
    }
    return TRUE;
}
414
05 января 2013 года
CassandraDied
763 / / 24.05.2012
Цитата: arrjj
Цитата: CassandraDied
Как мне потом из неуправляемого кода достучаться до "управляемой формы"? Без извращений.


ты запутался, зачем тебе это? DllMain я имел ввиду только чтоб например QApplication проинициализировать

Код:
#include <QApplication>
#include <windows.h>

static DWORD WINAPI launcher(void* h)
{
   QApplication app;
    return app.exec();
}
extern "C" BOOL APIENTRY DllMain(HMODULE h, DWORD reasonForCall, void* resv)
{
    if (reasonForCall == DLL_PROCESS_ATTACH)
    {
        CreateThread(0, 0, launcher, h, 0, 0);
    }
    return TRUE;
}


А, так ты уже о QT говоришь. Думал, что всё ещё об .NET речь. Спасибо, попробую.

1
05 января 2013 года
kot_
7.3K / / 20.01.2000
Цитата: CassandraDied
Цитата: kot_
Цитата: CassandraDied

Вот, у Qt не получится так из-за того, что нужно создавать QApplication и вызывать exec.


надо ж. Я и не знал. создавал себе длл, и ничего работало :) аказывается не должно было.
или может быть все таки дело не во фреймворке? :)


А виджет какой-нибудь в dll создавать пробовал? Если с виджетом и без QApplication всё работало, то даже и не знаю к чему эта строка в QtGuid4 - "QWidget: Must construct a QApplication before a QPaintDevice".


я использовал QDialog. Но по сути думаю что это не важно. Дело в том, что в конечном итоге вызовы компонентов кьюта разворачивается в вызов апи-функций. Но правда для этого надо тащить кьютовские библиотеки. Поэтому тут такой момент - если речь идет о програмном комплексе, созданном на Qt - это наверно оправданно. Если же это единичная утилита - лучше использовать .Net или же вообще прямой вызов апи. Цеплять для этого фреймворк - бредовая идея. ИМХО.

7
05 января 2013 года
@pixo $oft
3.4K / / 20.09.2006
Best practices for creating DLLs
Таки я её нашёл. Кочяй, читай
414
05 января 2013 года
CassandraDied
763 / / 24.05.2012
Цитата: @pixo $oft
Best practices for creating DLLs
Таки я её нашёл. Кочяй, читай


Пасибки. Надеюсь, всё заработает. У меня уже был написанный плагин, только вот в Winamp что-то поменяли и он открутился. Видимо, что-то с потоками изменили. Надеюсь, не придётся писать всё на native API.

7
05 января 2013 года
@pixo $oft
3.4K / / 20.09.2006
Вот на native API писать точно не придётся, ибо это чуть ли не ядро. Довольно близко к нему, в общем
А так, на API — почему б и не побаловаться? =)
414
06 января 2013 года
CassandraDied
763 / / 24.05.2012
Цитата: @pixo $oft
Вот на native API писать точно не придётся, ибо это чуть ли не ядро. Довольно близко к нему, в общем
А так, на API — почему б и не побаловаться? =)


С ума сойти можно с этими API. 2013-й год на дворе. Code less, create more.

277
06 января 2013 года
arrjj
1.7K / / 26.01.2011
Цитата: CassandraDied
Code less, create more.


Deploy Everywhere.
Qt.

414
06 января 2013 года
CassandraDied
763 / / 24.05.2012
Цитата: arrjj
Цитата: CassandraDied
Code less, create more.


Deploy Everywhere.
Qt.


Вот бы ещё знать, что такое deploy...

277
06 января 2013 года
arrjj
1.7K / / 26.01.2011
Цитата: CassandraDied

Вот бы ещё знать, что такое deploy...


Дословно - разворачивать. В программировании подразумевает обычно под Deploying процесс от компиляции до сборки пакета установщика приложения. В лозунге Qt подразумевает кроссплатформенность.

414
06 января 2013 года
CassandraDied
763 / / 24.05.2012
Добавил DllMain, теперь форма появляется, но падает сразу же, как только навожу на неё мышкой. Наверное, при обработке сообщения.

Код:
//главный модуль(gen_shower3.cpp)
#include "gen_shower3.h"
#include "mainwnd.h"
#include <windows.h>
#include "appthread.h"

extern "C" bool  WINAPI  DllMain(HMODULE h, DWORD reasonForCall, void* resv)
{
    if (reasonForCall == DLL_PROCESS_ATTACH)
    {
        AppThread* thrd = new AppThread();
        thrd->start();
    }
    return TRUE;
}
Код:
//appthread.h
#include "mainwnd.h"
#include <QThread>
#include <QApplication>
#include "gen_shower3.h"

class AppThread : public QThread {
    public:
    AppThread()
    {
        args_arr = CommandLineToArgvA(GetCommandLineA(), &args_cnt);
    }

    void run() {
        QApplication a(args_cnt, args_arr);
        main_wnd = new MainWnd();
        main_wnd->show();
        a.exec();
    }
};
 
Код:
//gen_shower3.h  
#include "mainwnd.h"

static MainWnd *main_wnd = NULL;
static int args_cnt = 0;
static char** args_arr = NULL;

PCHAR* CommandLineToArgvA(PCHAR CmdLine, int* _argc );
Что может быть не так? То, что окно - статическая переменная?
7
06 января 2013 года
@pixo $oft
3.4K / / 20.09.2006
Окно теперь переменная ☺
А почему бы просто не создать окно, а потом его просто показывать/прятать? Вместо того, чтобы каждый раз создавать окно. В DLL_PROCESS_DETACH уничтожать, разумеется

А с какой ошибкой падает?
414
06 января 2013 года
CassandraDied
763 / / 24.05.2012
Да оно так и работает. Форма вообще себя сама скрывать может по таймеру. И в этом, видимо, проблема. Раньше понасоздавал несколько слотов. Видимо, не подключил или какие-то переменные в классе формы не инициализировал. Если repaint работает, значит, нормально сообщения обрабатываются. Создал пустую форму и отобразил её - ничего не падает и даже кнопочка жмакается. Надо в инициализации покопаться.
414
06 января 2013 года
CassandraDied
763 / / 24.05.2012
arrjj
А чем менюшка Deploy в Creator'е отличается от Build?
414
06 января 2013 года
CassandraDied
763 / / 24.05.2012
Заработало. Всем спасибо за помощь.
277
06 января 2013 года
arrjj
1.7K / / 26.01.2011
Цитата: CassandraDied
arrjj
А чем менюшка Deploy в Creator'е отличается от Build?


Запускает сборку не просто "qmake&&make" а "qmake&&make&&make install"

Компилирует и устанавливает в систему , со всеми зависимостями
На мобильных - копирует собранный проект на целевое устройство (только для симбиан и win ce)

В винде по умолчанию install и uninstall пункты makefile пустые генерятся в других ос лень смотреть, но подозреваю что в OS X запускается утилитка macdeployqt а в линухе копирует все по папочкам(имхо)
И вроде из INSTALLS копирует файлы в конечную папку


Цитата: CassandraDied
Добавил DllMain, теперь форма появляется, но падает сразу же, как только навожу на неё мышкой. Наверное, при обработке сообщения.

Что может быть не так? То, что окно - статическая переменная?


Я ж тебе код показывал:

Цитата: arrjj

Код:
#include <QApplication>
#include <windows.h>

static DWORD WINAPI launcher(void* h)
{
    QApplication app;
    MainWnd a;
    a.show();
    return app.exec();
}
extern "C" BOOL APIENTRY DllMain(HMODULE h, DWORD reasonForCall, void* resv)
{
    if (reasonForCall == DLL_PROCESS_ATTACH)
    {
        CreateThread(0, 0, launcher, h, 0, 0);
    }
    return TRUE;
}

414
06 января 2013 года
CassandraDied
763 / / 24.05.2012
Код хороший и даже рабочий, но потом со стандартными потоками переписал. Падало из-за неинициализированного таймера. А вот почему теперь падает - не знаю.

Код:
//поток
void run() {
        QApplication a(args_cnt, args_arr);
        main_wnd = new MainWnd();
        bool suc = connect(main_wnd,SIGNAL(showForm()),this,SLOT(slotShowForm()));
        if (suc)
            MessageBoxA(0,"Slot connected","",0);
        else
            MessageBoxA(0,"Slot didnt connected","",0);
        a.exec();
    }

private slots:
    void slotShowForm()
    {
        MessageBoxA(0,"In slotShowForm","",0);
        main_wnd->show();
    }

Код:
//окно
void MainWnd::SetText(QString ttl)
{
    QString artist;
    QString title;
    int pos = 0;
    MessageBoxA(0,"In SetText","",0);
    //pos = ttl.indexOf("-");
    //artist = ttl.left(pos -1);
    //title = ttl.mid(pos + 1);
    //ui->Artist_lbl->setText(artist);
    //ui->Title_lbl->setText(title);
    MessageBoxA(0,"Before emit","",0);
    emit MainWnd::showForm();
    MessageBoxA(0,"After emit","",0);
}
Если отображать форму сразу в run, то всё нормально и потом текст меняется у Lable. Если через слот отображать, то доходит до сообщения Before emit. Слот коннектится нормально. А потом падает с "Access violation when reading".
Мне ведь не нужно, чтобы окно было всегда видимым.
277
06 января 2013 года
arrjj
1.7K / / 26.01.2011
Вот тебе пример рабочий
Объясняю суть: все объекты создаем в потоке с QApplication, кроме wrapper, его мы двигаем в поток приложения после создания (с QWidget так не канает) и уже в потоке приложения создаем окна.
main.cpp
Код:
#include <QApplication>
#include <windows.h>
#include <qt_dll_global.h>

#include "wrp.h"
static wrp * wrapper=NULL;
static QApplication * app=NULL;
static bool deleteapp=false;

static DWORD WINAPI launcher(void* h)
{
    app = (QApplication*)QApplication::instance();
    wrapper=new wrp();
    if(!app)
    {
        //Не Qt приложение
        deleteapp=true;
        int argc;
        WCHAR** argv=CommandLineToArgvW(GetCommandLineW(),&argc);
        app = new QApplication(argc,(char**)argv);
        wrapper->init();
        QApplication::setQuitOnLastWindowClosed(false);
        return app->exec();
    }
    else
    {
        //Qt приложение QApplication создавать не нужно, возможны проблемы совместимости версий Qt
        wrapper->moveToThread(app->thread());
        QMetaObject::invokeMethod(wrapper,"init");
        return 0;
    }
}
extern "C" void show()
{
    if(wrapper)
        QMetaObject::invokeMethod(wrapper,"show");
}

extern "C" void close()
{
    if(wrapper)
        QMetaObject::invokeMethod(wrapper,"close");
}


extern "C" BOOL APIENTRY DllMain(HMODULE h, DWORD reasonForCall, void* resv)
{
    if (reasonForCall == DLL_PROCESS_ATTACH)
    {
        CreateThread(0, 0, launcher, h, 0, 0);
    }
    if (reasonForCall == DLL_PROCESS_DETACH)
    {
        if(app)
        {
            if(wrapper)
                QMetaObject::invokeMethod(wrapper,"release");
            delete wrapper;
            if(deleteapp)
            {
                app->quit();
                app=NULL;
            }
        }
    }
    return TRUE;
}
wrp.cpp
Код:
#include "wrp.h"

wrp::wrp(QObject *parent) :
    QObject(parent)
{
}

void wrp::init()
{
    a=new MainWnd();
}
void wrp::release()
{
    a->close();
    a->deleteLater();
}

void wrp::show()
{
    a->show();
}
void wrp::close()
{
    a->close();
}
wrp.h
Код:
#ifndef WRP_H
#define WRP_H

#include <QObject>
#include <mainwnd.h>

class wrp : public QObject
{
    Q_OBJECT
public:
    explicit wrp(QObject *parent = 0);
    MainWnd *a;
public slots:
    void init();
    void release();
    void show();
    void close();
};

#endif // WRP_H
414
06 января 2013 года
CassandraDied
763 / / 24.05.2012
Спасибо. На днях займусь разбором и переписыванием. А пока лабораторки к сессии по Oracle надо дописывать...
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог