Форум » GUI » ShellExecute в МиниГуи » Ответить

ShellExecute в МиниГуи

Andrey: С некоторых пор перестало показываться окно при вызове команды ShellExecute. Раньше автоматом было. Т.е. фокус переходил на проводник. Что нужно сделать, чтобы фокус переходил на проводник ? Вот код: [pre2]// Как программно открыть папку и выделить файл? // ShellExecute(Application.Handle, 'OPEN', 'EXPLORER', '/select, ' + path, '', SW_NORMAL) FUNCTION RunExplFile2(cFile) ShellExecute( 0, "open", "explorer.exe", '/select, ' + cFile, , SW_SHOWNORMAL ) //InKeyGui(5000) - это не помогает. RETURN NIL[/pre2]

Ответов - 34, стр: 1 2 All

gfilatov2002: Andrey пишет: Что нужно сделать, чтобы фокус переходил на проводник ? У меня сработал такой вызов: // Using ShellExecute for opening Explorer with selected File ShellExecute( 0, "open", "explorer.exe", "/select," + cFileName, NIL, 1 ) где cFileName := CurDrive() + ":\" + CurDir() + "\MyPicture.png"

Andrey: Да на простом примере может и будет работать, только у меня не работает. Путь вот такой длинный: J:\Abonent4.Город\@Город-Sberbank\Export-2023\0156019111_10202810800190000111_200223.txt У меня на кнопках установлены вызовы других функций через блок кода, примерно так: [pre2] cRunBlock := cRunFun + "( '"+cVal+"' ,'"+aObj[1]+"', '"+aObj[2]+"', '"+cWrtFld+"' )" bBlock := &("{||"+cRunBlock+"}") SetProperty(cForm, aObj[1], "OnLostFocus", bBlock)[/pre2] Причём вызовов несколько. Это как то может повлиять на сбой фокуса ?

gfilatov2002: Andrey пишет: Путь вот такой длинный Для таких случаев используй преобразование пути с помощью функции _GetShortPathName(): cFileName := _GetShortPathName( cFileName )


Andrey: gfilatov2002 пишет: Для таких случаев используй преобразование пути с помощью функции _GetShortPathName(): Не помогает... Убрал русские буквы из пути. Думал что из диска J: подключённый через SUBST, но указание явно - тоже не работает, т.е. НЕ ВЫВОДИТ проводник на передний план рабочего стола компа, предыдущее модальное окно на переднем плане. [pre2]cFile = F:\DISK_J\ABONENT4.City\@City-Sberbank\Export-2023\0156019111_10202810800190000111_200223.txt c2File= F:\DISK_J\ABONENT4.City\@City-Sberbank\Export-2023\0156019111_10202810800190000111_200223.txt[/pre2] Что можно сделать ?

SergKis: Andrey пишет Что можно сделать ? для excel ты делаешь[pre2] hWnd := oExcel:hWnd // хендл окна Excel ShowWindow( hWnd, 6 ) // MINIMIZE windows ShowWindow( hWnd, 3 ) // MAXIMIZE windows BringWindowToTop( hWnd ) // a window on the foreground [/pre2] проделай для explorer.exe, поймав его hWnd через enumwindow() или через pid := ShellExcecuteEx(...) В hmg в примерах или lib был набор ф-й для pid (не могу вспомнить в данный момент) предыдущее модальное окно на переднем плане Сделай Minimaize этому окну, потом сделаешь Restore, возможно в нем Topmost сильно "заморозился"

Andrey: Пример C:\MiniGUI\SAMPLES\Advanced\ShellExec При вызове кнопки видно, что окно Хелпа МиниГуи становится после окна программы МиниГуи !!! Эта же программа лежит собранная где-то в 2019 году - Хелпа МиниГуи на переднем плане.

