2011-12-06 13 views
6

Po umieszczeniu kontrolki TRibbon na formularzu, który nie jest MainForm aplikacji, działania TRIBBON (tj. Wytnij, Wklej) zawsze będą zwracać fokus do MainForm po akcji jest wykonywany.Delphi XE - Działania TRIBBON zawsze wysyłają fokus do MainForm

Zdarza się to, nawet jeśli TForm posiadający TRibbon nie jest potomkiem MainForm.

Używam 64-bitowego systemu Windows 7, Embarcadero RAD Studio XE w wersji 15.0.3953.35171.

Czy używam kontrolki TRibon w nieprawidłowy sposób, czy jest to problem z TRIBBONEM?

+2

Wstęga ma być elementem interfejsu użytkownika w swojej głównej postaci, to jednak w rzeczywistości „modyfikować” formularza jest dodano do. Jeśli umieścisz wstążkę gdzieś poza główną formą twojego programu, a ona wyśle ​​fokus z powrotem do aplikacji.MainForm, nie jestem zaskoczony; spodziewa się, że jest częścią głównej formy. VCL zawiera kod źródłowy, więc możesz otworzyć jednostkę i sprawdzić, czy możesz znaleźć odpowiedni kod. –

+1

Aplikacja, którą projektuję, ma wygląd "Outlook'a", który w swojej implementacji wykorzystuje Wstążkę dla głównego programu i inną Wstążkę do tworzenia wiadomości e-mail, elementów kalendarza, kontaktów itp. Za każdym razem, gdy używam akcji Wstążki Outlook w e-mailu nie wysyłam mojego zainteresowania z powrotem do głównego okna Outlooka. Zrobiłem trochę patrzenia przez źródło dla komponentu TRibbon, ale jest wprawdzie trochę gruby. Nadal będę to robił, aby sprawdzić, czy mogę stwierdzić, gdzie to się dzieje, i czy mogę zmienić to zachowanie.Jak dotąd jednak nie miałem szczęścia. – Aaron

+2

Brzmi okropnie jak błąd dla mnie. Takie zachowanie nie powinno się zdarzyć. Jeśli możesz wymieniać się w prostej aplikacji, powinieneś zgłosić to do QC –

Odpowiedz

2

Jest to wyraźnie zgodne z projektem. Przykładowy kod urywek z „ribbonactnctrls.pas”:

procedure TRibbonBaseButtonControl.Click; 
begin 
    inherited; 
    SetFocus(Application.MainForm.Handle); 
end; 

Jak widać nie ma warunków sprawdzane, które pomogą nam uniknąć połączenia. Ten sam kod znajduje się również w wyborze pozycji menu i kluczowych procedurach obsługi komunikatów.


Prawdopodobnie zmodyfikowałbym źródło komentując wywołania fokusu i spróbował sprawdzić, czy są jakieś efekty uboczne.

Jako alternatywę można przywrócić ostrość z powrotem do formularza po przełączeniu do formularza głównego. Załóżmy „ActionList1” jest TActionList że zawiera standardowe czynności na nie głównego formularza:

type 
    TForm2 = class(TForm) 
    .. 
    procedure ActionList1Execute(Action: TBasicAction; var Handled: Boolean); 
    private 
    .. 

procedure TForm2.ActionList1Execute(Action: TBasicAction; var Handled: Boolean); 
begin 
    PostMessage(Handle, WM_SETFOCUS, WPARAM(True), 0); 
end; 

Będzie to jednak spowodować główną postać krótko migać za każdym razem akcja jest wykonywana. Jeśli tego nie chcesz, możesz zmienić projekt tak, aby główna postać wiedziała, kiedy robi się niechciany fokus, i udawać, że nie jest skupiona.

W Unit1:

const 
    UM_CANCELIGNOREFOCUS = WM_USER + 7; 

type 
    TForm1 = class(TForm) 
    .. 
    private 
    FIgnoreFocus: Boolean; 
    procedure UMCancelIgnoreFocus(var Msg: TMessage); message UM_CANCELIGNOREFOCUS; 
    procedure WMNCActivate(var Msg: TWMNCActivate); message WM_NCACTIVATE; 
    public 
    property IgnoreFocus: Boolean write FIgnoreFocus; 
    end; 

