2012-03-06 12 views
7

Natknąłem się ostatnio na naprawdę dziwne zachowanie. Kiedy używam TActionMainMenuBar (lub TActionToolBar) w moim programie, kompiluję i uruchamiam, a następnie uruchamiam Photoshop CS5 lub Internet Explorer 9, ActionMainMenuBar (i ActionToolBar) traci wszystkie swoje ustawienia. Kolory zdefiniowane w przypisanej mapie kolorów znikają, a ustawienia czcionek również zostają utracone. Czy ktoś widział to wcześniej i zna obejście?TActionMainMenuBar i TActionToolbar tracą ustawienia

D2007 Pro (wszystkie zastosowane aktualizacje), D2010 Pro (wszystkie zastosowane aktualizacje), Vista Home Premium 32-bitowy, NVidia GForce 8600 GT, najnowszy zainstalowany sterownik.

Kroki do odtworzenia:

  1. upuść TActionManager i TActionMainMenuBar na formularzu
  2. Tworzenie kategorii z niektórych elementów menu
  3. Drag kategorii na ActionMainMenuBar
  4. Przypisz TwilightColorMap do ActionMainMenuBar
  5. Uruchom program
  6. Uruchom program IE9 lub Photoshop CS5
  7. Oglądaj wszystkie predefiniowane ustawienia znikają (trzeba zamknąć IE9 ponownie, aby zobaczyć efekt)

Jeśli zaczniesz Photoshop lub IE, a potem program Delphi, nic się nie dzieje. Błąd występuje również w trybie projektowania w IDE. Inny programista potwierdził już opisane zachowanie dla swojego systemu za pomocą Win7 Pro 32bit i ATI Radeon 9800 Pro.

Thx za wszelkie komentarze/rozwiązań

Phil

PS: Korzystanie z Photoshop CS3 nie wywołuje ten błąd

+1

ouch, najprawdopodobniej ustawienie rejestru ... spróbuj przeszukać kod źródłowy rejestru, sprawdź, gdzie jest "zapisz/załaduj" implementację i wykonaj obejście ... – ComputerSaysNo

+0

Kiedy mówisz, że Twoje ActionMainMenuBar "traci wszystkie swoje ustawienia "Czy odnosisz się do ustawień właściwości, obrazów lub programów do obsługi zdarzeń lub czegoś innego? –

+0

Traci ustawienia właściwości - w tym przypadku kolory zdefiniowane w mapie kolorów i ustawienia czcionek. – Phil

Odpowiedz

7

Oto jeden inny sposób odtwarzając problem:

  • Kompletna kroki od 1 do 4 jak w pytaniu (w tym upuszczenie TwilightColorMap).
  • Dodaj przycisk do formularza z kodem  Perform(WM_SETTINGCHANGE, 0, 0); w jego module obsługi kliknięć.
  • Uruchom aplikację i naciśnij przycisk.


Więc teraz wiemy, że WM_SETTINGCHANGE transmisji może być przyczyną problemu, możemy się zastanawiać, czy uruchomienie IE produkuje ten sam:

type 
    TForm1 = class(TForm) 
    .. 
    protected 
    procedure WMSettingChange(var Message: TWMSettingChange); 
     message WM_SETTINGCHANGE; 
    .. 

procedure TForm1.WMSettingChange(var Message: TWMSettingChange); 
begin 
    Memo1.Lines.Add(IntToHex(Message.Flag, 4) + ', ' + Message.Section); 
    inherited; 
end; 

Po prowadzimy naszą aplikację, a następnie uruchomić IE, kilka sekund później poniżej pojawia się w notatce:

0000, Software \ Microsoft \ Internet Explorer \ SearchScopes

Nie mam pojęcia, co IE ma do powiedzenia na temat naszej formy (i wszystkich innych okien najwyższego poziomu) przy każdym uruchomieniu, i nie wiem, czy robi to na każdym polu Windows na ziemi, czy tylko na twoim i moim , ale widocznie ActionMainMenuBar nie jest dobry w obchodzeniu się z nim.


Kontrola wygranych (formularz), odbierająca WM_WININICHANGE, wykonuje CM_WININICHANGE, a po otrzymaniu wysyła ten sam do wszystkich kontrolek. Poniżej jak to jest obsługiwane przez menu:

procedure TCustomActionMainMenuBar.CMWininichange(var Message: TWMWinIniChange); 
begin 
    inherited; 
    RequestAlign; 
    Font.Assign(Screen.MenuFont); 
end; 

