Форум » GUI » МиниГуи и чужая программа... » Ответить

МиниГуи и чужая программа...

Andrey: Мне пишут: Возникла необходимость отслеживать окно другой программы (текстовый редактор, просмотрщик PDF) и при необходимости другую программу закрывать. Подобными отслеживаниями, на сколько я знаю, ты занимался. Если можно, короткие выжимки кода для решения данной задачи. Я думаю многим эта тема будет интересна, из-за этого выношу на всеобщий обзор. Кто-нибудь добавит или поправит меня. 1) Для того чтобы управлять другой программой, нужно знать ХЕНДЛ окна этой программы. Как его получить в примерах есть. Вот примерно так я делал: [more][pre2] STATIC lTrayTasks := .f. // нет показа скрытых окон aDim := ListApps() .... /////////////////////////////////////////////////////////////////////////// #define GW_HWNDFIRST 0 #define GW_HWNDLAST 1 #define GW_HWNDNEXT 2 #define GW_HWNDPREV 3 #define GW_OWNER 4 #define GW_CHILD 5 *--------------------------------------------------------* Function ListApps() *--------------------------------------------------------* LOCAL aWindows := {}, cTitle := "", iWindow, cStr, i:=1 LOCAL hWnd := GetWindow( GetForegroundWindow(), GW_HWNDFIRST ) // Get the first window WHILE hWnd != 0 // Loop through all the windows cTitle := GetWindowText( hWnd ) IF GetWindow( hWnd, GW_OWNER ) = 0 .AND.; // If it is an owner window IsWindowVisible( hWnd ) .AND. ; // If it is a visible window !EMPTY( cTitle ) .AND.; // If the window has a title !( "DOS Session" $ cTitle ) .AND.; // If it is not DOS session !( cTitle == "Program Manager" ) // If it is not the Program Manager AADD( aWindows, { hWnd, cTitle, IsWindowVisible( hWnd ) } ) ENDIF hWnd := GetWindow( hWnd, GW_HWNDNEXT ) // Get the next window ENDDO if lTrayTasks hWnd := GetWindow( GetForegroundWindow(), GW_HWNDFIRST ) WHILE hWnd != 0 // Loop through all the windows cTitle := GetWindowText( hWnd ) IF GetWindow( hWnd, GW_OWNER ) = 0 .AND.; // If it is an owner window !IsWindowVisible( hWnd ) .AND.; // If it is a visible window !EMPTY( cTitle ) .AND.; // If the window has a title !( "MS_" $ cTitle ) .AND.; // If it is not System apps !( "DDE" $ cTitle ) .AND.; // If it is not System apps !( "SYSTEM" $ cTitle ) .AND.; // If it is not System apps !( "SENS" $ cTitle ) .AND.; // If it is not System apps !( "WIN95" $ cTitle ) .AND.; // If it is not System apps !( "Spooler" $ cTitle ) .AND.; // If it is not System apps !( "Thread" $ cTitle ) .AND.; // If it is not System apps !( "DOS Session" $ cTitle ) .AND.; // If it is not DOS session !( cTitle == "Program Manager" ) // If it is not the Program Manager AADD( aWindows, { hWnd, cTitle, IsWindowVisible( hWnd ) } ) ENDIF hWnd := GetWindow( hWnd, GW_HWNDNEXT ) // Get the next window ENDDO endif // отладка в файл cStr := "" FOR iWindow := 1 TO LEN(aWindows) cStr += STR(iWindow,3)+";"+STR(aWindows[iWindow,1])+"; "+aWindows[iWindow,2] + CRLF NEXT hb_memowrit( ChangeFileExt( Application.ExeName, ".log" ), cStr ) Return aWindows [/pre2] [/more] 2) Закрыть чужое окно примерно так: [pre2]#define WM_CLOSE 0x0010 #define WM_DESTROY 0x0002 .... lAsk2Save := ??? PostMessage( iWindow, IF(lAsk2Save, WM_CLOSE, WM_DESTROY), 0, 0 ) // Close the window DO EVENTS[/pre2] Только я уже не помню разницу между WM_CLOSE и WM_DESTROY Давно делал в 2014 году ещё...

Ответов - 11

Dima: Andrey пишет: Только я уже не помню разницу между WM_CLOSE и WM_DESTROY гугл помнит

