Форум » [x]Harbour » Пара простых вопросов ;) » Ответить

Пара простых вопросов ;)

Dima: 1. Как узнать что путь к папке из которой запускается программа имеет символы кирилицы ? На ум приходит такой способ [pre2] proc main() local a REQUEST HB_LANG_RU866 HB_LANGSELECT("RU866") REQUEST HB_CODEPAGE_RU866 hb_cdpSelect( "RU866" ) a:=curdir() ? a if hb_oemtoansi(a)#a ? "Есть кирилица" endif wait RETURN NIL [/pre2] Есть еще метода ? 2. Как узнать что путь к папке из которой запускается программа имеет длинные имена ? На вскидку приходит вариант разбить на токены с разделителем "\" и затем чекать длины всех токенов. Есть еще метода ?

Ответов - 85, стр: 1 2 3 4 5 All

Dima: up

Haz: Dima пишет: up 1 проверить на ASC коды весь путь , если есть ASC кроме латинских то... 2 не помню на вскидку фенкцию ((( но есть точно - та что получает короткое имя и если есть в пути длинные - тто длинна будет разной и в короткой версии будет знак тильда

Dima: понял , затестю завтра. спасибо !


Haz: Dima пишет: не помню на вскидку фенкцию cShot := GETSHORTFILENAME( cLongName ) ============================================= #pragma BEGINDUMP #include <windows.h> #include "hbapi.h" HB_FUNC( GETSHORTFILENAME ) { char pszReturn[ MAX_PATH ] ; pszReturn[0]= '\0' ; GetShortPathName( hb_parcx( 1 ), pszReturn, MAX_PATH - 1 ) ; hb_retc( pszReturn ) ;

Haz: проверить на ASC коды весь пут Примерно так #require "hbxpp" #include "hbxpp.ch" FUNC Main( ... ) local n := 0 local cParh := "" local lFound := .F. REQUEST HB_CODEPAGE_RU1251 hb_cdpSelect( "RU1251" ) ? cPath := hb_argV(1) ? FOR n := 1 TO LEN(cPath) IF ASC(cPath[n]) > 127 lFound := .T. ? cPath[n] EXIT END END RETURN NIL

Dima: Игорь спасибо ! А такая проверка думаешь будет не правильной ? [pre2] a:=curdir() ? a if hb_oemtoansi(a)#a ? "Есть кирилица" endif [/pre2]

Dima: Haz пишет: cShot := GETSHORTFILENAME( cLongName ) что то она пустую строку выдает [pre2] proc main() ? GETSHORTFILENAME(curdir()) // пусто ? GETSHORTFILENAME() // пусто ? GETSHORTFILENAME("bla bla bla bla bla bla bla bla bla bla ") // пусто wait RETURN NIL *cShot := GETSHORTFILENAME( cLongName ) *============================================= #pragma BEGINDUMP #include <windows.h> #include "hbapi.h" HB_FUNC( GETSHORTFILENAME ) { char pszReturn[ MAX_PATH ] ; pszReturn[0]= '\0' ; GetShortPathName( hb_parcx( 1 ), pszReturn, MAX_PATH - 1 ) ; hb_retc( pszReturn ) ; } #pragma ENDDUMP [/pre2]

Haz: Dima пишет: А такая проверка думаешь будет не правильной ? не проверял , но должна работать , возможно дольше на пару микросекунд из-за преобразования

Haz: Dima пишет: что то она пустую строку выдает у меня работает проверял так ? GetShotFilename( Exename() ) CurDir() - возвращаяет не имя файла попробуй Directory()[1][1] вот это точно ничего не покажет т.к. файла нет GETSHORTFILENAME("bla bla bla bla bla bla bla bla bla bla ")

Dima: Haz пишет: ? GetShotFilename( Exename() ) OK. Понял. Если запустить из папки в имени которой есть кирилица то вернет пустую строку

Haz: Dima пишет: Если запустить из папки в имени которой есть кирилица то вернет пустую строку GetShotFilename( Exename() ) проверил - с кирилицей тож работает нормально отсюда запустил C:\Командировки\Документация>Ais_Zpto.exe во что выдало C:\C7BA~1\F63B~1\Ais_Zpto.exe

Dima: Ага. Это я кодовую страницу не указал. Если указать RU1251 - то все нормально Если указать RU866 - то тоже пусто Получается что обе проверки можно свести к одному условию. Если GetShortFilename( Exename() ) не равно Exename() то с путем что то не то.

Dima: Остановился на такой проверке [pre2] Func TestPath(cpath) local ret:=.t. local n FOR n=1 TO LEN(cPath) IF ASC(substr(cPath,n,1)) > 127 .or. ASC(substr(cPath,n,1))==32 ret:= .f. EXIT END next return ret [/pre2]

Haz: Dima пишет: Остановился на такой проверке Этот вариант проверяет наличие расширенных ASC кодов ( русские буквы ) , а зачем там == 32 ? Если для проверки длинного имени, то оно мжет быть и без пробелов Dima пишет: ASC(substr(cPath,n,1) можно заменить на ASCPOS( cPath. n), хотя мне больше нравится вариант работы со строкой как с массивом cPath[n] а в чем вообще суть проблемы , чем тебе помешали русские буквы и длинные пути ?

Dima: Haz пишет: а в чем вообще суть проблемы , чем тебе помешали русские буквы и длинные пути ? а косяки возникают при приеме / передаче файлов на фтп из проги.

Dima: Haz пишет: со строкой как с массивом cPath[n] этот вариант у меня ошибку бьет. local a:="12345" ? a[3] //Error BASE/1068 Argument error: array access wait

Haz: Dima пишет: тот вариант у меня ошибку бьет. нужно это #require "hbxpp" #include "hbxpp.ch" и это hbxpp.lib

Dima: Haz пишет: нужно это #require "hbxpp" #include "hbxpp.ch" Упс. Заработало.

Dima: еще простой вопрос ;) Есть ли такая функция , что бы вернула подстроку из строки , находящуюся между 2 - мя подстроками ? Например есть строка MN_20.3456.ZIP Нужно что типа вот такой фунции xxx("MN_20.3456.ZIP","MN_",".ZIP") // должна вернуть 20.3456 Понятно что можно сделать с помощью Substr,At,Rat.

Haz: Dima пишет: Понятно что можно сделать с помощью Substr,At,Rat. может так ? cString := MN_20.3456.ZIP cRegExp := "MN_|\.ZIP" ? hb_RegExSplit( cRegExp , cString)[2]

Dima: Haz Спасибо мастеру по регулярным выражениям ! ;) Да так подойдет. Описания что то не нашел я на hb_RegExSplit , интересная функция.

Dima: Haz пишет: |\ Игорь извини что дергаю в выходной. Что означает эта пара символов ?

Haz: Dima пишет: Что означает эта пара символов | - это знак или \ - это модификатор который говорит что . ( точка ) не любой один символ а именно точка на счет мастера ты погорячился я сам их редко применяю и все время со шпаргалками hb_RegExSplit у Александра на сайте есть http://www.kresin.ru/hrbfaq_3.html#Doc9

Dima: OK. Спасибо

Dima: В функции работающей(добавленной) через HB_IDLEADD() можно завершить работу основной программы через QUIT он же __Quit() . Попробовал тоже самое сделать в функции запущенной в отдельном потоке. Не получилось и QUIT просто заканчивает работу данного потока. Что логично. Вопрос: возможно ли из отдельного потока завершить работу основной программы ?

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

Dima: alkresin пишет: ( через общую переменную, например ), ну а он и завершит Как тогда отслеживать эту переменную в основном потоке ? Повесить функцию через Hb_idleadd() или как то иначе ...

Sergy: Как вариант - отслеживать наличие "нужного" потока (который посылает команду на завершение приложения). Как только он "кончился" - завершать основную программу.

alkresin: Dima пишет: Повесить функцию через Hb_idleadd() В консоли - наверное, так. В GUI - таймеры есть.

Dima: alkresin пишет: В GUI - таймеры есть. Как в Минигуи например C:\MiniGUI\SOURCE\c_timer.c ? А его можно использовать в консоли ?

alkresin: А его можно использовать в консоли ? Вопрос интересный. Не знаю, как именно это сделано в Minigui и можно ли использовать тот код напрямую, но что-то свое на его основе написать можно.

alkresin: Попробовал сейчас, получилось: [pre] function main() local s := " " ANNOUNCE HB_GTSYS request HB_GT_WVT REQUEST HB_GT_WVT_DEFAULT #include "hbgtinfo.ch" hb_gtinfo( HB_GTI_FONTWIDTH, Int( hb_gtinfo( HB_GTI_DESKTOPWIDTH ) / 80 ) ) hb_gtinfo( HB_GTI_FONTSIZE, Int( ( hb_gtinfo( HB_GTI_DESKTOPHEIGHT ) - 64 ) / 25 ) ) hb_gtinfo( HB_GTI_CLOSABLE, .F. ) clear screen xxx_settimer( 1000 ) @ 1,1 GET s READ xxx_killtimer() return nil Function xxx_timerproc() static nn := 0 nn ++ @ 1,20 say str(nn) Return Nil #pragma BEGINDUMP #include <windows.h> #include "hbapi.h" HWND handle; void wrlog( const char * sFile, const char * sTraceMsg, ... ) { FILE *hFile; if( sFile == NULL ) { hFile = hb_fopen( "ac.log", "a" ); } else { hFile = hb_fopen( sFile, "a" ); } if( hFile ) { va_list ap; va_start( ap, sTraceMsg ); vfprintf( hFile, sTraceMsg, ap ); va_end( ap ); fclose( hFile ); } } static void CALLBACK s_timerProc( HWND hWnd, UINT message, UINT idTimer, DWORD dwTime ) { static PHB_DYNS s_pSymTest = NULL; HB_SYMBOL_UNUSED( message ); if( s_pSymTest == NULL ) s_pSymTest = hb_dynsymGetCase( "XXX_TIMERPROC" ); wrlog( NULL,"proc-1" ); if( hb_dynsymIsFunction( s_pSymTest ) ) { wrlog( NULL,"proc-2" ); hb_vmPushDynSym( s_pSymTest ); hb_vmPushNil(); hb_vmPushLong( ( LONG ) idTimer ); hb_vmPushLong( ( LONG ) dwTime ); hb_vmDo( 2 ); } } HB_FUNC( XXX_SETTIMER ) { handle = GetActiveWindow(); SetTimer( handle, 1001, ( UINT ) hb_parni( 1 ), s_timerProc ); } HB_FUNC( XXX_KILLTIMER ) { KillTimer( handle, 1001 ); } #pragma ENDDUMP [/pre] Но это не работает с gtwin, т.к. там нет окна. Нужен gtwvt или что-то вроде этого.

Dima: Сейчас попробую. Да работает примерчик. Спасибо. GTWIN не использую. А я пробовал так. Срабатывает , но почему то однократно. Почему ? [pre2] REQUEST HB_GT_WVT REQUEST HB_GT_WVG Proc main local hwnd cls hwnd:=GetForegroundWindow() INITTIMER(hwnd,"TEST",100,My_test()) wait KILLTIMER(hwnd,"TEST") return ****************** Func My_test() @ 3,2 say seconds() return nil ****************** #pragma BEGINDUMP #include <windows.h> #include <hbapi.h> HB_FUNC (GETFOREGROUNDWINDOW) { HWND hWnd = GetForegroundWindow(); hb_retnl ((LONG) hWnd); } HB_FUNC( INITTIMER ) { hb_retl( SetTimer( ( HWND ) hb_parnl( 1 ), ( UINT ) hb_parni( 2 ), ( UINT ) hb_parni( 3 ), ( TIMERPROC ) NULL ) ); } HB_FUNC( KILLTIMER ) { KillTimer( ( HWND ) hb_parnl( 1 ), // handle of main window ( UINT ) hb_parni( 2 ) ); // timer identifier } #pragma ENDDUMP [/pre2]

alkresin: Таймер в в вашем примере не срабатывает ни разу, т.к. в inittimer() не определена callback процедура, NULL стоит. А один раз срабатывает my_test() при вызове initimer() - ему передается значение, возвращаемое my_test()

Dima: Вот так правильно будет ? HB_FUNC( INITTIMER ) { hb_retl( SetTimer( ( HWND ) hb_parnl( 1 ), ( UINT ) hb_parni( 2 ), ( UINT ) hb_parni( 3 ), ( TIMERPROC ) hb_parni( 4 ) ) ); } В Си я конечно валенок ;)

alkresin: Dima пишет: Вот так правильно будет ? Нет, конечно. Inittimer должен быть такой, как в моем примере. А если вы хотите передать процедуру обработки прерывания от таймера, то надо это делать на Harbour уровне - как в Hwgui, да и в Minigui, наверное, так же. Вам надо привязать эту процедуру, например, к id ( 2-й параметр в вызове settimer() ) - поместить в массив, например, соответсвующие id и кодоблок процедуры - а затем из callback-функции найти этот кодоблок по id и выполнить.

Dima: Has подсказал. Сваял примерчик , работает. [pre2] Proc main REQUEST HB_GT_WVT cls Wvt_SetTimer( 2, 200) wait Wvt_KillTimer(2) return ************* Func WVT_TIMER() @ 10,0 say time() return .t. [/pre2]

Dima: alkresin Александр у меня вопрос. Функции xxx_settimer() , xxx_killtimer() , xxx_timerproc() или Wvt_SetTimer() , Wvt_KillTimer() , WVT_TIMER() это из той же оперы что и HB_IDLEADD() или это "родственники" потоков или что то еще ? Почему спрашиваю. Допустим есть функция которая была добавлена в HB_IDLEADD() и срабатывает каждые 200 мск да еще что то выводит на экран ("для крутости") , так вот в основной программе я получу тормоза. Если тоже самое сделать через поток , тормозов нет.

alkresin: Dima пишет: это из той же оперы что и HB_IDLEADD() или это "родственники" потоков или что то еще ? Что-то еще. Насколько я понимаю, считает время и организует прерывание отдельный системный процесс, а обрабатывается это прерывание во время idle state. Допустим есть функция которая была добавлена в HB_IDLEADD() и срабатывает каждые 200 мск да еще что то выводит на экран ("для крутости") , так вот в основной программе я получу тормоза. Возможно, проблема в реализации этой функции, может, ее надо реже вызывать.

Dima: alkresin пишет: Возможно, проблема в реализации этой функции Так и есть , мой косяк. Спасибо за подсказку

Dima: В программе стоит такой вызов FT_OnTick({|| TEST()},500) // срабатывание TEST каждые 30 секунд Функция TEST опрашивает некую базу и в случае обнаружения в одном из полей значения .T. вываливает на экран какое то сообщение. Пока сообщение висит прога кушает примерно 25 % ресурсов проца. Можно эту проблему победить что бы не "жрало" столько ресурсов ? Пробовал перед выводом сообщения вешать FT_OnTick() а после закрытия сообщения FT_OnTick({|| TEST()},500) , не помогло. PS FT_OnTick это из HBNF и реализован c помощью Hb_idleadd , Hb_idleDel PS1 В Clipper такой же аналог не приводил к загрузке проца.

SergKis: Dima если использовать не idle, а on timer и сообщение вешать в потоке ?

Dima: SergKis С потоком нельзя. Работаю с ADS. Лет 5 назад проводил тесты , падает прога в разных потоках при работе с ADS , при чем непредсказуемо. В принципе есть исходник OnTick.c из Nanfor for Clipper https://searchcode.com/codesearch/view/4467408/ Может его можно как то под Harbour переписать ?

SergKis: Dima пишет:С потоком нельзя тогда используй отдельный запуск - монитор опроса (можно использовать приоритет задания) и сообщением в tray

Dima: SergKis Кажется понял почему такая загрузка. Дело в INKEY. Попробовал твою функцию INKEYGUI и кажется загрузки нет. Счас потестю.

SergKis: Dima пишет: Дело в INKEY ну да, inkey "морозит" обработку сообщений, InkeyGui - обрабатывае очередь и выделяет нажатия клавишь, но в wvt использовать, даже не подумал

Dima: SergKis В общем да нормально , не тормозит ни чего но вылезла новая проблема. В функции TEST что выше писал которая сидит в IDLE вызывается MEMOEDIT на просмотр (без редактирования) [pre2] memoedit(prime,11,21,18,59,.f.,"k2mmem_ff_prm",38) ......... ......... Функция обработки педалей Если в ней юзать INKEY , текст сообщения я вижу сразу , но грузит проц. Если вместо нее юзать INKEYGUI(100) , проц не грузит но не вижу сообщения , пока какую то кнопку не нажму. func k2mmem_ff_prm() local nxkey:=0 local local_time:=seconds() do while (nxkey:=INKEY(0.01))==0 if seconds()-local_time>10 TestKillUser() local_time:=seconds() endif enddo if nxkey==27 ft_putkey(nxkey) endif return 0 [/pre2] До кучи. Вставил в свой бровс вместо nkey:=inkey(0.01) -> nkey:=inkeygui(100) и функция пользователя больше не реагирует на функциональные клавиши. Enter обрабатывается.

SergKis: Dima сравни коды nkey после инкеев в gui VK_..., если правильно помню ...

SergKis: PS ? 'test' inkeygui(3000) видно или как ?

Dima: Да ESC , ENTER , Пробел совпадают , функциональные нет , насчет буквенно цифровых не проверял.

Dima: SergKis пишет: ? 'test' inkeygui(3000) видно или как ? Видно

Dima: Кажется понял чего надо. Нужен переходник из кодов INKEYGUI в обычные не расширенные коды INKEY. При чем с учетом раскладки клавы. Вопрос как это без напряга сделать !

SergKis: Dima пишетНужен переходник из кодов INKEYGUI где то видел, но непомню и заменяя inkey, inkeygui - аналог inkey clipper 5.2e и еще мышь не отрабатывает

Dima: Странно что в самом Harbour нет аналога типа INKEYIDLE , потому как если опрашивать клаву в IDLE фоновой задачи ( НЕ в потоке ), c помощью INKEY то грузит проц. Если в основном потоке идет опрос с помощью INKEY , проц не грузит.

PSP: Использовать в цикле hb_ReleaseCPU() не подойдет?

Dima: PSP пишет: Использовать в цикле hb_ReleaseCPU() не подойдет? Нет , уже тестил. Похоже для конвертации нужно что то типа https://msdn.microsoft.com/en-us/library/system.windows.input.keyinterop.keyfromvirtualkey%28v=vs.110%29.aspx Но в сях я валенок

SergKis: Dima мой товарищь посоветовал делать так: nKey := InkeyGui( ... ) nKey подать в hb_gt_wvt_Info(...) gtwwt.c добавить свою константу в case static BOOL hb_gt_wvt_Info( PHB_GT pGT, int iType, PHB_GT_INFO pInfo ) например case HB_GTI_VK_TO_INKEY используя hb_gt_wvt_KeyEvent(...) в которой hb_gt_wvt_TranslateKey(...) произвести перекодировку но надо пересобрать gtwwt.obj

Dima: SergKis Спасибо ! Думал есть способ проще , без переделки сырцов. Попробую.

SergKis: Dima пишет:Думал есть способ проще , без переделки сырцов вытащить из gtwvt.c эти функции (они static), сделать не static, переименовать ... повторить все - вряд ли это проще

Dima: В сишный код я точно не полезу , так как должен понимать что делаю.

Dima: SergKis А можете немного допилить INKEYGUI что бы она вернула ASCII код с учетом раскладки ? Вероятно нужна эта функция https://msdn.microsoft.com/en-us/library/windows/desktop/ms646318%28v=vs.85%29.aspx

Dima: Почти победил преобразование VK кодов , но с кирилицей фигня полная. Что не так сделал ? Собирал так c:\hb32\bin\hbmk2 t -gtwvt -gui [pre2] #include "hbgtinfo.ch" proc main local a REQUEST HB_GT_WVT_DEFAULT REQUEST HB_LANG_RU866 HB_LANGSELECT("RU866") REQUEST HB_CODEPAGE_RU866 hb_cdpSelect( "RU866" ) hb_gtInfo(HB_GTI_FONTNAME, 'Lucida Console') ? "TEST" do while (a:=inkeygui(0))#27 ? a ? chr(toasciiex(a)) enddo return ************************* #pragma BEGINDUMP #include <windows.h> #include "hbapi.h" #include "hbapiitm.h" HB_FUNC( TOASCIIEX ) { HKL hkl = GetKeyboardLayout( 0 ); BYTE KeyState[256]; WORD lpChar; GetKeyboardState( KeyState ); ToAsciiEx( hb_parnl(1), 0, KeyState, &lpChar, 0, hkl ); hb_retnl( LOBYTE( lpChar )); } #pragma ENDDUMP #pragma BEGINDUMP #include <windows.h> #include <hbapi.h> HB_FUNC( INKEYGUI ) { MSG Msg; BOOL lNoLoop=FALSE; UINT dwTimer, nRet=0, uTimeout=10; if( HB_ISNUM(1) ) uTimeout = hb_parni(1); if( uTimeout==0 ) uTimeout = 0x0FFFFFFF; dwTimer = SetTimer( NULL, 0, uTimeout, NULL); while( GetMessage(&Msg, NULL, 0, 0) ) { switch( Msg.message ) { case WM_KEYDOWN : case WM_SYSKEYDOWN : { nRet = Msg.wParam; lNoLoop = TRUE; break; } case WM_TIMER : { lNoLoop = Msg.wParam == dwTimer; break; } } if( lNoLoop ) { KillTimer( NULL, dwTimer ); hb_retni( nRet ); return ; } else { TranslateMessage( &Msg ); // Translates virtual key codes DispatchMessage( &Msg ); // Dispatches message to window } } } #pragma ENDDUMP [/pre2]

Dima: Упс , понял , надо так ? hb_ansitooem(chr(toasciiex(a)))

SergKis: Dima пишет:Упс , понял , надо так ? и что ? получилось ?

Dima: SergKis пишет: и что ? получилось ? Практически да , допиливаю пока.

Dima: SergKis А вот такой фокус похоже не работает. Keyboard chr(112) ? inkeygui() // ни какой реакции на посыл кода через Keyboard

SergKis: Dima в wvt соорудили перекодировку (см.функции выше ..event..1) VK клавиш ни какой реакции на посыл кода через Keyboard возможно надо использовать сообщение WM_COPYDATA, типа Keyboard посылает а в inkeygui вставить обработку

Dima: PSP пишет: Использовать в цикле hb_ReleaseCPU() не подойдет? Таки да Если в основном потоке клаву опрашивать так , nkey:=Inkey(0.01) , проц не грузит. Если так же ее опрашивать в IDLE функции живущей в HB_IdleAdd() , то да грузит проц. Долго игрался и доигрался В IDLE опрашивать надо так [pre2] nKey:=Inkey() hb_releasecpu() * ни чего грузит и все пучком. [/pre2]

PSP: Ну да, именно так )))

