descargar compiler macos delphi delphi-xe2 c++builder firemonkey

macos - compiler - c++ builder download



Cómo crear el formulario "No activar" en Firemonkey (2)

Es posible usar NSPanel con NSNonactivatingPanelMask . El NSView de la forma fmx debería convertirse en hijo de NSPanel. Escribí una clase de ayuda que funciona tanto para plataformas Windows como Mac ( Works on XE4 ):

unit NoActivateForm; interface uses Fmx.Forms, Fmx.Types {$IFDEF POSIX} , Macapi.AppKit {$ENDIF} ; type TNoActivateForm = class private form: TForm; {$IFDEF POSIX} panel: NSPanel; timer: TTimer; // for simulating mouse hover event {$ENDIF} procedure SetPosition(const x, y: Integer); procedure GetPosition(var x, y: Integer); procedure SetDimensions(const width, height: Integer); procedure SetLeft(const Value: Integer); procedure SetTop(const Value: Integer); procedure SetHeight(const Value: Integer); procedure SetWidth(const Value: Integer); procedure SetVisible(const Value: Boolean); function GetLeft: Integer; function GetTop: Integer; function GetHeight: Integer; function GetWidth: Integer; function GetVisible: Boolean; {$IFDEF POSIX} procedure OnTimer(Sender: TObject); {$ENDIF} public constructor Create(AForm: TForm); destructor Destroy; override; property Left: Integer read GetLeft write SetLeft; property Top: Integer read GetTop write SetTop; property Height: Integer read GetHeight write SetHeight; property Width: Integer read GetWidth write SetWidth; property Visible: Boolean read GetVisible write SetVisible; end; implementation uses Classes, System.Types {$IFDEF MSWINDOWS} , Winapi.Windows; {$ELSE} , Macapi.CocoaTypes, FMX.Platform.Mac, Macapi.CoreGraphics, Macapi.CoreFoundation; {$ENDIF} constructor TNoActivateForm.Create(AForm: TForm); {$IFDEF POSIX} var rect: NSRect; bounds: CGRect; window: NSWindow; style: integer; panelCount: integer; begin form := AForm; form.Visible := false; bounds := CGDisplayBounds(CGMainDisplayID); rect := MakeNSRect(form.Left, bounds.size.height - form.Top - form.Height, form.ClientWidth, form.ClientHeight); style := NSNonactivatingPanelMask; style := style or NSHUDWindowMask; panel := TNSPanel.Wrap( TNSPanel.Alloc.initWithContentRect(rect, style, NSBackingStoreBuffered, true)); panel.setFloatingPanel(true); //panel.setHasShadow(false); optional window := WindowHandleToPlatform(form.Handle).Wnd; panel.setContentView(TNSView.Wrap(window.contentView)); TNSView.Wrap(window.contentView).retain; timer := TTimer.Create(form.Owner); timer.OnTimer := OnTimer; timer.Interval := 50; end; {$ELSE} var hWin: HWND; begin form := AForm; form.TopMost := true; hWin := FindWindow(PWideChar(''FM'' + form.ClassName), PWideChar(form.Caption)); if hWin <> 0 then SetWindowLong(hWin, GWL_EXSTYLE, GetWindowLong(hWin, GWL_EXSTYLE) or WS_EX_NOACTIVATE); end; {$ENDIF} destructor TNoActivateForm.Destroy; {$IFDEF POSIX} begin panel.release; end; {$ELSE} begin end; {$ENDIF} procedure TNoActivateForm.SetPosition(const x, y: Integer); {$IFDEF POSIX} var point: NSPoint; screen: CGRect; begin screen := CGDisplayBounds(CGMainDisplayID); point.x := x; point.y := round(screen.size.height) - y - form.height; panel.setFrameOrigin(point); end; {$ELSE} begin form.Left := x; form.Top := y; end; {$ENDIF} procedure TNoActivateForm.GetPosition(var x, y: Integer); {$IFDEF POSIX} var screen: CGRect; begin screen := CGDisplayBounds(CGMainDisplayID); x := round(panel.frame.origin.x); y := round(screen.size.height - panel.frame.origin.y - panel.frame.size.height); end; {$ELSE} begin x := form.Left; y := form.Top; end; {$ENDIF} procedure TNoActivateForm.SetDimensions(const width, height: Integer); {$IFDEF POSIX} var size: NSSize; begin size.width := width; size.height := height; panel.setContentSize(size); end; {$ELSE} begin form.width := width; form.height := height; end; {$ENDIF} procedure TNoActivateForm.SetLeft(const Value: Integer); begin SetPosition(Value, Top); end; procedure TNoActivateForm.SetTop(const Value: Integer); begin SetPosition(Left, Value); end; procedure TNoActivateForm.SetHeight(const Value: Integer); begin SetDimensions(Width, Value); end; procedure TNoActivateForm.SetWidth(const Value: Integer); begin SetDimensions(Value, Height); end; procedure TNoActivateForm.SetVisible(const Value: Boolean); begin {$IFDEF POSIX} panel.setIsVisible(Value); {$ELSE} form.visible := Value; {$ENDIF} end; function TNoActivateForm.GetLeft: Integer; var x, y: Integer; begin GetPosition(x, y); result := x; end; function TNoActivateForm.GetTop: Integer; var x, y: Integer; begin GetPosition(x, y); result := y; end; function TNoActivateForm.GetHeight: Integer; begin {$IFDEF POSIX} result := round(panel.frame.size.height); {$ELSE} result := form.Height; {$ENDIF} end; function TNoActivateForm.GetWidth: Integer; begin {$IFDEF POSIX} result := round(panel.frame.size.width); {$ELSE} result := form.Width; {$ENDIF} end; function TNoActivateForm.GetVisible: Boolean; begin {$IFDEF POSIX} result := panel.isVisible(); {$ELSE} result := form.visible; {$ENDIF} end; {$IFDEF POSIX} procedure TNoActivateForm.OnTimer(Sender: TObject); var event: CGEventRef; point: CGPoint; form_rect: TRectF; client_point, mouse_loc: TPointF; shift: TShiftState; begin event := CGEventCreate(nil); point := CGEventGetLocation(event); CFRelease(event); mouse_loc.SetLocation(point.x, point.y); if Visible = true then begin form_rect := RectF(0, 0, form.Width, form.Height); client_point.X := mouse_loc.X - Left; client_point.Y := mouse_loc.y - Top; if PtInRect(form_rect, client_point) then form.MouseMove(shift, client_point.x, client_point.y) else form.MouseLeave(); end; end; {$ENDIF} end.