myśląc, że czcionki menu system może zostały zmienione (kod powinien mieć wyglądał na „WindowsThemeElement” lub sekcji WindowMetrics 'w wiadomości, ale tak czy inaczej ...), jest ponownie przypisywany z odświeżonego Screen.MenuFont. Problem polega na tym, że nie używaliśmy go dokładnie.

Dodatkowo ColorMap odpowiada na CM_WININICHANGE, resetując kolory, wywołując metodę UpdateColors. Jest nawet documented:

UpdateColors nazywa się automatycznie, gdy składnik ActionBand otrzymuje wiadomość CM_WININICHANGE.


więc rozwiązanie wiązałoby się zdecydować, co robić i przesłanianie zarówno zachowanie, próbowałem skomentować rozwiązania poniżej, dlaczego uważam, że byłoby to poprawne rozwiązanie:

type 
    // Derive your own ColorMap that would reset its own colors. 
    // This is an interposer for simplicity.. 
    TTwilightColorMap = class(actncolormaps.TTwilightColorMap) 
    public 
    procedure UpdateColors; override; 
    published 
    property Color default clGreen; 
    property FontColor default clYellow; 
    property MenuColor default $4488FF; 
    // reintroduce as many property as necessary, probably all is necessary.. 
    end; 

    TForm1 = class(TForm) 
    .. 
    private 
    FSaveMenuFont: TFont; // will hold initial main menu bar's font settings 
    protected 
    procedure WMSettingChange(var Message: TWMSettingChange); 
     message WM_SETTINGCHANGE; 
    end; 

.. 

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    FSaveMenuFont := TFont.Create; 
    FSaveMenuFont.Assign(ActionMainMenuBar1.Font); 
end; 

procedure TForm1.FormDestroy(Sender: TObject); 
begin 
    FSaveMenuFont.Destroy; 
end; 

procedure TForm1.WMSettingChange(var Message: TWMSettingChange); 
begin 
    inherited; 
    // The below are the *section*s that really changing system settings 
    // would notify that I'm aware of, there may be more... 
    if (Message.Section <> 'WindowsThemeElement') 
     or (Message.Section <> 'WindowMetrics') then 
    ActionMainMenuBar1.Font.Assign(FSaveMenuFont) 
    else 
    // Develop your logic here. The system menu font might really have been 
    // changed. You can get it from Screen.MenuFont. But then if we had been 
    // using the system font, the control already applies the change by default. 

end; 

procedure TTwilightColorMap.UpdateColors; 
begin 
    inherited; 
    // Reset your colors, note that system colors might have been 
    // changed or not. If changed, they should be reflected in 'cl..' constants. 
    Color := clGreen; 
    FontColor := clYellow; 
    MenuColor := $4488FF; 
end; 
+1

+1. Niezła robota detektywistyczna i dobrze napisana odpowiedź. :) –

+1

Dzięki @Ken. O ile mogę powiedzieć, nie będzie to zbyt użyteczne, ponieważ ColorMap nie jest powszechnie stosowaną kontrolą. Ale było fajnie :). –

+0

Nigdy nie wiadomo ... Wiele osób nadal używa D7 i 2007, którzy nie mają dostępu do stylów VCL, które mogą z nich korzystać. Nadal jest to miła robota, która pomaga nam rozwiązać problem. :) –

3

Znaleziona ! Problem polegał na tym, że właściwość Colormap w ActionMainMenuBar1 jest resetowana do ActionMainMenuBar1.DefaultColormap za każdym razem, gdy IE9 lub Photoshop CS5 jest uruchamiany/zamykany. Przyjmuję rozwiązanie Sertaca jako odpowiedź, ponieważ wskazał mi właściwy kierunek rozwiązania tego problemu.

Oto ostateczny kod. Działa bezbłędnie (o ile wiem) zarówno teraz w IE9, jak i Photoshop CS5.

unit Unit1; 

interface 

uses 
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
    Dialogs, ActnMan, ActnColorMaps, ActnList, ToolWin, ActnCtrls, ActnMenus, 
    StdCtrls; 


type 
    TForm1 = class(TForm) 
    ActionManager1: TActionManager; 
    ActionMainMenuBar1: TActionMainMenuBar; 
    Action1: TAction; 
    Action2: TAction; 
    Action3: TAction; 
    Action4: TAction; 
    TwilightColorMap1: TTwilightColorMap; 
    Memo1: TMemo; 
    procedure FormCreate(Sender: TObject); 
    procedure FormDestroy(Sender: TObject); 
    procedure ActionMainMenuBar1GetControlClass(Sender: TCustomActionBar; 
     AnItem: TActionClient; var ControlClass: TCustomActionControlClass); 
    protected 
    procedure WMSettingChange(var Message: TWMSettingChange); message WM_SETTINGCHANGE; 
    private 
    { Private declarations } 
    FSaveMenuFont: TFont; // will hold initial main menu bar's font settings 
    FSaveColormap: TTwilightColormap; 
    public 
    { Public declarations } 
    end; 

var 
    Form1: TForm1; 

implementation 

{$R *.dfm} 


// Fixing paint issue when IE9 was run and closed again 

procedure TForm1.ActionMainMenuBar1GetControlClass(Sender: TCustomActionBar; 
    AnItem: TActionClient; var ControlClass: TCustomActionControlClass); 
begin 
    ActionMainMenuBar1.ColorMap.Assign(FSaveColormap); 
end; 


procedure TForm1.FormCreate(Sender: TObject); 
begin 
    FSaveMenuFont := TFont.Create; 
    FSaveMenuFont.Assign(ActionMainMenuBar1.Font); 
    FSaveColormap := TTwilightColormap.Create(Self); 
    FSaveColormap.Assign(ActionMainMenuBar1.Colormap); 
end; 


procedure TForm1.FormDestroy(Sender: TObject); 
begin 
    FSaveMenuFont.Destroy; 
    FSaveColormap.Destroy; 
end; 


procedure TForm1.WMSettingChange(var Message: TWMSettingChange); 
begin 
    inherited; 
    // Memo1.Lines.Add(IntToHex(Message.Flag, 4) + ', ' + Message.Section); 
    ActionMainMenuBar1.Font.Assign(FSaveMenuFont); 
    // In case Photoshop CS5 was run and closed before 
    ActionMainMenuBar1.ColorMap.Assign(FSaveColormap); 
end; 

end. 

Jeszcze raz dziękuję wszystkim za pomoc.

+0

Cieszę się, że udało ci się to rozwiązać :) i dzięki za przesłanie rozwiązania. –

+0

W końcu udało mi się naprawić problem z farbami zarówno dla IE9, jak i Photoshop CS5. Zobacz zaktualizowany kod powyżej. Dzięki. – Phil

+0

Czy GetControlClass nie jest już niepotrzebny? –

Powiązane problemy