Форум » GUI » Новая версия Расширенного релиза библиотеки MiniGUI (часть III) » Ответить

Новая версия Расширенного релиза библиотеки MiniGUI (часть III)

gfilatov: Начало темы находится здесь, а теперь АНОНС * АНОНС * АНОНС * АНОНС * АНОНС Готовится к опубликованию новая сборка №48, которая выйдет в конце недели. Если у Вас есть интересные наработки для включения в новый релиз, то сейчас самое удобное время для их отправки мне Кратко, что нового: - исправление обнаруженных ошибок и неточностей кода; - новый класс HEADERIMAGE для Grid и Browse; - свойство Address в Hyperlink может теперь открывать папку или файл на диске; - добавлен NOTABSTOP класс для Browse; - поддержка пользовательских компонентов (заимствована из оффициального релиза); - расширения и исправления в библиотеках TsBrowse и PropGrid; - обновлены сборки Харбор и HMGS-IDE; - новые и обновленные старые примеры (как обычно ).

Ответов - 203, стр: 1 2 3 4 5 6 7 8 9 10 11 All

Петр: А я ошибку нашел в MPMC, логическую WinFolder := WinFolder + If ( Right ( WinFolder , 1 ) != '\' , '\' , '' ) EnvironmentFile := MemoRead ( WinFolder + 'mpm.ini' ) If Empty ( EnvironmentFile ) SaveEnvironment ( WinFolder ) EndIf ---------> забыли наново загрузить файл For i := 1 To MLCount ( EnvironmentFile )

gfilatov: Петр пишет: я ошибку нашел в MPMC Спасибо! По-видимому, д.б. так ... WinFolder += If ( Right ( WinFolder , 1 ) != '\' , '\' , '' ) EnvironmentFile := MemoRead ( WinFolder + 'mpm.ini' ) If Empty ( EnvironmentFile ) SaveEnvironment ( WinFolder ) EnvironmentFile := MemoRead ( WinFolder + 'mpm.ini' ) EndIf For i := 1 To MLCount ( EnvironmentFile ) ...

Петр: gfilatov пишет: Спасибо! По-видимому, д.б. так Угу. И еще надо было ж додуматься проводить, чуть ли не в каждой строке проверки на вхождение "\" ! Вместо того. чтобы сделать это раз и в одном месте. А вообще для себя я решил переписать эту утилиту - вещь довольно полезная, когда самому не хочется писать make файлы. Вот части кода FUNCTION SaveWorkSpace( cFile ) LOCAL hIni := {=>}, lResult := FALSE // hIni[ "MAIN" ] := {=>} hIni[ "MAIN" ][ "BCCFOLDER" ] := "F:\BORLAND\BCC55" hIni[ "MAIN" ][ "MINIGUIFOLDER" ] := "C:\MINIGUI" hIni[ "MAIN" ][ "HARBOURFOLDER" ] := "C:\MINIGUI\HARBOUR" hIni[ "MAIN" ][ "PROGRAMEDITOR" ] := "NOTEPAD.EXE" hIni[ "DEBUG" ] := {=>} hIni[ "DEBUG" ][ "DEBUGACTIVE" ] := iif( lDebugActive, "YES", "NO" ) hIni[ "COMPILERS" ] := {=>} hIni[ "COMPILERS" ][ "CC_SUPORTED" ] := "bcc|dmc|msvc|owatcom|pocc" hIni[ "COMPILERS" ][ "HB_SUPORTED" ] := "harbour|xharbour" hIni[ "BCC" ] := {=>} hIni[ "DMC" ] := {=>} hIni[ "MSVC" ] := {=>} hIni[ "OWATCOM" ] := {=>} hIni[ "POCC" ] := {=>} ... IF hb_IniWrite( cFile, hIni, "#Generated file; don't touch", "#end of " + cFile ) lResult := TRUE ENDIF // RETURN lResult FUNCTION CheckParam( aParams ) LOCAL nLen := Len( aParams ), nIndex, nBadIndex LOCAL cValidParam := "-? -C -D -H -L /? /C /D /H /L" LOCAL cRealParam := "", cTemp LOCAL lResult := FALSE PUBLIC lDebugActive := FALSE, lCleanActive := FALSE, lShowHelp := FALSE PUBLIC lShowLogo := TRUE // IF nLen == 0 .OR. nLen > MAX_PARAM ShowUsage() ELSEIF nLen == 1 lResult := TRUE SWITCH Upper( aParams[1] ) CASE "-?" CASE "/?" CASE "-H" CASE "/H" lShowHelp := TRUE EXIT ENDSWITCH ELSE FOR nIndex := 2 TO nLen cTemp := UPPER( aParams[nIndex] ) lResult := ( cTemp $ cValidParam ) IF lResult cRealParam += cTemp ELSE nBadIndex := nIndex EXIT ENDIF NEXT IF (lResult) IF "-D" $ cRealParam lDebugActive := TRUE ELSEIF "/D" $ cRealParam lDebugActive := TRUE ENDIF ..


Петр: Т.е. поддержка нескольких компиляторов, в идеале всех для которых реализована поддержка Harbour + MiniGUI. Отказ от жестко зашитых алгоритмов, все данные должны находиться в ini файле - хочу использовать семейство hb_Ini* функций. Еще какие фичи - - возможность использования не только глобального mpm.ini, но и локальных конфигурационных файлов - возможность указания в командной строке параметров в произвольном порядке, например mpmc -c myprog1.mpm -ulocalini.mpm myprog2.mpm /D /tbcc - обязательная проверка файла проекта на целосность (имеется ввиду все ли файлы, папки существуют.), странно, что этого не сделали раньше; - работа сразу с несколькими проектами; - возможность включения в проект не только .prg но и .c файлов. - может еще что-то полезного вспомню - придумаю + к этому конвертер для переноса файлов из старого формата проекта в новый.

gfilatov: Петр пишет: чуть ли не в каждой строке проверки на вхождение "\" ! Вместо того. чтобы сделать это раз и в одном месте. Так было сделано автором утилиты еще в 2003 году Петр пишет: я решил переписать эту утилиту Если у Вас будет желание, пришлите мне финальный вариант для включения в расширенный релиз библиотеки. Сам я практически не использую консольный вариант, поскольку есть графический MPM, переписанный практически с нуля Кевином Кармоди

Andrey_IV: Скачал версию : Harbour MiniGUI 1.5 Extended Edition (Build 56) - 2008.09.09 При установке антивирус Avast! версия 4.8 Home Edition VPS 080925-0, 25.09.2008 выдает сообщение о трояне C:\MiniGUI\SAMPLES\Applications\FREE_MEMORY\Memory.exe Троян: Win32:Oliga [Trj] Так вопрос: это глюк антивируса или на самом деле там троян сидит ? у кого-нибудь что-то похожее было ? EXE-шник я , конечно, удалил и перекомпилировал пример заново но все-таки любопытно

gfilatov: Andrey_IV пишет: выдает сообщение о трояне C:\MiniGUI\SAMPLES\Applications\FREE_MEMORY\Memory.exe Нет там никакого трояна! Проверено DrWeb и антивирусом Касперского, которым я доверяю

gustow: к вопросу о "пользующихся" компилятором/библиотекой (извиняюсь, не мог отозваться раньше): Сам пользуюсь все более активно (в конторе достаточно старых задачек, которые намного проще "чуть подлудить", переводя с Клиппера на Харбор, а в некоторых случаях, оставив "математику", прилепить ГУИ - чем делать с ноля на чем-то "вижуалистом") - и наши "тетки" все более завистливо поглядывают в мою сторону :) Также нашим сидящим в области в больницах программерам "показал пальцем" на это дело (а у многих тоже достаточно самописных "приблуд", связанных с возней с ДБФками и писаных на Фокспре-Клиппере, которые тоже неохота "с ноля" перерисовывать) - и человек 8-10 (как минимум) сказали "Опа! Интересно, интересно... тээкс... пошел разбираться - это практически то, что мне и надо" :) В школе у дочки (как-то писал про их "информатичку") эта "информатичка" тоже звонила про то, что "разбирается" и "вот если б еще русскую доку..." - а так тоже была сильно порадована количеству и разноообразию примеров, да и простоте (если не сказать - изяществу) решения многих вопросов (особо впечатлил "практически Total Commander с величиной исходника в 60 кбайт!.." - FileMan Григория). Так что "совращение" идет :)