SergKis: Andrey пишет При вызове кнопки видно, что окно Хелпа МиниГуи становится после окна программы МиниГуи !!! Что не ясно в примере и причем здесь год ? [pre2] DEFINE WINDOW Win_1 ; AT 0,0 WIDTH 450 HEIGHT 300 ; TITLE "ShellExecuteEx() Using Demo" ; MAIN ; TOPMOST ; ON INIT This.Topmost := .F. ; FONT "Tahona" SIZE 14 ; NOMAXIMIZE NOSIZE ... [/pre2] ты в примерах всегда это пишешь (красным)

Andrey: SergKis пишет: Что не ясно в примере и причем здесь год ? Блин, упустил из вида. Спасибо, понял !

Andrey: Как из PID процесса можно получить хендл окна ? Т.е. при запуске: [pre2] nPid := ShellExecuteEx( 0, "open", "explorer.exe", '/select, ' + cFile, , SW_SHOWNORMAL )[/pre2] Получаю nPid, а как потом получить Хендл окна для изменения его ? [pre2] hWin := ????? nPid cTitle := GetWindowText( hWin ) cTitle += ": " + cFileNoPath(cFile) SetWindowText( hWin, cTitle ) // меняем текст Title [/pre2] Видел это - http://clipper.borda.ru/?1-4-0-00001093-000-0-0-1438070443 Кто нибудь реализовал ?

Haz: Andrey пишет: Видел это - http://clipper.borda.ru/?1-4-0-00001093-000-0-0-1438070443 Кто нибудь реализовал ? Реализовывал лет 5 назад, только обратную задачу по окну найти процесс, все работает. А в чем сложность протестировать ? там не более 10 строк кода будет всего. Учти только что у одного процесса может быть много окон ( кнопки, к примеру, это тоже окна ) https://learn.microsoft.com/en-us/windows/win32/winmsg/about-window-classes

SergKis: Haz пишет А в чем сложность протестировать ? Что есть в hmg примерах - танцует от hWnd, т.е. для explorer.exe [pre2] LOCAL cClass := "CabinetWClass" // класс окна explorer.exe ... nId := ShellExecuteEx( 0, "open", "explorer.exe", '/select, ' + cFile, , SW_SHOWNORMAL ) ... IF !Empty(nId) // запустился и прорисовался aWin := HandlesHbWin( , cClass, .T.) IF ( lRun := Len(aWin) > 0 ) i := 0 h := aWin[1] ? GetWindowThreadProcessId(h, @nThr, @nPid) // вернет Nil ?? i, h, nId, nPid, nThr ^^^ ^^^^ // разные значения [/pre2] Вопрос от Андрея и меня, как получить hWnd от nId ? Ведь из оной или разных программ может быть запущено несколько explorer.exe aWin := HandlesHbWin( , cClass, .T.) даст несколько hWnd. Пример тут https://TransFiles.ru/qyyji - внизу кнопка (1) запускает просмотр запущенного, на ней Reset - обновляет список, Excel запускается, в Reset видно - внизу кнопка (2) запускает explorer.exe с new Title и блокирует 2-ой запуск - внизу кнопка (3) останавливает explorer.exe с new Title - вверху кнопка 1) запускает explorer.exe (запустить можно несколько), тут вопрос и возникает (вверху) PS Мне хватало, на клиентской PC, помечать запущенную прогу, меняя title[pre2] t := GetWindowText( h ) SetWindowText( h, t +": "+cFile ) // меняем текст Title [/pre2] У Андрея RDP есть и такая фишка может не прокатить, или на своем столе он увидит только свой explorer.exe

Haz: SergKis пишет: Вопрос от Андрея и меня, как получить hWnd от nId ? примерно так [pre2] Func Test local hWnd := 0 local aWin := {} local hPid, hProcess hPID := hb_processOpen( "Explorer.exe /select," + cFile,,,,.F., @hProcess) aWin := EnumWindows() for each hWnd in aWin if hPID == GetWindowThreadProcessID(hWnd) // тут и hWnd и hPID и hProcess можно дополнительно указать титл "Проводник" и ClassName окна "Static" ЧТОБ КНОПКИ ОТСЕЧЬ ? hWnd , hPID, hProcess end END return nil [/pre2] НЕ ПРОВЕРЯЛ , позже

