Не получается встроить окно внешней проги

Только для тех, кто пишет плагины под Total Commander. Обмен опытом, решение проблем.

Модераторы: d-view, Моторокер, Avada, CaptainFlint, Nik

Ответить
AkulaBig
Сообщения: 640
Зарегистрирован: Ср дек 03, 2008 11:48

Не получается встроить окно внешней проги

Сообщение AkulaBig »

Решил написать плагин WLX с внешним просмотрщиком. За основу взял исходники sLister, также использовал исходники TCPlayer. На Visual C++. И никак не получается встроить внешнюю прогу в листер, а тем более в быстрый просмотр. Прога запускается отдельно в своем окне, чтобы я не делал. Меняю в этом-же коде все на данные суматры, опять все работает правильно. Изменяю детект-строку, название проги и название класса ее окна. Собственно именно эти данные и меняются в коде плага. Но не получается встроить прогу в листер и все.
Может кто может поподробнее объяснить, как встроить окно внешней проги в листер?
AkulaBig
Сообщения: 640
Зарегистрирован: Ср дек 03, 2008 11:48

Сообщение AkulaBig »

Решил привести полностью процедуру, может это поможет:

Код: Выделить всё

extern "C" __declspec(dllexport) HWND __stdcall ListLoadW(HWND ParentWin,wchar_t* FileToLoad,int ShowFlags) {
	bool sf = false;
	if (WS_CHILD & GetWindowLong((HWND)ParentWin, GWL_STYLE))sf = true;
	HWND ppp = GetFocus();
	PROCESS_INFORMATION pi = { 0 };
	STARTUPINFOW si = { 0 };
	wchar_t path[MAX_PATH] = L"";
	wchar_t rpath[MAX_PATH] = L"";
	wchar_t spath[MAX_PATH] = L"";
	GetModuleFileNameW(hInst, path, MAX_PATH);
	//PathRemoveFileSpecW((LPWSTR)path);
	if (wcsrchr(path, L'\\'))*wcsrchr(path, L'\\') = L'\0';
	wcscat_s(path, MAX_PATH, L"\\");
	wcscpy_s(spath, MAX_PATH, path);
	wcscpy_s(rpath, MAX_PATH, path);
	wcscat_s(spath, MAX_PATH, PROGRAMNAME);
	wcscat_s(rpath, MAX_PATH, PROGRAMNAME);
	wchar_t cmd[4096]=L"";
	WNDCLASSA wc = {};
	wc.hCursor=LoadCursor(NULL,IDC_ARROW);
	wc.style=CS_DBLCLKS;
	wc.hInstance     = hInst;
	wc.lpfnWndProc   = WLXPluginsWindowProc;
	wc.lpszClassName = "WLXPluginsClass";
	RegisterClassA(&wc);
	RECT r;
	GetClientRect(ParentWin,&r);
	HWND WLXPluginsClass = CreateWindowExA(0, "WLXPluginsClass", NULL, WS_CHILD|WS_VISIBLE|WS_CLIPCHILDREN, r.left, r.top, r.right-r.left,r.bottom-r.top, ParentWin, NULL, hInst, NULL);
	swprintf_s(cmd,4096,L"%s -plugin %d \"%s\"",rpath,WLXPluginsClass,FileToLoad);
	si.cb = sizeof(si);
	if (CreateProcessW(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
	{
		HWND swnd = NULL;
		for (int i = 0; swnd == NULL && i < 5000; i++) {
			Sleep(10);
			swnd = FindWindowEx(WLXPluginsClass, NULL, NULL, NULL);
		}
		if (sf)SetWindowLongPtr(WLXPluginsClass, GWLP_USERDATA, (LONG)SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)SpyProcQ, hInst, pi.dwThreadId));
		else
			SetWindowLongPtr(WLXPluginsClass, GWLP_USERDATA, (LONG)SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)SpyProcN, hInst, pi.dwThreadId));
		if (sf) {
			for (int i = 0; GetFocus() == ppp && i < 5000; i++)Sleep(10);
			SetFocus(ppp);
		}
		CloseHandle(pi.hProcess);
		CloseHandle(pi.hThread);
		return WLXPluginsClass;
	}
	else	DestroyWindow(WLXPluginsClass);
	return NULL;

}
Вот эту строку я не могу понять. Если убрать -plugin, то и суматра выводится отдельным окном.
swprintf_s(cmd,4096,L"%s -plugin %d \"%s\"",rpath,WLXPluginsClass,FileToLoad);
То-есть проблема явно в этой строке, но как она должна правильно выглядеть - не пойму.
AkulaBig
Сообщения: 640
Зарегистрирован: Ср дек 03, 2008 11:48

Сообщение AkulaBig »

Разобрался и понял, что не каждую прогу можно встроить в листер.
AkulaBig
Сообщения: 640
Зарегистрирован: Ср дек 03, 2008 11:48

Сообщение AkulaBig »

Проблему локализовал. Дело в том, вообще что не удается стандартными методами (через CreateProcessA, либо через ShellExecuteEx) вставить вызов любой программы в дочернее окно. Внешнее приложение всегда запускается в отдельном окне. В SumatrePDF для запуска ее в дочернем окне есть специальный недокументированный ключ -plugin. Вот код этого ключа:

Код: Выделить всё

// in order to host SumatraPDF as a plugin, create a (child) window and
// handle the following messages for it:
LRESULT CALLBACK PluginParentWndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
    if (WM_CREATE == msg) {
        // run SumatraPDF.exe with the -plugin command line argument
        PluginStartData* data = (PluginStartData*)((CREATESTRUCT*)lp)->lpCreateParams;
        AutoFreeWstr cmdLine(str::Format(L"-plugin %d \"%s\"", hwnd, data->filePath));
        if (data->fileOriginUrl) {
            cmdLine.Set(str::Format(L"-plugin \"%s\" %d \"%s\"", data->fileOriginUrl, hwnd, data->filePath));
        }
Есть у кого-нибудь идеи, как это использовать из внешнего кода, то-есть который я пишу?
Аватара пользователя
imig73
Сообщения: 285
Зарегистрирован: Вт июн 18, 2013 13:21
Откуда: г. Иркутск

Сообщение imig73 »

AkulaBig
Я не такой крутой специалист как вы, но про внешний какой то код вообще ничо не понял. Вам надо напрямую обратиться к MVV или Флинту и они вам подскажут как правильно оформить вызов. Тема созданная вами заведомо гласит быть дохлой.
AkulaBig
Сообщения: 640
Зарегистрирован: Ср дек 03, 2008 11:48

Сообщение AkulaBig »

Вопрос решен. Тему можно закрывать. Огромное спасибо автору AmpView за открытые исходники. Именно на их основе удалось выполнить задуманное.
Ответить