SergKis: Не давно делал для получения hWnd[pre2] *-----------------------------------------------------------------------------* STATIC FUNCTION HandlesDosBox() *-----------------------------------------------------------------------------* LOCAL h, t LOCAL cText := 'DOSBox ' LOCAL aDBox := {} LOCAL aRet := {} AEVal( EnumWindows(), {|hw| iif( GetClassName(hw) == "SDL_app", AAdd( aDBox, hw ), Nil )} ) FOR EACH h IN aDBox t := GetWindowText( h ) IF cText $ t /* .and. upper( cText ) $ t */ ; AAdd( aRet, h ) ENDIF NEXT RETURN aRet *-----------------------------------------------------------------------------* STATIC FUNCTION HandlesHbWin( cText, cClass, lLogOut ) *-----------------------------------------------------------------------------* LOCAL i, h, t LOCAL aWnd := EnumWindows() LOCAL aTmp := {} LOCAL aRet := {} IF empty(cClass) ; aTmp := aWnd ELSE ; AEVal(aWnd, {|hw| iif( GetClassName(hw) == cClass, AAdd( aTmp, hw ), )}) ENDIF IF ! empty(cText) .and. HB_ISCHAR(cText) .and. Len(aTmp) > 0 FOR EACH h IN aTmp t := GetWindowText( h ) IF cText $ t ; AAdd( aRet, h ) ENDIF NEXT ELSE aRet := aTmp ENDIF IF ! Empty(lLogOut) FOR i := 1 TO Len(aTmp) t := GetWindowText(aTmp[ i ]) MsgLog( str(i, 5), aTmp[ i ], GetClassName(aTmp[ i ]), t ) NEXT ENDIF RETURN aRet Использование для DosBox LOCAL aAll := HandlesDosBox() LOCAL nAll := Len(aAll) ... _Execute( 0, , cRun, '-conf dosbox.conf -noconsole', cPath ) hTmp := nJ := nW := 0 ; wApi_Sleep(50) FOR nI := 1 TO 11 // опр. новый handle DosBox nW := 50 If nI > 2 nJ ++ nW := nWait EndIf wApi_Sleep( nW ) oMain:StatusBar:Say( cWait + ' ' + iif( nJ > 0, hb_ntos( nJ ), '' ) ) aTmp := HandlesDosBox() IF ( nTmp := Len( aTmp ) ) > 0 IF nAll > 0 FOR nK := 1 TO nTmp nN := AScan( aAll, aTmp[ nK ] ) IF nN == 0 hTmp := aTmp[ nK ] EXIT ENDIF NEXT ELSE hTmp := ATail( aTmp ) ENDIF ENDIF IF ! empty( hTmp ) ; EXIT ENDIF NEXT oMain:StatusBar:Say( '' ) IF ! empty( hTmp ) // нашли row := This.&(cName).Cargo [ DOSBOX_ROW ] col := This.&(cName).Cargo [ DOSBOX_COL ] nRow := iif( Empty(row), nRow, row ) nCol := iif( Empty(col), nCol, col ) width := GetWindowWidth (hTmp) height := GetWindowHeight(hTmp) MoveWindow ( hTmp , nCol , nRow , width , height , .T. ) // меняем позицию окна DosBox (как ставили при пред. запуске) This.&(cName).Cargo [ DOSBOX_HANDLE ] := hTmp This.&(cName).Cargo [ DOSBOX_ROW ] := nRow This.&(cName).Cargo [ DOSBOX_COL ] := nCol This.&(cName).Cargo [ DOSBOX_SEND ] := cSend This.&(cName).Cargo [ DOSBOX_RECV ] := cRecv This.&(cName).Cargo [ DOSBOX_KOD ] := cKod This.&(cName).Enabled := .F. This.Dos.Enabled := .T. DO EVENTS ENDIF (ThisWindow.Object):Action := .T. ... На таймере висит ф-я, определяющая команды от DosBox на запуск wvt или hmg программ цветом использование ф-ий выше указанных *----------------------------------------------------------------------------* STATIC FUNCTION Timer_IsDosBoxHandle() *----------------------------------------------------------------------------* LOCAL aTmp, cItm, aMnu, nN, nI := 0, nK, nH, nP LOCAL nDos := 0, aDos, hDos, cStr, cTitl, cClNm LOCAL cTxt := '', cSend, hWvt, aWvt, lBlk LOCAL aFil := {}, cRecv, cExe, cPar, nHmg, hHmg LOCAL cFil, nRow, nCol, cIni, cKod, cDrv, cMount LOCAL cDir, cBlk, cRun, cDsk, cPll, cPath LOCAL cSpooler, cFilePrn, cFun, cMsg, cWait, lWait This.Dos.Enabled := .F. WITH OBJECT oMain:Cargo cPath := :cDosBoxPath // :cCurDir = C:\DosBox cMount := upper( :cDosBoxBase ) // Mount cFil := :cHbkIniDat cPll := :cPll cSpooler := :cPll + 'SPOOLER' + '\' cFilePrn := :cPll + 'FILEPRN' + '\' END WITH aMnu := ThisWindow.Cargo:Menu aDos := HandlesDosBox() FOR EACH cItm IN aMnu nI ++ aTmp := This.&(cItm).Cargo hDos := aTmp [ DOSBOX_HANDLE ] // handle DosBox window nRow := aTmp [ DOSBOX_ROW ] nCol := aTmp [ DOSBOX_COL ] cSend := aTmp [ DOSBOX_SEND ] cRecv := aTmp [ DOSBOX_RECV ] cKod := aTmp [ DOSBOX_KOD ] hWvt := aTmp [ DOSBOX_WVT ] lBlk := aTmp [ DOSBOX_BLK ] IF ! empty( hDos ) IF ( nN := AScan( aDos, hDos ) ) == 0 hDos := hWvt := 0 cSend := cRecv := cKod := '' This.&(cItm).Enabled := .T. ELSE nDos += 1 nRow := GetWindowRow( hDos ) nCol := GetWindowCol( hDos ) ENDIF DO EVENTS ENDIF This.&(cItm).Cargo [ DOSBOX_HANDLE ] := hDos This.&(cItm).Cargo [ DOSBOX_ROW ] := nRow This.&(cItm).Cargo [ DOSBOX_COL ] := nCol This.&(cItm).Cargo [ DOSBOX_SEND ] := cSend This.&(cItm).Cargo [ DOSBOX_RECV ] := cRecv This.&(cItm).Cargo [ DOSBOX_KOD ] := cKod If ! empty(hDos) cIni := cSend+cItm+'.ini' cBlk := cSend+cItm+'.blk' cMsg := cSend+cItm+'.msg' lBlk := ! empty(lBlk) If hb_FileExists( cIni ) wApi_Sleep(200) lBlk := hb_FileExists( cBlk ) cTitl := gIniC7( cIni, [RUN], 'Txt' , '' ) cClNm := gIniC7( cIni, [RUN], 'Cln' , '' ) cDrv := gIniC7( cIni, [RUN], 'Drv' , '' ) cDir := gIniC7( cIni, [RUN], 'Ctl' , '' ) cRun := gIniC7( cIni, [RUN], 'Run' , '' ) cWait := gIniC7( cIni, [RUN], 'Wait', 'Y' ) lWait := 'Y' $ upper(cWait) fErase( cIni ) If ! empty(cDir) .and. ! empty(cRun) nK := At(' ', cRun) cExe := Left(cRun, nK-1) cDsk := iif( empty(cDsk), '""', cDsk ) cPar := Trim(Subs(cRun, nK+1))+' '+cMsg hWvt := nHmg := 0 IF lower(right(cExe, 4)) == '.fun' cFun := left(cExe, RAt('.', cExe)-1) If lower(cFun) == 'copy_to' ; Copy_To (cMount, cDrv, cPar) ElseIf lower(cFun) == 'copy_from' ; Copy_From(cMount, cDrv, cPar) ElseIf lower(cFun) == 'copy_file' ; Copy_File(cMount, cDrv, cPar) EndIf fErase( cBlk ) lBlk := .F. ELSEIF lower(right(cExe, 4)) == '.prg' .or. lower(right(cExe, 4)) == '.hrb' ELSE IF hb_FileExists(cExe) If lWait aWwt := HandlesHbWin(cTitl, cClNm) oMain:Minimize() DO EVENTS ENDIF nHmg := _ExecuteEx( 0, , cExe, cPar, cDir ) // это ShellExecuteEx(...) wApi_Sleep(1000) DO EVENTS IF lWait IF cClNm == WVT_CLASS_NAME ; wApi_Sleep(1000) ENDIF If ! Empty(nHmg) FOR EACH nH IN HandlesHbWin(cTitl, cClNm) IF ( nP := AScan(aWvt, nH) ) == 0 hWvt := nH EXIT ENDIF NEXT EndIf DO EVENTS ELSE fErase( cBlk ) ENDIF ELSE MsgBox('File not found !'+CRLF+cExe, 'Info-'+cItm) fErase( cBlk ) ENDIF ENDIF EndIf ElseIf lBlk IF ! empty(hWvt) .and. hb_FileExists( cBlk ) IF Empty( AScan( HandlesHbWin(), hWvt ) ) fErase( cBlk ) wApi_Sleep(200) ENDIF ENDIF IF ! hb_FileExists( cBlk ) wApi_Sleep(200) oMain:Restore() DO EVENTS lBlk := .F. hWvt := 0 BringWindowToTop( hDos ) DO EVENTS ENDIF EndIf EndIf This.&(cItm).Cargo [ DOSBOX_WVT ] := hWvt This.&(cItm).Cargo [ DOSBOX_BLK ] := ! empty(lBlk) AAdd( aFil, { cItm, hDos, nRow, nCol, cSend, cRecv, cKod, hWvt, lBlk } ) NEXT hb_memowrit( cFil, hb_valtoexp( aFil ) ) IF nDos > 0 cTxt := chr(9)+hb_ntos(nDos) This.Dos.Enabled := .T. ENDIF oMain:StatusBar:Say( cTxt, 3) oMain:Cargo:nDosBoxRun := Val( cTxt ) RETURN Nil ... [/pre2] Для MiniGui имя окна MAIN является именем класса, т.е. правильно называя main окна, можно находить по нему нужное окно hWnd для hmg