Dima: PSP пишет: Ну да, именно так ))) Нет что б сразу сказать подробнее ))) 2 дня убил да еще мучал InkeyGui (с ним тоже вариант , но функция специфическая)

PSP: Я ж не знал ) А ты написал, что уже пробовал... ))

Dima: Можно ли в вызываемой функции узнать , она была вызвана из основного потока или дочернего ? ЗЫ MT приложение. Проехали , нашел. hb_threadSelf()

alkresin: pThID := hb_threadSelf() Возвращает указатель потока, из которого вызывается эта функция.

Dima: Почему есть функции HB_LEFTEQ() и HB_LEFTEQI() (удобнее чем LEFT()) а подобных аналогов c RIGHT нет ?

Петр: В ChangeLog логика HB_LEFT* ясно описана + added new function to replace "=" operator without the SET EXACT ambiguity in its most common pattern of usage: hb_LeftEq( <cString1>, <cString2> ) -> <lResult> it's equivalent to this expression, but faster and shorter: ( Left( <cString1>, Len( <cString2> ) ) == <cString2> ) 2014-01-22 03:09 UTC+0100 Viktor Szakáts + added hb_LeftEqI(). Same as hb_LeftEq() but case-insensitive. hb_LeftEqI( <cString1>, <cString2> ) -> <lResult> 2014-02-04 13:38 UTC+0100 Viktor Szakáts Ну а RIGHT, наверное, так часто не пользуются

