Помогите выборать на чём писать утилиту.
Нужен какой-нибудь фреймворк или ЯП, чтобы можно было сделать следующее:
скомпилировать dll;
в dll вызывать native API без сложностей;
в dll создать GUI(не через CreateWindowEx) формочку, которая может быть cо static размещением в памяти;
чтобы создание формочки не требовало создания каких-то иных объектов или обработчиков сообщений, если только эти объекты и обработчики не умеют возвращать управление сразу же после своего создания и вообще никогда не уходят в бесконечный цикл в основном потоке.
Ну, вот, как-то так.
2) функции создания окон неблокирующие (в винде по крайней мере) - т.е. тебе достаточно создать окно и WNDPROC (это минимум без использования фреймворков)
3) почти все фреймворки содержат в себе event-loop'ы, которые запускаются блокирующими функциями - это решается запуском в потоке (winapi/pthread etc).
Вывод - можешь писать на чем угодно, что скомпилируется в dll
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. Хочется как-то попроще это всё сделать, без потоков и большого количества объектов, и кода поменьше. :)
Вот, у Qt не получится так из-за того, что нужно создавать QApplication и вызывать exec.
надо ж. Я и не знал. создавал себе длл, и ничего работало :) аказывается не должно было.
или может быть все таки дело не во фреймворке? :)
Вот, у Qt не получится так из-за того, что нужно создавать QApplication и вызывать exec.
надо ж. Я и не знал. создавал себе длл, и ничего работало :) аказывается не должно было.
или может быть все таки дело не во фреймворке? :)
А виджет какой-нибудь в dll создавать пробовал? Если с виджетом и без QApplication всё работало, то даже и не знаю к чему эта строка в QtGuid4 - "QWidget: Must construct a QApplication before a QPaintDevice".
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
Да мне не влом...Хотя после трёхдневного секса и неудачного результата потерял все надежды на успех с теми инструментами, что владею.
Давай тебе сначала обрисую, что вообще должно быть.
Итак: есть один Winamp и есть плагин к нему. Суть в том, чтобы, когда сменяется воспроизводимый трек, то появлялось небольшое окошко в правом нижнем краю, модальное, и показывало тайтл нового трека и кто его исполняет. Весь код уже есть: и получение имени исполнителя, и сабклассинг. Нет только окошка и места, где его можно создать.
Если мне память ни с кем не изменяет, именно это (создание окна) там делать не стоит. Есть в MSDN статья «Что не стоит делать в DLLMain», а также целый .doc-файлик, в котором это подробно расписано
Не вкурю, где у меня DLLMain должен находиться. По-моему, ничего такого не было при создании проекта.
Можешь глянуть в исходники и сказать, что за технологии использую?:) Забыл, как проект созадвал.
Не вкурю, где у меня DLLMain должен находиться. По-моему, ничего такого не было при создании проекта.
Можешь глянуть в исходники и сказать, что за технологии использую?:) Забыл, как проект созадвал.
это .net assembly (clr/c++) а не dll
ты запутался, зачем тебе это? DllMain я имел ввиду только чтоб например 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;
}
ты запутался, зачем тебе это? DllMain я имел ввиду только чтоб например 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 речь. Спасибо, попробую.
Вот, у Qt не получится так из-за того, что нужно создавать QApplication и вызывать exec.
надо ж. Я и не знал. создавал себе длл, и ничего работало :) аказывается не должно было.
или может быть все таки дело не во фреймворке? :)
А виджет какой-нибудь в dll создавать пробовал? Если с виджетом и без QApplication всё работало, то даже и не знаю к чему эта строка в QtGuid4 - "QWidget: Must construct a QApplication before a QPaintDevice".
я использовал QDialog. Но по сути думаю что это не важно. Дело в том, что в конечном итоге вызовы компонентов кьюта разворачивается в вызов апи-функций. Но правда для этого надо тащить кьютовские библиотеки. Поэтому тут такой момент - если речь идет о програмном комплексе, созданном на Qt - это наверно оправданно. Если же это единичная утилита - лучше использовать .Net или же вообще прямой вызов апи. Цеплять для этого фреймворк - бредовая идея. ИМХО.
Таки я её нашёл. Кочяй, читай
Таки я её нашёл. Кочяй, читай
Пасибки. Надеюсь, всё заработает. У меня уже был написанный плагин, только вот в Winamp что-то поменяли и он открутился. Видимо, что-то с потоками изменили. Надеюсь, не придётся писать всё на native API.
А так, на API — почему б и не побаловаться? =)
А так, на API — почему б и не побаловаться? =)
С ума сойти можно с этими API. 2013-й год на дворе. Code less, create more.
Deploy Everywhere.
Qt.
Deploy Everywhere.
Qt.
Вот бы ещё знать, что такое deploy...
Вот бы ещё знать, что такое deploy...
Дословно - разворачивать. В программировании подразумевает обычно под Deploying процесс от компиляции до сборки пакета установщика приложения. В лозунге Qt подразумевает кроссплатформенность.
#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;
}
#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();
}
};
#include "mainwnd.h"
static MainWnd *main_wnd = NULL;
static int args_cnt = 0;
static char** args_arr = NULL;
PCHAR* CommandLineToArgvA(PCHAR CmdLine, int* _argc );
А почему бы просто не создать окно, а потом его просто показывать/прятать? Вместо того, чтобы каждый раз создавать окно. В DLL_PROCESS_DETACH уничтожать, разумеется
А с какой ошибкой падает?
А чем менюшка Deploy в Creator'е отличается от Build?
А чем менюшка Deploy в Creator'е отличается от Build?
Запускает сборку не просто "qmake&&make" а "qmake&&make&&make install"
Компилирует и устанавливает в систему , со всеми зависимостями
На мобильных - копирует собранный проект на целевое устройство (только для симбиан и win ce)
В винде по умолчанию install и uninstall пункты makefile пустые генерятся в других ос лень смотреть, но подозреваю что в OS X запускается утилитка macdeployqt а в линухе копирует все по папочкам(имхо)
И вроде из INSTALLS копирует файлы в конечную папку
Что может быть не так? То, что окно - статическая переменная?
Я ж тебе код показывал:
#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;
}
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);
}
Мне ведь не нужно, чтобы окно было всегда видимым.
Объясняю суть: все объекты создаем в потоке с QApplication, кроме wrapper, его мы двигаем в поток приложения после создания (с QWidget так не канает) и уже в потоке приложения создаем окна.
main.cpp
#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::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();
}
#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