Vlad04: Ок Спасибо, ищет, закрывает


Vlad04: Ещё надо отследить закрылась или нет чужая программа. Конечно, можно, по выше указанному алгоритму - если исчезла программа, значит закрылась. Но может ак-то короче.

SergKis: Vlad04 пишет Но может ак-то короче. Если имеете текст заголовка, то ищете по нему, подождав к примеру wApi_Sleep(500) после посылки сообщения на закрытие. Если несколько экземпляров этой программы, то по handle ищем, кому было сообщение на закрытие или по алгоритму

Andrey: SergKis пишет: То есть: если PID есть, то приложение уже запустилось, если не сработал PostMessage(hWnd, WM_CLOSE, 0, 0) для внешнего приложения, делаем TerminateProcess( hPid ), если это не помогло, то запускаем cRun := %windir%/System32/taskkill.exe /T /IM <AppName.exe> через _ExecuteEx( 0, "runas", cRun, , , SW_HIDE ) С этими изменениями стало проще бороться с внешними приложениями Что то непонятно мне как делать снятие задачи. Имеется запущенная программа с переходом MAIN-окна на другое. MAIN-окно NOSHOW !!! Делаю в коде так: [pre2] cAppTitle := "Мой-тест" hWnd := FindWindowEx( ,,, cAppTitle ) if hWnd # 0 iif( IsIconic( hWnd ), _Restore( hWnd ), SetForeGroundWindow( hWnd ) ) PostMessage( hWnd, WM_CLOSE, 0, 0 ) wApi_Sleep(500) endif[/pre2] Прога не снимается, на экране MAIN окно появляется. Почему ? Как дальше прогу снять по - делаем TerminateProcess( hPid ) ?