Sergey Spirin: Здравствуйте, Григорий, Такой вопрос, создается окно в IDE: Function Main Load Window Test Center Window Test Activate Window Test Return Function MyTest() MsgBox(Str(Test:Width)) Return 1 На вызов MyTest() выдает: Variable does not exist: TEST Собственно, а как обращаться то к окну? И второе, как получить его Handle? Спасибо. Спирин Сергей.

gfilatov: Sergey Spirin пишет: а как обращаться то к окну? Sergey Spirin В библиотеке MiniGUI принята VB-подобная нотация (для разделения объектов используется точка): Test.Width Sergey Spirin пишет: как получить его Handle? Надо воспользоваться такой функцией: GetFormHandle ('Test')

gfilatov: Новый релиз библиотеки выложил по адресу: http://minigui.mylivepage.ru/file/?fileid=6019 а также, как обычно, на сервере http://hmgextended.com по адресу: http://hmgextended.com/files/CONTRIB/hmg-1.5-57-setup.zip Что нового: - исправление обнаруженных ошибок и неточностей кода; - новый класс PALETTE в команде DEFINE WINDOW; - поправлен Си-код для успешной сборки библиотеки под бесплатными компиляторами BCC 5.82 и Pelles C 4.50 - синхронизация с изменениями в официальной версии HMG выпусков 2.6.5-2.6.6; - исправления в библиотеке PropertySheet; - обновлены сборки Харбора (до версии 1.0.1 final) и HMGS-IDE; - новые и обновленные старые примеры (как обычно ). Большое спасибо всем откликнувшимся на мой призыв! Желаю удачи в программировании!