Haz: Haz пишет: НЕ ПРОВЕРЯЛ , позже Проверил , EXPLORER так не выловить ! он как то хитро запускается что ID процесса не выдает корректно Любое другое приложение запускаясь ловится отлично

SergKis: Haz пишет Проверил , EXPLORER так не выловить ! он как то хитро запускается что ID процесса не выдает корректно Ерунда получается, ты прав.[pre2] nId := ShellExecuteEx( 0, "open", aCmd[1], aCmd[2]+' '+aCmd[3], , SW_SHOWNORMAL ) DO EVENTS ; wApi_Sleep(1000) IF !Empty(nId) //hProc := hb_processOpen( "explorer.exe "+'/select, ' + cFile, , , , .F., @nPID ) hProc := hb_processOpen( cCmd, , , , .F., @nPID ) hb_processClose(hProc) aWin := HandlesHbWin( , cClass, .T.) // снимок ? procName(),cClass,nId,hProc,nPID, aWin FOR EACH hWnd IN aWin GetWindowThreadProcessID(hWnd, @nTread, @nProcID) ? hb_EnumIndex(hWnd), hWnd,nTread, nPID, nProcID NEXT ENDIF результат: 1-ый запуск 1 15729718 CabinetWClass _ShellExecute RUNEXPLORFILE2EX CabinetWClass 1516 912 11968 ARRAY[1] 2-ой запуск 1 15729718 12672 11968 6252 1 16516746 CabinetWClass _ShellExecute 2 15729718 CabinetWClass _ShellExecute RUNEXPLORFILE2EX CabinetWClass 900 1564 3936 ARRAY[2] 1 16516746 12652 3936 4356 2 15729718 12672 3936 6252 [/pre2] Любое другое приложение запускаясь ловится отлично Вернусь к своей схеме, проверена, работает[pre2] ... aPos := HandlesHbWin( cFile, cClass, .T.) // снимок ДО для cFile, проверка 2-го запуска IF Len(aPos) > 0 ; RETURN .F. // уже есть такой ENDIF aOld := HandlesHbWin( , cClass, .T.) // снимок ДО nId := ShellExecuteEx( 0, "open", "explorer.exe", '/select,'+' '+cFile, , SW_SHOWNORMAL ) DO EVENTS ; wApi_Sleep(1000) // ждем прорисовки и форм. Title IF !Empty(nId) // запустилcя ok! aWin := HandlesHbWin( , cClass, .T.) // снимок ПОСЛЕ IF Len(aWin) > 1 FOR EACH hWnd IN aWin nPos := aScan(aOld, hWnd) IF ( lNew := nPos == 0 ) ; EXIT ENDIF NEXT ELSE lNew := .T. hWnd := aWin[1] ENDIF DO EVENTS ; wApi_Sleep(100) IF lNew i := 0 t := GetWindowText( hWnd ) SetWindowText( hWnd, t +": "+cFile ) // меняем текст Title DO EVENTS ; wApi_Sleep(100) WHILE !cFile $ GetWindowText( hWnd ) .and. i++ < 10 // проверяем Title SetWindowText( hWnd, t +": "+cFile ) DO EVENTS ; wApi_Sleep(100) END ENDIF ENDIF ... [/pre2]

Andrey: Haz пишет: Любое другое приложение запускаясь ловится отлично Что-то у меня не получается... Покажи код как ловиться ?

Haz: Andrey пишет: Что-то у меня не получается... Покажи код как ловиться ? [pre2] #include "common.ch" #include "i_winuser.ch" #include "hbthread.ch" Func Main local hWnd := 0 local aWin := {} local hPid, hProcess local nT, nP, cClassName hPID := hb_processOpen( "Notepad.exe",,,,.F., @hProcess) hb_idlesleep(1) aWin := EnumWindows() for each hWnd in aWin cClassName := GetClassName( hWnd ) if cClassName == "Notepad" GetWindowThreadProcessID(hWnd, @nT, @nP) if hProcess == nP ? "Вот оно окно , делай что хочешь hWnd = ", hWnd, cClassName end end END return nil [/pre2]