Andrey: SergKis пишет: если это не помогло, то запускаем cRun := %windir%/System32/taskkill.exe /T /IM <AppName.exe> через _ExecuteEx( 0, "runas", cRun, , , SW_HIDE ) Что-то не работает под Win8.1 это. Выдаёт такую фигню: Пришлось делать так: [pre2] hWnd := FindWindowEx( ,,, cAppTitle ) IF hWnd # 0 cRun := "taskkill.exe" cPar := " /T /IM " + cFileNoPath(cFileExe) _ExecuteEx( 0, "open", cRun, cPar, , SW_HIDE ) wApi_Sleep(500) ENDIF[/pre2]

Andrey: Я правильно ли понимаю, что если MAIN-окно NOSHOW, то функция hWnd := FindWindowEx( ,,, cAppTitle ) возвращает хендл следующего окна которое не NOSHOW ? А есть ли функция которое всегда возвращает хендл MAIN-окна ? Интересует только отдельная функция. Функцию для перебора всех окон - ahWnd := EnumWindows() знаю.

SergKis: Andrey Т.к. у нас откл. 16 российских каналов, пришлось по быстрому соорудить просмотр iptv на VLC и упр. им. Работает управление, показывает VLC iptv каналы Тексты (от ProcInfo.lib отказался в пользу набора C ф-ий из примера Advanced\EnumProcesses) [pre2] STATIC FUNCTION VlcHandle( lLog ) LOCAL cVlc := oApp(1):cClassVlc // "Qt5QWindowIcon" LOCAL cTxt := oApp(1):cTitleVlc // " VLC" LOCAL aVlc := HandlesHbWin( , cVlc, !Empty(lLog) ) LOCAL lVlc := .F., hVlc, nVlc LOCAL hYes := 0 LOCAL nCnt := 0 FOR nVlc := 1 TO Len(aVlc) hVlc := aVlc[ nVlc ] cVlc := GetWindowText( hVlc ) IF cTxt $ cVlc hYes := hVlc lVlc := .T. nCnt += 1 ELSE DO EVENTS ; PostMessage(hVlc, WM_CLOSE, 0, 0) DO EVENTS ; InkeyGui(20) ENDIF NEXT RETURN iif( lVlc, hYes, 0 ) STATIC FUNCTION VlcIs( nMax ) LOCAL nVlc := 0 LOCAL hVlc := VlcHandle() LOCAL lVlc := .T. Default nMax := 50 IF ! Empty( hVlc ) WHILE ( ++nVlc ) <= nMax InkeyGui(20) hVlc := VlcHandle() IF ( lVlc := Empty( hVlc ) ) ; EXIT ENDIF END ENDIF RETURN ( ! lVlc ) STATIC FUNCTION VlcStart( lLog ) LOCAL hVlc := VlcHandle( lLog ) LOCAL cCtl := System.ProgramFilesFolder LOCAL cVlc := "\VideoLAN\VLC" LOCAL cExe := "vlc.exe" LOCAL hRun := 0, cPth, nMax // "C:\Program Files\VideoLAN\VLC" путь к VLC LOCAL cRun := (App.Object):Cargo:cRun IF Empty( cRun ) // первый вход\старт VLC cPth := cCtl + cVlc cRun := cPth + "\" + cExe IF ! hb_DirExists( cPth ) .and. "(x86)" $ cCtl cCtl := trim( StrTran(cCtl, "(x86)") ) cPth := cCtl + cVlc IF ! hb_DirExists( cPth ) MsgStop("Directory not found !"+CRLF+cPth, "ERROR") RETURN hRun ENDIF ENDIF cRun := cPth + "\" + cExe IF ! hb_FileExists( cRun ) MsgStop("VLC file not found !"+CRLF+cRun, "ERROR") RETURN hRun ENDIF (App.Object):Cargo:cRun := cRun ENDIF IF ! empty( hVlc ) DO EVENTS ; PostMessage(hVlc, WM_CLOSE, 0, 0) DO EVENTS ; InkeyGui(20) VlcIs() ; hVlc := VlcHandle( lLog ) ENDIF IF Empty( hVlc ) .or. hVlc != hHandlesVLC DO EVENTS ; hRun := _ExecuteEx( 0, "open", cRun, , cPth, 3 ) // SHellExecuteEx( 0, "open", cRun, , cPth, 3 ) DO EVENTS ; InkeyGui(300) hProcessVLC := hHandlesVLC := 0 IF ! Empty( hRun ) nMax := 20 WHILE Empty(hVlc) .and. --nMax >= 0 hVlc := VlcHandle( lLog ) ; InKeyGui(100) END hProcessVLC := hRun hHandlesVLC := hVlc SetForeGroundWindow( hVlc ) ; InkeyGui(30) IF GetForeGroundWindow() != hVlc SetForeGroundWindow( hVlc ) ; InkeyGui(30) ENDIF IF Empty( (App.Object):Cargo:cCapt ) (App.Object):Cargo:cCapt := GetWindowText( hVlc ) ENDIF InkeyGui(300) ENDIF ENDIF RETURN hRun STATIC FUNCTION VlcClose( lLog, lClose ) LOCAL nVlc := 0, nProc, nThread LOCAL hVlc := VlcHandle( lLog ) Default lClose := .T. IF lClose .and. ! Empty( hVlc ) DO EVENTS ; PostMessage(hVlc, WM_CLOSE, 0, 0) DO EVENTS ; InkeyGui(20) VlcIs() hVlc := VlcHandle( lLog ) ENDIF IF ! Empty( hProcessVLC ) .and. ! Empty( hVlc ) GetWindowThreadProcessId( hVlc, @nThread, @nProc ) TerminateProcess ( nProc ) ; InkeyGui(200) ; VlcIs() DO EVENTS hVlc := VlcHandle( lLog ) IF ! Empty( hVlc ) GetWindowThreadProcessId( hVlc, @nThread, @nProc ) TerminateProcess ( nProc ) ; InkeyGui(200) ; VlcIs() DO EVENTS ENDIF hProcessVLC := 0 ENDIF IF ! Empty( hVlc := VlcHandle( lLog ) ) ; VlcIs() ENDIF hHandlesVLC := 0 RETURN Empty( VlcHandle( lLog ) ) STATIC FUNCTION SetVlcKanal( nPos, uAdr ) LOCAL hVlc := VlcHandle() LOCAL cFoc := oApp(1):cBtnFocus LOCAL nFoc := oApp(1):nBtnFocus LOCAL aFoc := oApp(1):aBtnFocus LOCAL aAdr := oApp(1):aAdrFocus LOCAL nMax, cAdr, cGru, nBtn LOCAL cCap, cNam, cTxt, lAdr LOCAL lPos := nPos == Nil Default nPos := 0 IF Empty( hVlc ) ; RETURN Nil ENDIF This.Minimize ; DO EVENTS IF ISARRAY( uAdr ) ; aAdr := AClone( uAdr ) ENDIF lAdr := Empty( nPos ) .and. Empty( uAdr ) IF IsIconic( hVlc ) ShowWindow( hVlc, SW_MINIMIZE ) ShowWindow( hVlc, SW_RESTORE ) ENDIF nMax := 100 WHILE GetForeGroundWindow() != hVlc .and. --nMax > 0 InkeyGui(20) ; SetForeGroundWindow( hVlc ) END ShowWindow( hVlc, SW_MAXIMIZE ) InkeyGui(10) //IF GetForeGroundWindow() != hVlc // BringWindowToTop( hVlc ) ; InkeyGui(20) //ENDIF hHandlesVLC := hVlc aAdr := ASize(aAdr, 7) cNam := aAdr[ 1 ] cGru := aAdr[ 2 ] cAdr := aAdr[ 3 ] nBtn := aAdr[ 4 ] ; Default nBtn := 0 IF ! Empty( cAdr ) oApp(1):nBtnFocus := iif( lPos, 1, nPos ) oApp(1):cBtnFocus := iif( Empty(nPos), "", "o"+hb_ntos(nPos) ) oApp(1):aBtnFocus := { cNam, cGru, cAdr, nBtn } oApp(1):aAdrFocus := { cNam, cGru, cAdr, nBtn } cCap := oApp(1):cCapt cCap := cNam + " - " + cCap cTxt := cCap System.Clipboard := cAdr SetWindowText( hVlc, cCap ) HMG_PressKey(VK_CONTROL, VK_V) ; InkeyGui(20) SetWindowText( hVlc, cCap ) ; nMax := 100 WHILE Len( HandlesHbWin( , oApp(1):cClassVlc ) ) < 2 .and. --nMax < 0 ; InkeyGui(10) END HMG_PressKey(VK_RETURN) ; InkeyGui(20 ) HMG_PressKey(VK_RETURN) ; InkeyGui(20 ) SetWindowText( hVlc, cCap ) ; InkeyGui(200) nMax := 10 WHILE --nMax > 0 ; SetWindowText( hVlc, cCap ) ; InkeyGui(200) END SetWindowText( hVlc, cCap ) ENDIF nPos := iif( lAdr, nFoc, oApp(1):nBtnFocus ) cNam := iif( Empty( nPos ), "oIPTV", "o"+hb_ntos(nPos) ) This.&(cNam).SetFocus RETURN Nil // PostMessage( oBRM:hBrowse, WM_KEYDOWN, VK_F15, 0) // PostMessage( oBRM:hBrowse, WM_KEYP , VK_F15, 0) *-----------------------------------------------------------------------------* STATIC FUNCTION HandlesHbWin( cText, cClass, lLogOut ) *-----------------------------------------------------------------------------* LOCAL i, h, t LOCAL aWnd := EnumWindows() LOCAL aTmp := {} LOCAL aRet := {} IF Empty(cClass) aTmp := aWnd ELSE FOR EACH h IN aWnd IF IsWindowHandle( h ) .and. GetClassName( h ) == cClass AAdd( aTmp, h ) ENDIF NEXT ENDIF IF ! empty(cText) .and. HB_ISCHAR(cText) .and. Len(aTmp) > 0 FOR EACH h IN aTmp IF IsWindowHandle( h ) t := GetWindowText( h ) IF cText $ t ; AAdd( aRet, h ) ENDIF ENDIF NEXT ELSE aRet := aTmp ENDIF IF ! Empty(lLogOut) FOR i := 1 TO Len(aTmp) IF IsWindowHandle( aTmp[ i ] ) t := GetWindowText(aTmp[ i ]) _LogFile( .T., str(i, 5), aTmp[ i ], GetClassName(aTmp[ i ]), t ) ENDIF NEXT ENDIF RETURN aRet Применение ... SET DEFAULT ICON TO "1MAIN_ICO" SET MENUSTYLE EXTENDED // switch menu style to advanced SetMenuBitmapHeight( GetFontHeight("Font_1") ) // set image size ... VlcHandle() IF Empty( VlcStart() ) ; QUIT // First start VLC ENDIF nY := nX := 0 nW := System.DesktopWidth nH := oApp(1):nBtnHeight DEFINE WINDOW &cForm AT nY,nX WIDTH nW HEIGHT nH ; TITLE SHOW_TITLE ; MAIN NOMAXIMIZE NOSIZE NOSYSMENU NOCAPTION ; ON INIT {|| This.Topmost := .F., This.Minimize, ; DoEvents(), _wPost(11, , Nil) } ; ON RELEASE {|| dbCloseAll(), VlcClose() } ; ON GOTFOCUS {|| Local nf := oApp(1):nBtnFocus Local cf := "o"+hb_ntos(nf) If _IsControlDefined( cf, This.Name ) This.&(cf).SetFocus DO EVENTS EndIf Return Nil } _BtnFafour( 1, 1 ) ... WITH OBJECT oWnd() :Event( 1, {|| // context меню IPTV каналов Local y := This.oIPTV.Row+This.oIPTV.Height Local x := This.oIPTV.Col Local a := oApp(1):oGrp:GetAll(.T.) Local c := oApp(1):cBtnFocus Local f := {"Font_1", "Font_2"} If !Empty( c ) ; This.&(c).SetFocus ; DO EVENTS EndIf Context_Menu( y, x, 100, a, "IPTV каналы :", "Выход", f ) Return Nil } ) :Event( 2, {|| // context меню режимов VLC Local y := This.oVlc.Row+This.oVlc.Height Local x := This.oVlc.Col Local c := oApp(1):cBtnFocus Local f := {"Font_1", "Font_2"} Local a := {"Перезапустить медиапроигрыватель VLC", ; "Refresh (обновить) перепоказ канала" , ; "Таймер выключения работы программы" ; } If !Empty( c ) ; This.&(c).SetFocus ; DO EVENTS EndIf Context_Menu( y, x, 300, a, "Режимы работы :", "Выход", f ) Return Nil } ) :Event( 3, {|| // работа TimerEnd, TimerCnt IF oApp(1):nTimerEnd > 0 oApp(1):nTimerCnt += 1 IF oApp(1):nTimerCnt >= oApp(1):nTimerEnd This.TimerEnd.Enabled := .F. _wSend(99) ENDIF ENDIF Return Nil } ) :Event( 9, {|| // context меню действий с VLC Return Nil } ) :Event(10, {|ow,ky,aa| ky := oApp(1):nBtnFocus, aa := oApp(1):aAdrFocus, ; VlcClose(), VlcStart(), DoEvents(), ; SetForeGroundWindow( ow:Handle ), DoEvents(), ; SetFocus( ow:Handle ), DoEvents(), SetVlcKanal(ky, aa) }) ... [/pre2] На win8.1, win10 работает

Andrey: SergKis пишет: То есть: делаем TerminateProcess( hPid ), А как получить hPid программы ? Если программу запустили через ShellExecute()

SergKis: Andrey Посмотри Скрытый текст, который выше публиковал, там все есть



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