Перейти к содержанию
Fire Monkey от А до Я

dnekrasov

Пользователи
  • Постов

    317
  • Зарегистрирован

  • Посещение

  • Победитель дней

    52

Активность репутации

  1. Like
    dnekrasov отреагировална Всеволод Леонов в Перспективы RAD   
    Коллеги, всем привет!
    Сначала хочу всех немного успокоить. Часто бывает, что в команде (а то и в сборной) по футболу меняют тренера, ведущих игроков, стратегию игры и т.д. Для футбола это - нормально. Нормально ли это для разработки софта?
    Отвечу комплексно. Сначала скажу, что я - MVP Embarcadero, но работаю я в www.workspad.ru - компании, организованной Сергеем Орликом. Во многом моя работа в Embarcadero до Samsung-а повлияло на то, что Сергей меня взял себе сотрудником - сейчас я занимаюсь развитием международного бизнеса www.workspad.com. Delphi остаётся моим любимым инструментом, недавно я начал писать что-то на блоге, просто жизнь позволила заниматься этим активно.
    Также мы начали проект TurboCocoa, где мне доверили роль frontman-а. Это такая тулза поверх Delphi, чтобы можно было писать 100% нативные по UI/UX приложения (Mac OS, iOS, Android). Но это - отдельный разговор.
    Конкретно про IT-бизнес, разработку ПО, зрелость продукта и кадровую политику Embarcadero. Я могу себе позволить её комментировать, т.к. я НЕ сотрудник Embarcadero (that's really impossible from inside).
    Разработка современного ПО - не вся, а определённого класса - стала настолько зрелой, что может быть правильным образом формализована с точки зрения требований и разбита на изолированный класс задач. Первый небольшой софт писался человеком, который "всё-в-одном", мы знаем, что первые версии Pascal писались одним человеком. Теперь это - большой коллектив. Как только Delphi как продукт стала большой и (!) зрелой, то стало возможным оптимизировать вовлечение специалистов. Это нормально для строительства - каждый новый дом - отдельный релиз. Вот наняли архитекторов, вот - проектантов, вот - бригаду бетонщиков, вот - электриков. А вот - систему кондиционирования взяли у другой компании с их проектом и их монтажом, которые тоже сами кондиционеры не производят. А обслуживать здание будет вообще другая компания (багфиксинг).
    Поймите правильно - я связан тесными личными отношениями с Егвением Крюковым, Ярославом Бровиным и другими разработчиками Embarcadero. Но есть и объективные процессы, которые лично меня по жизни двигали часто не туда, куда я хотел двигаться сам - есть обстоятельства непреодолимой силы. Т.е. мой анализ - безличностный.
    Если мы побьём задачи развития Дельфи на составные компоненты, то - да - есть совсем изолированные задачи:
    - компоненты
    - компиляторы
    - надстройки над IDE
    Возможно, именно такая организация Delphi как открытой среды и явилось причиной модульности не только её самой, но и команды специалистов, её развивающей. Т.е. я бы не стал сейчас резко негативно высказываться (опять же, несмотря на дружбу с разработчиками-Эмбаркадеровцами). Вопрос контрактной схемы развития продукта существует. Например, есть такая компания - SoftServe. Я её знаю ещё со времён Samsung. Потому как эта компания выполняет заказные разработки для крупнейших вендоров в мире, что совсем не вредит продукту.
    Какие минусы. Конечно, если в основе продукта не стоит узкая команда эксклюзивных архитекторов, то могут быть проблемы. Но, положа руку на сердце, даже FMX уже стала зрелой платформой, архитектурно созданной и отработанной Евгением Крюковым. Вспомним Андерса Хейлсберга. Да и даже Вирта - совсем не обязательно, чтобы он работал в Embarcadero для развития языка Object Pascal. Компоненты - ну тут мы вообще видели, что многие компоненты (наш же всеми любимый FireDAC) как раз и создавался вне Borland/Embarcadero. Компилятор - вообще отдельная песня. 
    Какие плюсы. Плюсы - возможность оптимизировать затраты на разработку. Всякий из нас знает, можно нанять строителей на оклад и на "объем - сделал/получил" - дают существенную разницу в результатах. Более того, это - мировой тренд. Если свой разработчик может "пудрить мозг", то сдельный - не сделал, не получил. Наняли другого. А ещё с внешней рабочей силой можно поддержать любой релизный темп. Нужно упереться и выполнить обещание перед пользователями - до-няняли ещё 10 разработчиков и уложились. Стегать своих сотрудников, работающих на постоянке - бесполезно. 
    Что можно ждать в будущем. В будущем нужно ждать следующего релиза. Не секрет, что у Embarcadero roadmap существенно расходится с релизами. В случае с сторонней разработкой это будет невозможно. Всё будет выполняться точнее. Что по деньгам? Не думаю, что это - вопрос денег. Можно больше вложить и "резче" сделать релиз, чем "растягивать удовольствие годами" (то же Linux-компилятор, я ещё до-Embarcadero это слышал). И получить больше продаж. И более сильные рыночные позиции. В любом случае, контроля над разработкой у Embarcadero теперь больше, а средства - гибче. Нужно посмотреть на следующий релиз.
     
     
     
  2. Like
    dnekrasov отреагировална Andrey Efimov в С Наступающим Новым Годом!   
    Уважаемые форумчане!
    Поздравляю Вас с Наступающим Новым Годом и Рождеством!
    Пусть 2017 год станет новым этапом на Вашем пути и принесет успех, самореализацию и, конечно же, счастье.

  3. Like
    dnekrasov отреагировална krapotkin в Очистить очеред нажатий на кнопку   
    вооот
    поэтому надо, чтобы из очереди сообщений они ушли...
    у вас логическая ошибка на слове "пауза". не стоит в обработчике делать паузу вообще. запустили таймер или поток, и вышли.
    все остальные клики не сработают, пока кнопка задизаблена, но события обработаются штатно
    потом таймер или поток вернет ее в enabled и все будет работать без всяких пауз
    вот то, что вам нужно (uses system.treading)
    procedure TForm1.b1Click(Sender: TObject); begin b1.Enabled := false; m1.Lines.Add('test'); TTask.Run( procedure begin sleep(2000); TThread.Synchronize(nil, procedure begin b1.Enabled := True; end); end); end;  
  4. Like
    dnekrasov отреагировална Tera в Светодиодная панель   
    Компонент LED Panel - светодиодная панель с возможностью вывода текста бегущей строкой.
    В архив включена демонстрационная программа с исходным кодом. После запуска программы, кнопка с панели задач прячется в трей.
     

    LED_Panel.zip
  5. Like
    dnekrasov отреагировална Равиль Зарипов (ZuBy) в ANDROID не приходят PUSH Уведомления   
    Такс, начнём с этого:
    Project Options Entitlement List Recieve Push Notification = true Version Info apiKey = server_key (из консоли) uses секция
    в private секции формы пишем
    процедура для получения и отправки токенов на сервер
    событие OnServiceConnectionChange
    событие OnReceiveNotificationEvent
    AndroidManifest.template.xml
    Ваша реализация может отличаться, т.к. у меня работа с FCM выполнена на PHP
  6. Like
    dnekrasov получил реакцию от GASCHE в Как принудительно завершить поток скачивания   
    Очень советовал бы обратить своё внимание на TTask из System.Threading - ну ооччеень полезный класс
    Можете посмотреть запись вебинара где про него подробно рассказывают
  7. Like
    dnekrasov получил реакцию от #WAMACO в TBitmap сглаживание   
    Все просто:
    bmpDest.Canvas.BeginScene; try bmpDest.Canvas.DrawBitmap(bmpSource, RectF(0, 0, bmpSource.Width, bmpSource.Height), RectF(0, 0, bmpDest.Width, bmpDest.Height), 1, False); finally bmpDest.Canvas.EndScene; end; и в bmpDest вы получите Вашу битмапку сглаженную и с новыми размерами
  8. Like
    dnekrasov получил реакцию от AngryOwl в TBitmap сглаживание   
    Все просто:
    bmpDest.Canvas.BeginScene; try bmpDest.Canvas.DrawBitmap(bmpSource, RectF(0, 0, bmpSource.Width, bmpSource.Height), RectF(0, 0, bmpDest.Width, bmpDest.Height), 1, False); finally bmpDest.Canvas.EndScene; end; и в bmpDest вы получите Вашу битмапку сглаженную и с новыми размерами
  9. Like
    dnekrasov получил реакцию от Rusland в TBitmap сглаживание   
    Все просто:
    bmpDest.Canvas.BeginScene; try bmpDest.Canvas.DrawBitmap(bmpSource, RectF(0, 0, bmpSource.Width, bmpSource.Height), RectF(0, 0, bmpDest.Width, bmpDest.Height), 1, False); finally bmpDest.Canvas.EndScene; end; и в bmpDest вы получите Вашу битмапку сглаженную и с новыми размерами
  10. Like
    dnekrasov получил реакцию от enatechno в Не работает редактор стилей   
    Судя по скриншоту - вы просто не видите куда и что добавлять. Откройте Wiew->Structure (Shift+Alt+F11) и работайте со стилем через него
  11. Like
    dnekrasov получил реакцию от Kitty в Не работает редактор стилей   
    Судя по скриншоту - вы просто не видите куда и что добавлять. Откройте Wiew->Structure (Shift+Alt+F11) и работайте со стилем через него
  12. Like
    dnekrasov получил реакцию от Rusland в Не работает редактор стилей   
    Судя по скриншоту - вы просто не видите куда и что добавлять. Откройте Wiew->Structure (Shift+Alt+F11) и работайте со стилем через него
  13. Like
    dnekrasov получил реакцию от AngryOwl в Плоская кнопка (желательно с картинкой)   
    Конечно можно. Что-то вроде этого:

  14. Like
    dnekrasov отреагировална rareMax в MD5   
    Для получения МД5 есть стандартный класс: http://docwiki.embarcadero.com/Libraries/XE8/en/System.Hash.THashMD5
    uses System.Hash; ////////// ... md5param:='&q='+reqest+'&auto_complete=1&lyrics=0&performer_only=0&sort=0&search_own=0'; with fGeneral.RESTRequest1.Params.AddItem do begin name:='sig'; Value:=THashMD5.GetHashString('/method/'+fGeneral.RESTRequest1.Resource+'?v=5.28&https=1'+md5param+'&count=100&offset=1&access_token='+fGeneral.OAuth2Authenticator1.AccessToken+fGeneral.OAuth2Authenticator1.ClientSecret); end;  
  15. Like
    dnekrasov получил реакцию от Andrey Efimov в Плоская кнопка (желательно с картинкой)   
    Конечно можно. Что-то вроде этого:

  16. Like
    dnekrasov получил реакцию от Tarik Live в Таймер в сервисе   
    В архиве - простенький проект. Протестирован на Win и OSX.
     
    TimerThreadDemo.zip
  17. Like
    dnekrasov получил реакцию от Tarik Live в Таймер в сервисе   
    Когда-то, лет 5 назад у меня возникла такая-же проблема, только в Win32-сервисе. Тогда, для её решения, я написал 2 простеньких класса.
    Вот код, может пригодится?
    unit Utils.TimerThread; interface uses System.Classes, System.SysUtils, System.SyncObjs; type TCustomTimerThread = class abstract (TThread) private FLock: TCriticalSection; FCancelledEvent: TSimpleEvent; FInterval: Integer; FOnTimer: TNotifyEvent; function GetInterval: Integer; function GetOnTimer: TNotifyEvent; procedure SetInterval(const Value: Integer); procedure SetOnTimer(const Value: TNotifyEvent); protected procedure Lock; procedure Unlock; procedure Sleep(AInterval: Integer); reintroduce; procedure TerminatedSet; override; procedure DoOnTimer; virtual; public constructor Create(AInterval: Integer; AOnTimer: TNotifyEvent); reintroduce; procedure BeforeDestruction; override; procedure Cancel; virtual; property Interval: Integer read GetInterval write SetInterval; /// <summary> /// <para> /// За синхронизацией потоков отвечает поток в котором обрабатывается OnTimer /// </para> /// <para> /// !!! НЕ ЗАБЫВАТЬ ПРО ЭТО !!! /// </para> /// </summary> property OnTimer: TNotifyEvent read GetOnTimer write SetOnTimer; end; /// <summary> /// Simple wait thread /// </summary> /// <remarks> /// <para> /// !!! Important !!! /// </para> /// <para> /// Use Cancel instead of Terminate. You can get ThreadExternalTerminate /// exception in multi-thread applications /// </para> /// </remarks> TWaitThread = class(TCustomTimerThread) protected procedure Execute; override; public end; /// <summary> /// Thread independed timer /// </summary> /// <remarks> /// <para> /// !!! Important !!! /// </para> /// <para> /// Use Cancel instead of Terminate. You can get ThreadExternalTerminate /// exception in multi-thread applications /// </para> /// </remarks> TTimerThread = class(TCustomTimerThread) private FEnabled: Boolean; function GetEnabled: Boolean; procedure SetEnabled(const Value: Boolean); protected procedure Execute; override; public constructor Create(AInterval: Integer; AOnTimer: TNotifyEvent; AEnabled: Boolean = True); reintroduce; property Enabled: Boolean read GetEnabled write SetEnabled; end; implementation { TCustomTimerThread } procedure TCustomTimerThread.BeforeDestruction; begin FLock.Free; FreeAndNil(FCancelledEvent); inherited; end; constructor TCustomTimerThread.Create(AInterval: Integer; AOnTimer: TNotifyEvent); begin inherited Create; FInterval := AInterval; FOnTimer := AOnTimer; FreeOnTerminate := True; FLock := TCriticalSection.Create; FCancelledEvent := TSimpleEvent.Create; FCancelledEvent.ResetEvent; end; procedure TCustomTimerThread.Cancel; begin FCancelledEvent.SetEvent; end; procedure TCustomTimerThread.DoOnTimer; begin if Assigned(OnTimer) then OnTimer(Self); end; function TCustomTimerThread.GetInterval: Integer; begin Lock; try Result := FInterval; finally Unlock; end; end; function TCustomTimerThread.GetOnTimer: TNotifyEvent; begin Lock; try Result := FOnTimer; finally Unlock; end; end; procedure TCustomTimerThread.Lock; begin FLock.Enter; end; procedure TCustomTimerThread.SetInterval(const Value: Integer); begin Lock; try FInterval := Value; finally Unlock; end; end; procedure TCustomTimerThread.SetOnTimer(const Value: TNotifyEvent); begin Lock; try FOnTimer := Value; finally Unlock; end; end; procedure TCustomTimerThread.Sleep(AInterval: Integer); begin FCancelledEvent.WaitFor(AInterval); end; procedure TCustomTimerThread.TerminatedSet; begin inherited; FCancelledEvent.SetEvent; end; procedure TCustomTimerThread.Unlock; begin FLock.Leave; end; { TWaitThread } procedure TWaitThread.Execute; begin if FCancelledEvent.WaitFor(FInterval) = wrTimeout then DoOnTimer; end; { TTimerThread } constructor TTimerThread.Create(AInterval: Integer; AOnTimer: TNotifyEvent; AEnabled: Boolean); begin inherited Create(AInterval, AOnTimer); FOnTimer := AOnTimer; FEnabled := AEnabled; end; procedure TTimerThread.Execute; begin while not Terminated do case FCancelledEvent.WaitFor(FInterval) of wrTimeout: begin if Enabled then DoOnTimer; end; else Break; end; end; function TTimerThread.GetEnabled: Boolean; begin Lock; try Result := FEnabled; finally Unlock; end; end; procedure TTimerThread.SetEnabled(const Value: Boolean); begin Lock; try FEnabled := Value; finally Unlock; end; end; end.  
  18. Thanks
    dnekrasov получил реакцию от Mars M в Таймер в сервисе   
    В архиве - простенький проект. Протестирован на Win и OSX.
     
    TimerThreadDemo.zip
  19. Like
    dnekrasov получил реакцию от Brovin Yaroslav в Таймер в сервисе   
    Когда-то, лет 5 назад у меня возникла такая-же проблема, только в Win32-сервисе. Тогда, для её решения, я написал 2 простеньких класса.
    Вот код, может пригодится?
    unit Utils.TimerThread; interface uses System.Classes, System.SysUtils, System.SyncObjs; type TCustomTimerThread = class abstract (TThread) private FLock: TCriticalSection; FCancelledEvent: TSimpleEvent; FInterval: Integer; FOnTimer: TNotifyEvent; function GetInterval: Integer; function GetOnTimer: TNotifyEvent; procedure SetInterval(const Value: Integer); procedure SetOnTimer(const Value: TNotifyEvent); protected procedure Lock; procedure Unlock; procedure Sleep(AInterval: Integer); reintroduce; procedure TerminatedSet; override; procedure DoOnTimer; virtual; public constructor Create(AInterval: Integer; AOnTimer: TNotifyEvent); reintroduce; procedure BeforeDestruction; override; procedure Cancel; virtual; property Interval: Integer read GetInterval write SetInterval; /// <summary> /// <para> /// За синхронизацией потоков отвечает поток в котором обрабатывается OnTimer /// </para> /// <para> /// !!! НЕ ЗАБЫВАТЬ ПРО ЭТО !!! /// </para> /// </summary> property OnTimer: TNotifyEvent read GetOnTimer write SetOnTimer; end; /// <summary> /// Simple wait thread /// </summary> /// <remarks> /// <para> /// !!! Important !!! /// </para> /// <para> /// Use Cancel instead of Terminate. You can get ThreadExternalTerminate /// exception in multi-thread applications /// </para> /// </remarks> TWaitThread = class(TCustomTimerThread) protected procedure Execute; override; public end; /// <summary> /// Thread independed timer /// </summary> /// <remarks> /// <para> /// !!! Important !!! /// </para> /// <para> /// Use Cancel instead of Terminate. You can get ThreadExternalTerminate /// exception in multi-thread applications /// </para> /// </remarks> TTimerThread = class(TCustomTimerThread) private FEnabled: Boolean; function GetEnabled: Boolean; procedure SetEnabled(const Value: Boolean); protected procedure Execute; override; public constructor Create(AInterval: Integer; AOnTimer: TNotifyEvent; AEnabled: Boolean = True); reintroduce; property Enabled: Boolean read GetEnabled write SetEnabled; end; implementation { TCustomTimerThread } procedure TCustomTimerThread.BeforeDestruction; begin FLock.Free; FreeAndNil(FCancelledEvent); inherited; end; constructor TCustomTimerThread.Create(AInterval: Integer; AOnTimer: TNotifyEvent); begin inherited Create; FInterval := AInterval; FOnTimer := AOnTimer; FreeOnTerminate := True; FLock := TCriticalSection.Create; FCancelledEvent := TSimpleEvent.Create; FCancelledEvent.ResetEvent; end; procedure TCustomTimerThread.Cancel; begin FCancelledEvent.SetEvent; end; procedure TCustomTimerThread.DoOnTimer; begin if Assigned(OnTimer) then OnTimer(Self); end; function TCustomTimerThread.GetInterval: Integer; begin Lock; try Result := FInterval; finally Unlock; end; end; function TCustomTimerThread.GetOnTimer: TNotifyEvent; begin Lock; try Result := FOnTimer; finally Unlock; end; end; procedure TCustomTimerThread.Lock; begin FLock.Enter; end; procedure TCustomTimerThread.SetInterval(const Value: Integer); begin Lock; try FInterval := Value; finally Unlock; end; end; procedure TCustomTimerThread.SetOnTimer(const Value: TNotifyEvent); begin Lock; try FOnTimer := Value; finally Unlock; end; end; procedure TCustomTimerThread.Sleep(AInterval: Integer); begin FCancelledEvent.WaitFor(AInterval); end; procedure TCustomTimerThread.TerminatedSet; begin inherited; FCancelledEvent.SetEvent; end; procedure TCustomTimerThread.Unlock; begin FLock.Leave; end; { TWaitThread } procedure TWaitThread.Execute; begin if FCancelledEvent.WaitFor(FInterval) = wrTimeout then DoOnTimer; end; { TTimerThread } constructor TTimerThread.Create(AInterval: Integer; AOnTimer: TNotifyEvent; AEnabled: Boolean); begin inherited Create(AInterval, AOnTimer); FOnTimer := AOnTimer; FEnabled := AEnabled; end; procedure TTimerThread.Execute; begin while not Terminated do case FCancelledEvent.WaitFor(FInterval) of wrTimeout: begin if Enabled then DoOnTimer; end; else Break; end; end; function TTimerThread.GetEnabled: Boolean; begin Lock; try Result := FEnabled; finally Unlock; end; end; procedure TTimerThread.SetEnabled(const Value: Boolean); begin Lock; try FEnabled := Value; finally Unlock; end; end; end.  
  20. Like
    dnekrasov отреагировална Равиль Зарипов (ZuBy) в Наложение картинки на фото   
    да, а чем проблемы?
    через Canvas.DrawBitmap 
  21. Like
    dnekrasov получил реакцию от AngryOwl в [Windows] Глобальный хук на клавиши возможно ли FMX   
    Легче всего, по моему мнению, сделать так:
    ... FWnd := AllocateHWnd(WindowProc); ... procedure WindowProc(var AMsg: TMessage); begin case AMsg.Msg of WM_HOTKEY: case TWMHotKey(AMsg).hotkey of 1: ...; 2: ...; ... end; end; end; ... RegisterHotkey(FWnd, ...); // как обычно в VCL ... UnregisterHotkey(...); // как обычно в VCL ...  
  22. Like
    dnekrasov получил реакцию от Просто Проги в [Windows] Глобальный хук на клавиши возможно ли FMX   
    Легче всего, по моему мнению, сделать так:
    ... FWnd := AllocateHWnd(WindowProc); ... procedure WindowProc(var AMsg: TMessage); begin case AMsg.Msg of WM_HOTKEY: case TWMHotKey(AMsg).hotkey of 1: ...; 2: ...; ... end; end; end; ... RegisterHotkey(FWnd, ...); // как обычно в VCL ... UnregisterHotkey(...); // как обычно в VCL ...  
  23. Like
    dnekrasov получил реакцию от Brovin Yaroslav в [Windows] Глобальный хук на клавиши возможно ли FMX   
    Легче всего, по моему мнению, сделать так:
    ... FWnd := AllocateHWnd(WindowProc); ... procedure WindowProc(var AMsg: TMessage); begin case AMsg.Msg of WM_HOTKEY: case TWMHotKey(AMsg).hotkey of 1: ...; 2: ...; ... end; end; end; ... RegisterHotkey(FWnd, ...); // как обычно в VCL ... UnregisterHotkey(...); // как обычно в VCL ...  
  24. Like
    dnekrasov отреагировална Pax Beach в TBitmap и экономия памяти   
    В FMX Opacity всегда от 0 до 1. Не верьте безоговорочно примерам Студии, они не актуальные.
     
  25. Like
    dnekrasov отреагировална Error в PowerOff - пример приложения с гибким интерфейсом(flexible interface)   
    PowerOff - максимально упрощенное приложение для автоотключения компьютера.
    Приложение и исходный код можно загрузить здесь: https://github.com/errorcalc/PowerOff
    Полезно если вы перед сном любите включать ролики на YouTube/музыку/сериалы/фильмы, но засыпаете и они продолжают играть всю ночь, вызывая на утро головную боль...
    По большому счету утилита была написана и с целью проверить пригодность технологии FireMonkey для разработки - в целом - да, на данный момент, под Windows (и для имитирования UWP интерфейса), это вполне работоспособная технология.
×
×
  • Создать...