Haz: Сергей пишет: Ерунда получается, ты прав. При попытке запуска EXPLORER.EXE управление передается SVCHOST и из него дочерним процессом запускается EXPLORER Поэтому hPID и nProcess имеют значения отличные от получаемых в hb_ProcessOpen() Попытка трассировки ProcessID и ParentProcessID ничего не дает и уходит в WinInit Остается только твой вариант - перед запуском снимок окон пользователя с Wnd.ClassName = 'CabinetWClass' и отлов нового после запуска.

Andrey: Haz пишет: if cClassName == "Notepad" GetWindowThreadProcessID(hWnd, @nT, @nP) if hProcess == nP ? "Вот оно окно , делай что хочешь hWnd = ", hWnd, cClassName end end А если запущено уже несколько Notepad пользователем, то что будет ? Т.е. уже есть открытые Notepad и я запускаю свой. Хочу поменять титул окна, чтобы знать что это мой экземпляр и облом с этим действием. Рассматриваю Notepad в качестве примера.

SergKis: Andrey пишет Хочу поменять титул окна, чтобы знать что это мой экземпляр и облом с этим действием. Облома нет, все работает по схеме, как для explorer.exe выше, т.е. титул окна меняется [pre2] FUNCTION StartNotepad(cFile, cCapt) LOCAL nId, aWin, hWnd, lNew, nPos, aPos, aOld, i, t LOCAL cClass := "Notepad" // класс окна DEFAULT cFile := ".\demo2.prg" DEFAULT cCapt := cFile aPos := HandlesHbWin( cCapt, cClass, .T.) // снимок ДО для cFile, проверка 2-го запуска IF Len(aPos) > 0 ; RETURN .F. // уже есть такой ENDIF aOld := HandlesHbWin( , cClass, .T.) // снимок ДО nId := ShellExecuteEx( 0, "open", "notepad.exe", cFile, , SW_SHOWNORMAL ) DO EVENTS ; wApi_Sleep(500) // ждем прорисовки и форм. Title IF !Empty(nId) // запустился ok! aWin := HandlesHbWin( , cClass, .T.) // снимок ПОСЛЕ IF Len(aWin) > 1 FOR EACH hWnd IN aWin nPos := aScan(aOld, hWnd) IF ( lNew := nPos == 0 ) ; EXIT ENDIF NEXT ELSE lNew := .T. hWnd := aWin[1] ENDIF DO EVENTS ; wApi_Sleep(100) IF lNew i := 0 t := GetWindowText( hWnd ) SetWindowText( hWnd, t + cCapt ) // меняем текст Title DO EVENTS ; wApi_Sleep(100) WHILE !cFile $ GetWindowText( hWnd ) .and. i++ < 10 // проверяем Title SetWindowText( hWnd, t + cCapt ) DO EVENTS ; wApi_Sleep(100) END ENDIF ENDIF RETURN .T. Вызов, например, такой StartNotepad(".\demo2.hbp", " - my start !") [/pre2]

Andrey: SergKis пишет: Облома нет, все работает по схеме, как для explorer.exe выше, т.е. титул окна меняется Только что попробовал, вот результат - титул окна НЕ МЕНЯЕТСЯ : [pre2] 1 526190 Notepad _a.txt – Блокнот 2 395100 Notepad _a4.txt – Блокнот 1 526190 Notepad _a.txt – Блокнот 2 395100 Notepad _a4.txt – Блокнот 1 329742 Notepad Demo2.hbp – Блокнот 2 526190 Notepad _a.txt – Блокнот 3 395100 Notepad _a4.txt – Блокнот ----- Вызов из: TEST_3(711) -> demo2.prg hProcessHandleShellExecuteEx= NIL [/pre2]



полная версия страницы