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

dnekrasov

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

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

  • Посещение

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

    52

Весь контент dnekrasov

  1. dnekrasov

    Align кнопок

    Перед тем как сделать кнопку видимой присвоить ей Position.X на 1 больше чем Position.X кнопки, за которой она должна следовать
  2. Нужно переопределять основной обработчик событий окна, но легче всего сделать так: ... 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 ... С OSX не все так просто. Посмотрите темы Глобальный Hook в OSX и Глобальные хоткеи в OS X
  3. Не забудьте поделиться
  4. В архиве - простенький проект. Протестирован на Win и OSX. TimerThreadDemo.zip
  5. Когда-то, лет 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.
  6. На самом деле слишком уж громко они заявили о поддержке HDPI. На первый взгляд - сделали только масштабирование форм при включенной поддержке HDPI (ну может еще и реализацию MultyResBitmaps). А необходимое при работе с HDPI - осталось неизменным. Достаточно взглянуть на реализацию IFMXDeviceMetricsService.GetDisplayMetrics: function TPlatformWin.GetDisplayMetrics: TDeviceDisplayMetrics; var R: TRect; begin Winapi.Windows.GetWindowRect(GetDesktopWindow, R); Result.PhysicalScreenSize := TSize.Create(R.Width, R.Height); Result.RawScreenSize := Result.PhysicalScreenSize; Result.LogicalScreenSize := Result.PhysicalScreenSize; if Result.PhysicalScreenSize.cx > 0 then Result.AspectRatio := Result.PhysicalScreenSize.cy / Result.PhysicalScreenSize.cx else Result.AspectRatio := 1; Result.PixelsPerInch := 96; // Windows Default Result.ScreenScale := 1; Result.FontScale := 1; end; Как было так и осталось
  7. Попробуйте TBitmapSurface.StretchFrom
  8. dnekrasov

    FullScreen в El Capitan

    BorderStyle установить в Single или ToolWindow Можно ещё поиграться с NSWindow.setCollectionBehavior (флаги NSWindowCollectionBehaviorFullScreenPrimary и NSWindowCollectionBehaviorFullScreenAuxiliary)
  9. Отлавливать события kCGEventKeyDown необходимо было только ради реализации глобальных хоткеев. Их сделал другим способом. Так что тему можно закрывать.
  10. Ещё в AppKit.framework у NSEvent есть такой метод как addGlobalMonitorForEventsMatchingMask. Может кто использовал?
  11. Хм... Сам задал вопрос и сам же на него отвечаю... Нашёл ещё один вариант: Импортировал несколько методов из Carbon.framework и всё получилось: uses Macapi.CocoaTypes, Macapi.ObjCRuntime, Macapi.CoreFoundation, Macapi.CoreServices; const HITFwk = '/System/Library/Frameworks/Carbon.framework/Frameworks/HIToolbox.framework/HIToolbox'; type EventParamName = OSType; EventParamNamePtr = ^EventParamName; EventParamType = OSType; EventParamTypePtr = ^EventParamType; EventRef = ^SInt32; EventRefPtr = ^EventRef; EventHotKeyIDPtr = ^EventHotKeyID; EventHotKeyID = record signature: OSType; id: UInt32; end; EventTypeSpec = record eventClass: OSType; eventKind: UInt32; end; EventTypeSpecPtr = ^EventTypeSpec; EventTargetRef = ^SInt32; EventHotKeyRef = ^SInt32; OptionBits = UInt32; ByteCountPtr = ^ByteCount; EventHandlerRef = ^SInt32; EventHandlerRefPtr = ^EventHandlerRef; EventHandlerCallRef = ^SInt32; EventHandlerCallRefPtr = ^EventHandlerCallRef; type EventHandlerProcPtr = function(inHandlerCallRef: EventHandlerCallRef; inEvent: EventRef; inUserData: Pointer): OSStatus; cdecl; EventHandlerUPP = EventHandlerProcPtr; const kEventHotKeyNoOptions = ; kEventHotKeyExclusive = 1 shl ; kEventRawKeyDown = 1; kEventRawKeyRepeat = 2; kEventRawKeyUp = 3; kEventRawKeyModifiersChanged = 4; kEventHotKeyPressed = 5; kEventHotKeyReleased = 6; kEventClassKeyboard: UInt32 = Ord('k') shl 24 + Ord('e') shl 16 + Ord('y') shl 8 + Ord('b'); typeEventHotKeyID: UInt32 = Ord('h') shl 24 + Ord('k') shl 16 + Ord('i') shl 8 + Ord('d'); typeWildCard: UInt32 = Ord('*') shl 24 + Ord('*') shl 16 + Ord('*') shl 8 + Ord('*'); kEventParamDirectObject: UInt32 = Ord('-') shl 24 + Ord('-') shl 16 + Ord('-') shl 8 + Ord('-'); const cmdKeyBit = 8; { command key down?} shiftKeyBit = 9; { shift key down?} optionKeyBit = 11; { option key down?} controlKeyBit = 12; { control key down?} cmdKey = 1 shl cmdKeyBit; shiftKey = 1 shl shiftKeyBit; optionKey = 1 shl optionKeyBit; controlKey = 1 shl controlKeyBit; // in version 10.0 and later in Carbon.framework function GetApplicationEventTarget: EventTargetRef; cdecl; external HITFwk name _PU + 'GetApplicationEventTarget'; {$EXTERNALSYM GetApplicationEventTarget} // in version 10.0 and later in Carbon.framework function InstallEventHandler(inTarget: EventTargetRef; inHandler: EventHandlerUPP; inNumTypes: UInt32; {const} inList: {variable-size-array} EventTypeSpecPtr; inUserData: Pointer; outRef: EventHandlerRefPtr { can be NULL } ): OSStatus; cdecl; external HITFwk name _PU + 'InstallEventHandler'; {$EXTERNALSYM InstallEventHandler} // in version 10.0 and later in Carbon.framework function RemoveEventHandler( inHandlerRef: EventHandlerRef ): OSStatus; cdecl; external HITFwk name _PU + 'RemoveEventHandler'; {$EXTERNALSYM RemoveEventHandler} // in version 10.0 and later in Carbon.framework function RegisterEventHotKey(inHotKeyCode: UInt32; inHotKeyModifiers: UInt32; inHotKeyID: EventHotKeyID; inTarget: EventTargetRef; inOptions: OptionBits; var outRef: EventHotKeyRef): OSStatus; cdecl; external HITFwk name _PU + 'RegisterEventHotKey'; {$EXTERNALSYM RegisterEventHotKey} // in version 10.0 and later in Carbon.framework function UnregisterEventHotKey(inHotKey: EventHotKeyRef): OSStatus; cdecl; external HITFwk name _PU + 'UnregisterEventHotKey'; {$EXTERNALSYM UnregisterEventHotKey} // in version 10.0 and later in Carbon.framework function GetEventParameter(inEvent: EventRef; inName: EventParamName; inDesiredType: EventParamType; outActualType: EventParamTypePtr { can be NULL }; inBufferSize: ByteCount; outActualSize: ByteCountPtr { can be NULL }; outData: Pointer { can be NULL } ): OSStatus; cdecl; external HITFwk name _PU + 'GetEventParameter'; {$EXTERNALSYM GetEventParameter}
  12. Как APP я бы не советовал - это все равно как под винду выкладывать голый EXE-шник... а PKG и в стандартную папку Applications установит и Bandle зарегит и права раздаст. К тому же
  13. Попробуйте передавать в этот перегруженный метод не просто (B1) а (B1 as B1.ClassType)
  14. Увы, не помогло... Если файл базы лежит в документах пользователя - то сервис, возможно, просто не имеет прав доступа в эту папку. Попробуйте его переместить в папку общие документы (тогда можно будет использовать System.IOUtils.TPath.GetSharedDocumentsPath) или в какую-нибудь другую публичную папку. Увы, не помогло... Полностью согласен, только одно маленькое дополнение - вместо TPath.GetDocumentsPath + TPath.DirectorySeparatorChar лучше использовать IncludeTrailingPathDelimiter(TPath.GetDocumentsPath)
  15. Sorry, не заметил. Тогда можно попробовать ввести локальные переменные тех типов, которые могут быть в Value, а потом тупо скопировать содержимое памяти из них по адресу Result
  16. Я этот механизм реализовывал следующим способом: В родительском классе 2 метода - public Draw и protected DoDraw; virtual; abstract; В родительском Draw вызывается DoDraw В наследниках остается переопределить только DoDraw и все прекрасно работает без is, as, if, case of.
  17. А что Вам мешает использовать TValue.AsType<T> ?
  18. Возможно проблема в System.IOUtils.TPath.GetDocumentsPath Попробуйте прописать путь к базе константой. System.IOUtils.TPath.GetDocumentsPath - возвращает путь к папке "Мои документы" пользователя, а сервисы запускаются от своего пользователя.
  19. Попробуйте приложение http://s.sudre.free.fr/Software/Packages/about.html Я в нём нашёл все что мне нужно
  20. Не знаю как в DropDMG (и зачем DMG). Создайте .pkg (стандартными средствами) и распростроняйте. Некоторое время назад задавался вопромом - PKG или DMG. Отказался от DMG почитав его спецификацию. Если создавать инсталляшку под Mac - то или pkg или mpkg. DMG - просто представление Вашего приложения в виде образа диска.
  21. 1. Получить на сайте сертификаты (Developer ID Application и 3rd Party Mac Developer Installer). 2. Установить их на Маке. 3. Прописать их в Delphi (Tools->Options->Provisioning) 4. Сделать Deploy с конфигурацией AppStore После этого на Маке появится [ваше приложение].pkg, на который уже не ругается OSX
  22. Решил вопрос с помощью CGEventTap (http://fire-monkey.ru/topic/2119-globalnyi-hook-v-osx/)
  23. Пока нашел только такой выход: Создаю инсталляшку с помошью Packages (http://s.sudre.free.fr/Software/Packages/about.html) При завершении установки выполняю скрипт #!/bin/sh touch /private/var/db/.AccessibilityAPIEnabled && sqlite3 "/Library/Application Support/com.apple.TCC/TCC.db" "INSERT or REPLACE INTO access (service, client, client_type, allowed, prompt_count) VALUES ('kTCCServiceAccessibility', 'com.CompanyName.AppName', 0, 1, 0);" После этого все работает!
×
×
  • Создать...