Sergey Spirin: gfilatov пишет: Надо воспользоваться такой функцией: GetFormHandle ('Test') Ok. Спасибо. Следующий вопрос, похоже окна в MiniGUI в разных ситуациях перехватывают нажатия Enter и Escape, и потом уже решают, что с ними делать, можно ли регулировать эту ситуацию? Объясню, что я делаю. Я сел, наконец, за давнишний свой "должок" в Фасте - множественный предпросмотр. В том числе, рассматриваю возможность встраиваемого предпросмотра в юзерское окно. С консольным приложением это проблематично из-за специфики консоли, решил делать только для GUI. Для тестов и дальнейшей демки выбор пал, конечно, на MiniGUI Встраивая предпросмотр, подумал, почему бы не встроить, например, Grid, да и другое, уже не в контексте Фата. Просто, можно сделать хорошие компоненты для MiniGIU . Сделал набросок для грида: http://www.paritetsoft.ru/downloads/TMP_PICT/GRID.zip Это тест, в начале нажать - File-Open. Лучше смотреть на Win2000 и выше. Проблема пока только с "непонятным" поведением Enter-Escape. Такая вот идея, в принципе можно ее реализовать.

Sergey Spirin: Sergey Spirin пишет: Проблема пока только с "непонятным" поведением Enter-Escape Проверил с просто окнами. При немодальном окне та же проблема. Enter-Escape окно не получает, вся остальная клавиатура и мышка без проблем. Проблемы нет только в модальном режиме, но это и понятно, в модальности вся диспетчеризация производится только дельфийским кодом... Григорий, есть ли какие-то мысли по этому поводу?