... 
uses Unit2; 

procedure TForm1.WMNCActivate(var Msg: TWMNCActivate); 
begin 
    Msg.Result := 0; 
    if not (Msg.Active and FIgnoreFocus) then 
    inherited; 
end; 

procedure TForm1.UMCancelIgnoreFocus(var Msg: TMessage); 
begin 
    FIgnoreFocus := False; 
    TForm(Msg.WParam).SetFocus; 
end; 

w Unit2:

uses 
    unit1; 

procedure TForm2.ActionList1Execute(Action: TBasicAction; var Handled: Boolean); 
begin 
    Form1.IgnoreFocus := True; 
    PostMessage(Form1.Handle, UM_CANCELIGNOREFOCUS, NativeInt(Self), 0); 
end; 


Jednak to nie wystarczy, jeśli nie masz zestaw 'MainFormOnTaskBar' w źródle projektu, gdyż wtedy formularzu głównym nie tylko skupi się, ale zostanie postawiony na pierwszym planie. W takim przypadku obie formy mogą reagować na niechcianą zmianę/aktywację fokusa przez zamrożenie ich zleceń Z. Kod będzie wówczas stać na Unit1:

const 
    UM_CANCELIGNOREFOCUS = WM_USER + 7; 

type 
    TForm1 = class(TForm) 
    .. 
    private 
    FIgnoreFocus: Boolean; 
    procedure UMCancelIgnoreFocus(var Msg: TMessage); message UM_CANCELIGNOREFOCUS; 
    procedure WMNCActivate(var Msg: TWMNCActivate); message WM_NCACTIVATE; 
    procedure WMWindowPosChanging(var Msg: TWMWindowPosChanging); 
     message WM_WINDOWPOSCHANGING; 
    public 
    property IgnoreFocus: Boolean read FIgnoreFocus write FIgnoreFocus; 
    end; 

var 
    Form1: TForm1; 

implementation 

{$R *.dfm} 

uses Unit2; 

procedure TForm1.WMNCActivate(var Msg: TWMNCActivate); 
begin 
    Msg.Result := 0; 
    if not (Msg.Active and FIgnoreFocus) then 
    inherited; 
end; 

procedure TForm1.WMWindowPosChanging(var Msg: TWMWindowPosChanging); 
begin 
    inherited; 
    if FIgnoreFocus then 
    Msg.WindowPos.flags := Msg.WindowPos.flags or SWP_NOZORDER; 
end; 

procedure TForm1.UMCancelIgnoreFocus(var Msg: TMessage); 
begin 
    FIgnoreFocus := False; 
    TForm(Msg.WParam).SetFocus; 
end; 

i Unit2:

type 
    TForm2 = class(TForm) 
    .. 
    procedure ActionList1Execute(Action: TBasicAction; var Handled: Boolean); 
    private 
    procedure WMWindowPosChanging(var Msg: TWMWindowPosChanging); 
     message WM_WINDOWPOSCHANGING; 
    public 
    end; 

var 
    Form2: TForm2; 

implementation 

uses 
    unit1; 

{$R *.dfm} 

procedure TForm2.ActionList1Execute(Action: TBasicAction; var Handled: Boolean); 
begin 
    Form1.IgnoreFocus := True; 
    PostMessage(Form1.Handle, UM_CANCELIGNOREFOCUS, NativeInt(Self), 0); 
end; 

procedure TForm2.WMWindowPosChanging(var Msg: TWMWindowPosChanging); 
begin 
    inherited; 
    if Form1.IgnoreFocus then 
    Msg.WindowPos.flags := Msg.WindowPos.flags or SWP_NOZORDER; 
end; 
+1

Świetna odpowiedź! Nadal nie wiem, czy ktoś może mi powiedzieć, dlaczego zaprojektowali kontrolę, aby zachowywał się w tak wymuszony sposób, kiedy mógł po prostu przekazać kontrolę rodzicowi Ribbon - myślę, że to tylko tajemnica Delphi. – Aaron

Powiązane problemy