Firemonkey में “No Activate” फॉर्म कैसे बनाएं


147

अपने NSView उपवर्ग में इन विधियों को जोड़कर XCode में विंडो को क्लिक करने पर सक्रिय होने से रोका जा सकता है:

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

विंडोज प्लेटफॉर्म में यह इस सरल कोड द्वारा किया जाता है:

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 को कैसे उप-वर्ग कर सकता हूं?

मैं फायरमैन में " नो एक्टिवेट " फॉर्म कैसे बना सकता हूं ?


3
यह निश्चित नहीं है कि क्या यह Firemonkey पर लागू होता है, या यदि यह आपके प्रश्न का ठीक से उत्तर देता है, लेकिन आप इस उदाहरण पर एक नज़र डालना चाहते हैं: delphi.about.com/od/delphitips2008/qt/ex_noactive.htm
TildalWave

थैंक्यू, लेकिन यह केवल विंडोज के लिए है और आसान तरीका है मेरा समाधान "सेटविंडोवलॉन्ग" द्वारा ऊपर वर्णित है, सवाल मैकओएस के बारे में है।
mh taqia


Devon: यह लिंक कैसे मेरी मदद कर सकता है?
mh taqia

WBAR के लिए धन्यवाद, यह दूसरा इनाम है!
mh taqia

जवाबों:


13

इसे का उपयोग संभव है NSPanel साथ NSNonactivatingPanelMask झंडा। Fmx फॉर्म का NSView NSPanel का बच्चा बनना चाहिए। मैंने एक सहायक वर्ग लिखा है जो विंडोज और मैक दोनों प्लेटफॉर्म ( एक्सई 4 पर काम करता है) के लिए काम करता है :

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 में डालने की सलाह दी जाती है।

यहाँ छवि विवरण दर्ज करें

नोट : WindowHandleToPlatform XE3 में मौजूद नहीं लगता है ताकि लाइन को बदला जा सके

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

1
महान समाधान के लिए धन्यवाद - विंडोहैलेटोप्लेट रिकॉर्डर XE3 में मौजूद नहीं लगता है ताकि लाइन को खिड़की से बदला जा सके: = NSWindow (NSWindowFromObjC (FmxHandleToObjC (Form.Handle)));
डेविड पीटर्स

2

आप फ़ोकस माउस हैंडलिंग को बंद कर सकते हैं ताकि इसे फोकस किया जा सके। आपके फॉर्म को मान लेना 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);

इसमें एक छोटी सी समस्या है कि यह एक सही माउस क्लिक को नहीं रोकता है। यदि यह समस्या है, तो आपको फॉर्म में मूसडाउन ईवेंट का जवाब देना होगा और मुख्य फॉर्म मूसडाउन को कॉल करना होगा ताकि यह माउस ईवेंट को न खोए। चूंकि सही माउस डाउन माउस की घटनाओं को कैप्चर करेगा, इसलिए आपको माउस चाल और माउस अप घटनाओं का भी जवाब देना होगा - उन्हें आपके मुख्य रूप में अग्रेषित करना। हालांकि यह माउस को राइट क्लिक पर कैप्चर करता है, फिर भी यह फॉर्म को फोकस नहीं करेगा।

डेव पीटर्स डीपी सॉफ्टवेयर


गलत, काम नहीं करता। रूप परिवर्तन कीबोर्ड पर क्लिक पर ध्यान केंद्रित करता है।
mh taqia

वैसे इसका ध्यान नहीं जा रहा है लेकिन क्या होता है कि कोई भी माउस क्लिक उस फॉर्म से गुजरता है जो उसके नीचे होता है। यदि आप यह व्यवस्था कर सकते हैं कि नॉन फ़ोकस फॉर्म में टॉपमोस्ट प्रॉपर्टी सेट है और आपके अपने मुख्य फॉर्म का केवल एक खाली हिस्सा इसके नीचे है, तो यह काम करेगा। यदि आपके पास विंडो के नीचे कोई मुख्य रूप से नियंत्रण है तो वे तब फोकस करेंगे जब आप माउस क्लिक करेंगे क्योंकि गैर-फ़ोकस विंडो व्यवहार करती है जैसे कि यह नहीं है। इसी तरह अगर विंडो को डेस्कटॉप पर रखा जाता है तो डेस्कटॉप पर माउस क्लिक हो जाता है और आपका एप्लिकेशन फोकस खो देता है।
डेविड पीटर्स

ध्यान दें कि मुझे माउस ईवेंट की आवश्यकता है। मैं माउस घटनाओं को अनदेखा नहीं कर सकता। मैं एक बटन पर क्लिक करना चाहता हूं, जब मैं माउस पॉइंटर को एक नियंत्रण पर रखता है, तो मुझे फायरमैन की एनिमेशन भी चाहिए। मान लें कि मैं एक वर्चुअल कीबोर्ड बनाना चाहता हूं, अग्रभूमि अनुप्रयोग (उदाहरण के लिए) TextEdit है। जब मैं अपने fmx फॉर्म के एक बटन पर क्लिक करता हूं, तो एक कीबोर्ड ईवेंट उत्पन्न हो जाएगा और एक चरित्र टाइप हो जाएगा।
mh taqia
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.