Sergey Spirin: Сделал то же самое под Xailer. Enter-Escape работают.... Очевидно, что где-то в коде MiniGUI мессаги глушатся.

Sergey Spirin: Sergey Spirin пишет: Очевидно, что где-то в коде MiniGUI мессаги глушатся. Пришлось немного поизучать исходники MiniGUI. Собственно, мест, связанных с диспетчеризацией сообщений, как и следовало ожидать, немного. Но именно в них и кроется причина столь несовместимого со стандартом WinAPI поведения. Модуль c_windows.c: [pre2] if( !IsWindow(GetActiveWindow()) || !IsDialogMessage(GetActiveWindow(), &Msg) ) { TranslateMessage( &Msg ); DispatchMessage( &Msg ); } [/pre2] ??? Это относится, естественно, к условию под if: if( !IsWindow(GetActiveWindow()) || !IsDialogMessage(GetActiveWindow(), &Msg) ) Во-первых, левая часть - это, практически, гарантированный False. Как может быть handle "просроченным", если он получен здесь и сейчас? В этом можно убедиться, если отбросить правую часть. Любой пример придется снимать диспетчером задач. Фактически, все идет через правую часть, где и содержится "засада". В большинстве случаев IsDialogMessage просто вернет False и мы уходим на диспетчеризацию. Вообще говоря IsDialogMessage используется ТОЛЬКО для WinAPI-диалогов FileOpen, FileClose и т.п. Но в MSDN упомянуто, что может работать и с обычными окнами, в этом и засада. Дочерние окна эта функция начинает воспринимать как "свой" диалог, а для диалога Enter-Escape это и есть DialogMessages Производится "особенная" обработка с посылкой DM_GETDEFID and DM_SETDEFID messages и т.д. Резюм. Все это условие (if( !IsWindow(GetActiveWindow()) || !IsDialogMessage(GetActiveWindow(), &Msg) ) ) необходимо выкидывать. Левое безболезненно. Правое, практически, тоже, но: IsDialogMessage надо бы использовать, но ТОЛЬКО в случае, если активное окно РЕАЛЬНО является WinApi-диалогом. Так, например, делается в Delphi (эти диалоги "пасутся" объектом Application). Григорий, жду от вас какой-то реакции, да и вообще, хотелось бы об этом поговорить с Вами поподробнее.

gfilatov: Sergey Spirin пишет: Все это условие (if( !IsWindow(GetActiveWindow()) || !IsDialogMessage(GetActiveWindow(), &Msg) ) ) необходимо выкидывать. Т.е. записать так: HB_FUNC( _DOMESSAGELOOP ) { MSG Msg; while( GetMessage(&Msg, NULL, 0, 0) ) { TranslateMessage( &Msg ); DispatchMessage( &Msg ); } return; } Sergey Spirin пишет: IsDialogMessage надо бы использовать, но ТОЛЬКО в случае, если активное окно РЕАЛЬНО является WinApi-диалогом Как именно это можно сделать - т.е. определить, что активное окно РЕАЛЬНО является WinApi-диалогом? Каково Ваше предложение применительно к MiniGUI? Sergey Spirin пишет: хотелось бы об этом поговорить с Вами поподробнее Мой почтовый адрес Вам известен

gfilatov: Новый релиз библиотеки выложил по адресу: http://minigui.mylivepage.ru/file/?fileid=6025 а также, как обычно, на сервере http://hmgextended.com по адресу: http://hmgextended.com/files/CONTRIB/hmg-1.5-57a-setup.zip Что нового: - исправление ошибок, связанных с изменениями в псевдо-ООП коде, которые были внесены в 57-й сборке. Жду Ваших замечаний

