Firemonkey에서 "No Activate"양식을 만드는 방법
XCode에서 이러한 메소드를 NSView 서브 클래스에 추가하면 클릭시 창이 활성화되지 않을 수 있습니다.
- (BOOL)shouldDelayWindowOrderingForEvent:(NSEvent )theEvent {
return YES;
}
- (BOOL)acceptsFirstMouse:(NSEvent )theEvent {
return YES;
}
- (void)mouseDown:(NSEvent )theEvent {
[[[NSApp]] preventWindowOrdering];
}
Windows 플랫폼에서이 간단한 코드로 수행됩니다.
HWND hWnd = FindWindowW((String("FM") + fmxForm->ClassName()).c_str(),
fmxForm->Caption.c_str());
SetWindowLong(hWnd, GWL_EXSTYLE,
GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_NOACTIVATE);
FMX TForm을 클릭 할 때 활성화되지 않도록 NSView를 서브 클래 싱하려면 어떻게해야합니까?
firemonkey 에서 " No Activate "양식을 어떻게 만들 수 있습니까?
NSNonactivatingPanelMask 플래그 와 함께 NSPanel 을 사용할 수 있습니다 . fmx 형식의 NSView는 NSPanel의 자식이되어야합니다. Windows 및 Mac 플랫폼 모두에서 작동하는 도우미 클래스를 작성했습니다 ( 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.
상기 단위의 사용법 :
TNoActivateForm *naKeyboard; // global scope
void __fastcall TfrmKeyboard::TfrmKeyboard(TObject *Sender)
{
naKeyboard = new TNoActivateForm(frmKeyboard); // frmKeyboard is a normal fmx form
naKeyboard->Visible = true;
}
frmKeyboard가 기본 양식 인 경우 양식 생성자에 위 코드를 넣지 말고 OnShow에 넣는 것이 좋습니다.
Note: WindowHandleToPlatform doesn't seem to exist in XE3 so that line can be replaced with
window := NSWindow(NSWindowFromObjC(FmxHandleToObjC(Form.Handle)));
You can turn off the forms mouse handling to prevent it being focused. Assuming your form is called 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);
There is a slight problem in that it doesn't stop a right mouse click. If that's a problem, you will have to respond to the mousedown event in the form and call the main forms mousedown so it doesn't lose the mouse event. Since the right mouse down will then capture the mouse events, you also then need to respond to mouse move and mouse up events too - forwarding them to your main form. Although it captures the mouse on right click, it will still not focus the form.
Dave Peters DP Software
참고URL : https://stackoverflow.com/questions/12769064/how-to-create-no-activate-form-in-firemonkey
'IT' 카테고리의 다른 글
당신이 본 가장 우스운 비관은 무엇입니까? (0) | 2020.06.14 |
---|---|
중첩을 줄이기 위해“if”문을 반전 (0) | 2020.06.14 |
언제 std :: forward를 사용하여 인수를 전달합니까? (0) | 2020.06.14 |
Git 소스 제어 하에서 IntelliJ IDEA 프로젝트 파일을 처리하는 방법은 끊임없이 변경됩니까? (0) | 2020.06.14 |
누가이 프로그래밍 말을 썼습니까? (0) | 2020.06.14 |