Dima: Петр пишет: Ну а RIGHT, наверное, так часто не пользуются Да наверное так и есть. PRG аналоги могли бы быть примерно такими [pre2] Func Hb_rightEQI(Cstr1 , Cstr2) return Iif (Hb_isstring(Cstr1) .and. Hb_isstring(Cstr1) ; .and. Right(upper(Cstr1),len(Cstr2))==Upper(Cstr2),.T.,.F.) [/pre2] Примерно так же Hb_rightEQ , но без Upper или можно было сделать единую функцию Hb_right() с 3-м параметром.

Dima: Посетила меня идея , организовать в своей сетевой задаче просмотр экрана другого юзера , для начала только скрин , в перспективе "видео" (показ тех же скринов с задержкой). Реализация думаю не очень сложная и решу. Есть пара вопросов ( Терминал GTWVT (WVG) ) 1. Как средствами Harbour снять скрин окна с нужным заголовком и сохранить в файл формата JPG скажем. 2. -\\-\\-\\\-\\- cнять скрин всего рабочего стола со всеми окнами и -\\-\\-\\\-\\-

Andrey: Dima пишет: экрана другого юзера , для начала только скрин Давай уж сразу на МиниГуи ! Тем более там уже реализовано снятие всего экрана ! Не помню какой пример, но точно сам видел !