Sergey Spirin: gfilatov пишет: Т.е. записать так: цитата: HB_FUNC( _DOMESSAGELOOP ) { MSG Msg; while( GetMessage(&Msg, NULL, 0, 0) ) { TranslateMessage( &Msg ); DispatchMessage( &Msg ); } return; } Да. Думаю, что с вероятностью 99,9999% это ничем не грозит. Оставшаяся доля - это оставшееся на диалоги. WinApi - диалоги - это диалоги созданные функциями типа CreateDialog(), CreateDialogIndirect() и т.п. По большому счету эти функции остались для совместимоcти еще со времен Win 2.00-3.11. Сегодня мало кто будет разрабатывать форму в редакторе ресурсов, а именно этого эти фунуции требуют. Традиционно FileOpen, FileSave - диалоги такого типа, но они модальные, то есть проблемы здесь нет. Единственная проблемка - это создание пользовательского немодального диалога с юзерскими кнопками. MiniGUI позволяет создавать эти диалоги (c_dialog.c и h_dialog.prg). На prg уровне функция _DefineDialog(). Однако, естественно, нигде более это не используется вообще. Ни в исходниках, ни в примерах. Определить "в лоб" что это диалог такого типа увы нельзя. Дельфи, например для этого использует такой прием: [pre2] function TApplication.IsDlgMsg(var Msg: TMsg): Boolean; begin Result := False; if FDialogHandle <> 0 then Result := IsDialogMessage(FDialogHandle, Msg); end; [/pre2] Установка же значения FDialogHandle производится в хуке этого диалога: [pre2]function FindReplaceWndProc(Wnd: HWND; Msg, WParam, LParam: Longint): Longint; stdcall; function CallDefWndProc: Longint; begin Result := CallWindowProc(Pointer(GetProp(Wnd, MakeIntAtom(WndProcPtrAtom))), Wnd, Msg, WParam, LParam); end; begin case Msg of WM_DESTROY: if Application.DialogHandle = Wnd then Application.DialogHandle := 0; WM_NCACTIVATE: if WParam <> 0 then begin if Application.DialogHandle = 0 then Application.DialogHandle := Wnd; end else begin if Application.DialogHandle = Wnd then Application.DialogHandle := 0; end; WM_NCDESTROY: begin Result := CallDefWndProc; RemoveProp(Wnd, MakeIntAtom(WndProcPtrAtom)); Exit; end; end; Result := CallDefWndProc; end;[/pre2] Я вот думаю, стоит ли "заморачиваться" и делать что-то аналогичноe, или просто "забить", так как по-большому счету не нужно.... Аналог хука у вас - это DialogProc() вызываемый из HMG_DlgProc() gfilatov пишет: Мой почтовый адрес Вам известен Ok. Про "компонентyю" идею напишу мылом.