Uso de la unidad anterior:

TNoActivateForm *naKeyboard; // global scope void __fastcall TfrmKeyboard::TfrmKeyboard(TObject *Sender) { naKeyboard = new TNoActivateForm(frmKeyboard); // frmKeyboard is a normal fmx form naKeyboard->Visible = true; }

Si frmKeyboard es su Formulario principal, entonces no coloque el código anterior en el constructor de formulario, se recomienda ponerlo en OnShow.

Nota : WindowHandleToPlatform no parece existir en XE3 por lo que la línea puede ser reemplazada por

window := NSWindow(NSWindowFromObjC(FmxHandleToObjC(Form.Handle)));

En XCode al agregar estos métodos a su subclase NSView puede evitar que la ventana se active al hacer clic en ella:

- (BOOL)shouldDelayWindowOrderingForEvent:(NSEvent )theEvent { return YES; } - (BOOL)acceptsFirstMouse:(NSEvent )theEvent { return YES; } - (void)mouseDown:(NSEvent )theEvent { [[[NSApp]] preventWindowOrdering]; }

En la plataforma de Windows, se realiza mediante este código simple:

HWND hWnd = FindWindowW((String("FM") + fmxForm->ClassName()).c_str(), fmxForm->Caption.c_str()); SetWindowLong(hWnd, GWL_EXSTYLE, GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_NOACTIVATE);

¿Cómo puedo subclase NSView para evitar que mi FMX TForm se active al hacer clic en él?

¿Cómo puedo crear el formulario " No activar " en firemonkey ?


Puede desactivar el manejo del mouse de formularios para evitar que se enfoque. Suponiendo que su formulario se llama myform:

uses fmx.platform.mac, macapi.appkit; . . Var nswin:nswindow; . . NSWin:= NSWindow(NSWindowFromObjC(FmxHandleToObjC(myform.Handle))); { get the NSWindow } NSWin.setIgnoresMouseEvents(true); { ignore mouse events } NSWin.setAcceptsMouseMovedEvents(false);

Existe un pequeño problema ya que no detiene el clic con el botón derecho del mouse. Si eso es un problema, tendrá que responder al evento mousedown en el formulario y llamar al mousedown de las formas principales para que no pierda el evento del mouse. Como el mouse derecho hacia abajo capturará los eventos del mouse, también tendrá que responder a los eventos de movimiento del mouse y mouse up también, reenviándolos a su formulario principal. Aunque captura el mouse con el botón derecho, no enfocará el formulario.

Dave Peters DP Software