petr707: есть такой пример..\MiniGUI\SAMPLES\Applications\ScreenshotMaker портируется и в harbour, из примера нужно взять JPG.DLL = = = DYNAMIC SaveToJpgEx ... Function SnapJpg(cSaveFile,cfile_dll) Local nW := HB_GTINFO( HB_GTI_DESKTOPWIDTH ) Local nH := HB_GTINFO( HB_GTI_DESKTOPHEIGHT ) Local nHandle := GETDESKTOPWINDOW() Local ret := .f. cfile_dll := IIF(cfile_dll=NIL,"jpg.dll",cfile_dll) if file(cfile_dll) cSaveFile := IIF( cSaveFile=NIL, "test.jpg" ,cSaveFile) Calldll32( "SaveToJpgEx",cfile_dll, nHandle, cSaveFile, nW, nH ) ret:=file(cSaveFile) else tolog("SnapJpG: Нет файла DLL {"+cfile_dll+"} ") ret:=.f. endif Return ret

Dima: petr707 Спасибо за идею , работает. [pre2] #include "hbgtinfo.ch" #include "hbdyn.ch" Proc main REQUEST HB_GT_WVT REQUEST HB_GT_WVG_DEFAULT ? " " ? snapJpg(CurDrive()+":\"+CurDir()+"\test.jpg",0) wait return ********************* Func SnapJpg(cfile,nmode) Local nW Local nH Local nHandle hb_default(@nmode,0) hb_default(@cfile,"test.jpg") if nmode==0 nHandle := wapi_GETDESKTOPWINDOW() nW := HB_GTINFO( HB_GTI_DESKTOPWIDTH ) nH := HB_GTINFO( HB_GTI_DESKTOPHEIGHT ) else nHandle := GETFOREGROUNDWINDOW() nw := HB_GTINFO( HB_GTI_SCREENWIDTH ) nh := HB_GTINFO( HB_GTI_SCREENHEIGHT ) endif hb_DynCall( { "SaveToJpgEx", "jpg.dll",HB_DYN_CALLCONV_STDCALL },nHandle,cfile,nw,nh ) return HB_fileexists(cfile) ***************** #pragma BEGINDUMP #include <windows.h> #include <hbapi.h> HB_FUNC (GETFOREGROUNDWINDOW) { HWND hWnd = GetForegroundWindow(); hb_retnl ((LONG) hWnd); } #pragma ENDDUMP [/pre2]

Dima: Dima пишет: petr707 Спасибо за идею , работает. Я так понял что снять скриншот окна по хендлу не получится если окно свернуто , или можно ? PS Можно конечно проверить если свернуто то развернуть , снять скрин и снова свернуть...

petr707: Просто поднять окно..чтоб юзер помнил , что у него есть задача .. и не спал и не отвлекался на непрофильное..

Dima: petr707 Вариант , спасибо !

rvu: А есть функция переименовать папку (с файлами внутри)?

Dima: rvu Самопал придется писать...



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