Петр: gfilatov пишет: Сам я практически не использую консольный вариант, поскольку есть графический MPM, переписанный практически с нуля Кевином Кармоди mpmbuild C-версия [pre2]#include <windows.h> #if !defined( INVALID_FILE_ATTRIBUTES ) #define INVALID_FILE_ATTRIBUTES ( ( DWORD ) -1 ) #endif #if !defined( FILE_ATTRIBUTE_DEVICE ) #define FILE_ATTRIBUTE_DEVICE 0x00000040 #endif char * _getenv( const char * ); char * xstrcpy( char *, const char *, ... ); BOOL fsFileExists( const char * ); BOOL strEmpty( const char *, DWORD ); int WaitRun( char *, WORD ); #define MPMB_NOLOCFILE -101 #define MPMB_NOLOCREAD -102 #define MPMB_NOBUILDFILE -103 int PASCAL WinMain( HINSTANCE inst, HINSTANCE previnst, LPSTR cmdline, int cmdshow ) { DWORD dwResult; char * szTmpFolder = _getenv( (const char*) "TEMP" ); char * szLocFile; HANDLE handle; DWORD dwSize, dwNumberOfBytesRead; char cBuildFile[MAX_PATH] = {0}; szLocFile = xstrcpy( NULL, szTmpFolder, (const char*) "\\", (const char*) "_MpmBuild.txt", NULL ); if( !fsFileExists( szLocFile ) ) { dwResult = MPMB_NOLOCFILE; goto end; } handle = CreateFile( szLocFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, (DWORD) NULL, NULL ); if ( handle == 0 ) { dwResult = MPMB_NOLOCREAD; goto end; } dwSize = GetFileSize( handle, NULL ); if ( dwSize == 0xFFFFFFFF ) { dwResult = MPMB_NOLOCREAD; CloseHandle( handle ); goto end; } ReadFile( handle, cBuildFile, ( dwSize <= MAX_PATH ) ? dwSize : MAX_PATH, &dwNumberOfBytesRead, NULL ); CloseHandle( handle ); if ( strEmpty( cBuildFile, dwNumberOfBytesRead ) ) { dwResult = MPMB_NOLOCREAD; goto end; } if( !fsFileExists( cBuildFile ) ) { dwResult = MPMB_NOBUILDFILE; goto end; } DeleteFile( szLocFile ); dwResult = WaitRun( cBuildFile, 0 ); end: if ( szTmpFolder ) free( (void *) szTmpFolder ); if ( szLocFile ) free( (void *) szLocFile ); return dwResult; } /* */ char * _getenv( const char * pszName ) { DWORD size = GetEnvironmentVariableA( pszName, NULL, 0 ); char * pszBuffer = NULL; if( size != 0 ) { pszBuffer = (char *) malloc( size ); GetEnvironmentVariableA( pszName, pszBuffer, size ); } return pszBuffer; } /* */ BOOL fsFileExists( const char * szFileName ) { DWORD dwAttr; BOOL bExist; dwAttr = GetFileAttributesA( szFileName ); bExist = ( dwAttr != INVALID_FILE_ATTRIBUTES ) && ( dwAttr & ( FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE ) ) == 0; return bExist; } /* */ BOOL strEmpty( const char * szText, ULONG ulLen ) { while( ulLen-- ) { char c = szText[ ulLen ]; if( !isspace(c) ) return FALSE; } return TRUE; } /* */ char * xstrcpy( char * szDest, const char * szSrc, ... ) { char * szResult; va_list va; if( szDest == NULL ) { const char * szSrcPtr = szSrc; ULONG ulSize = 1; va_start( va, szSrc ); while( szSrcPtr ) { ulSize += strlen( szSrcPtr ); szSrcPtr = va_arg( va, char * ); } va_end( va ); szDest = ( char * ) malloc ( ulSize ); } szResult = szDest; va_start( va, szSrc ); while( szSrc ) { while( *szSrc ) *szDest++ = *szSrc++; szSrc = va_arg( va, char * ); } *szDest = '\0'; va_end( va ); return szResult; } /* */ int WaitRun( char * cFile, WORD wShow ) { DWORD dwExitCode; STARTUPINFO stInfo = {0}; PROCESS_INFORMATION prInfo; BOOL bResult; stInfo.cb = sizeof( stInfo ); stInfo.dwFlags = STARTF_USESHOWWINDOW; stInfo.wShowWindow = wShow; bResult = CreateProcess( NULL, cFile, NULL, NULL, TRUE, CREATE_NEW_CONSOLE | NORMAL_PRIORITY_CLASS, NULL, NULL, &stInfo, &prInfo ); if( !bResult ) return (DWORD) -1L; WaitForSingleObject( prInfo.hProcess, INFINITE ); GetExitCodeProcess( prInfo.hProcess, &dwExitCode ); CloseHandle( prInfo.hThread ); CloseHandle( prInfo.hProcess ); return dwExitCode; } [/pre2]

Петр: Компилируем bcc32 -5 -6 -G -tW -tWR -q -w-8057 mpmbuild.c -laa -lGn -lTpe -q -lx Размер бинарника [pre2] при использовании bcc32 (5.5.1) 8192 bytes при использовании msvc (13.10.3077) 5120 bytes оригинальная версия bcc32 (5.5.1) 993 Kb [/pre2]



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