On-line: гостей 0. Всего: 0 [подробнее..]
АвторСообщение
постоянный участник




Пост N: 6569
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 31.01.20 03:01. Заголовок: МиниГуи и чужая программа...


Мне пишут:
Возникла необходимость отслеживать окно другой программы (текстовый редактор, просмотрщик PDF)
и при необходимости другую программу закрывать.
Подобными отслеживаниями, на сколько я знаю, ты занимался.
Если можно, короткие выжимки кода для решения данной задачи.


Я думаю многим эта тема будет интересна, из-за этого выношу на всеобщий обзор.
Кто-нибудь добавит или поправит меня.

1) Для того чтобы управлять другой программой, нужно знать ХЕНДЛ окна этой программы.
Как его получить в примерах есть.
Вот примерно так я делал:
Скрытый текст


2) Закрыть чужое окно примерно так:
#define WM_CLOSE        0x0010 
#define WM_DESTROY 0x0002
....
lAsk2Save := ???
PostMessage( iWindow, IF(lAsk2Save, WM_CLOSE, WM_DESTROY), 0, 0 ) // Close the window
DO EVENTS

Только я уже не помню разницу между WM_CLOSE и WM_DESTROY
Давно делал в 2014 году ещё...

Спасибо: 0 
ПрофильЦитата Ответить
Ответов - 11 [только новые]


администратор




Пост N: 7159
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 31.01.20 10:42. Заголовок: Andrey пишет: Тольк..


Andrey пишет:

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


гугл помнит

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 3017
Зарегистрирован: 17.02.12
ссылка на сообщение  Отправлено: 31.01.20 11:16. Заголовок: Не давно делал для п..


Не давно делал для получения hWnd
 
*-----------------------------------------------------------------------------*
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
...

Для MiniGui имя окна MAIN является именем класса, т.е. правильно называя main окна, можно
находить по нему нужное окно hWnd для hmg

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник


Пост N: 835
Зарегистрирован: 13.10.05
ссылка на сообщение  Отправлено: 31.01.20 14:08. Заголовок: Ок Спасибо, ищет, за..


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

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник


Пост N: 837
Зарегистрирован: 13.10.05
ссылка на сообщение  Отправлено: 06.02.20 11:05. Заголовок: Ещё надо отследить з..


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

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 3023
Зарегистрирован: 17.02.12
ссылка на сообщение  Отправлено: 06.02.20 13:59. Заголовок: Vlad04 пишет Но може..


Vlad04 пишет
 цитата:
Но может ак-то короче.


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

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 6910
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 12.03.21 07:37. Заголовок: SergKis пишет: То е..


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 !!!
Делаю в коде так:
   cAppTitle := "Мой-тест"  
hWnd := FindWindowEx( ,,, cAppTitle )

if hWnd # 0
iif( IsIconic( hWnd ), _Restore( hWnd ), SetForeGroundWindow( hWnd ) )
PostMessage( hWnd, WM_CLOSE, 0, 0 )
wApi_Sleep(500)
endif

Прога не снимается, на экране MAIN окно появляется.
Почему ?
Как дальше прогу снять по - делаем TerminateProcess( hPid ) ?

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 6911
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 12.03.21 08:41. Заголовок: SergKis пишет: есл..


SergKis пишет:

 цитата:

если это не помогло, то запускаем
cRun := %windir%/System32/taskkill.exe /T /IM <AppName.exe> через
_ExecuteEx( 0, "runas", cRun, , , SW_HIDE )



Что-то не работает под Win8.1 это.
Выдаёт такую фигню:

Пришлось делать так:
   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


Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 6912
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 12.03.21 09:25. Заголовок: Я правильно ли поним..


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

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 3606
Зарегистрирован: 17.02.12
ссылка на сообщение  Отправлено: 12.03.21 11:44. Заголовок: Andrey Т.к. у нас о..


Andrey
Т.к. у нас откл. 16 российских каналов, пришлось по быстрому соорудить просмотр iptv на VLC и упр. им.
Работает управление, показывает VLC iptv каналы
Тексты (от ProcInfo.lib отказался в пользу набора C ф-ий из примера Advanced\EnumProcesses) Скрытый текст

На win8.1, win10 работает

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 6916
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 14.03.21 15:43. Заголовок: SergKis пишет: То е..


SergKis пишет:

 цитата:
То есть:
делаем TerminateProcess( hPid ),



А как получить hPid программы ?
Если программу запустили через ShellExecute()

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 3612
Зарегистрирован: 17.02.12
ссылка на сообщение  Отправлено: 14.03.21 15:48. Заголовок: Andrey Посмотри Скр..


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

Спасибо: 0 
ПрофильЦитата Ответить
Ответ:
1 2 3 4 5 6 7 8 9
большой шрифт малый шрифт надстрочный подстрочный заголовок большой заголовок видео с youtube.com картинка из интернета картинка с компьютера ссылка файл с компьютера русская клавиатура транслитератор  цитата  кавычки моноширинный шрифт моноширинный шрифт горизонтальная линия отступ точка LI бегущая строка оффтопик свернутый текст

показывать это сообщение только модераторам
не делать ссылки активными
Имя, пароль:      зарегистрироваться    
Тему читают:
- участник сейчас на форуме
- участник вне форума
Все даты в формате GMT  3 час. Хитов сегодня: 18
Права: смайлы да, картинки да, шрифты да, голосования нет
аватары да, автозамена ссылок вкл, премодерация откл, правка нет