2012-03-06 12 views
7

Recentemente sono incappato in un comportamento davvero strano. Quando uso un TActionMainMenuBar (o un TActionToolBar) nel mio programma, compile ed eseguo, e poi avvio Photoshop CS5 o Internet Explorer 9, ActionMainMenuBar (e ActionToolBar) perde tutte le sue impostazioni. I colori definiti nella mappa colori assegnata scompaiono e anche le impostazioni dei caratteri vengono perse. Qualcuno ha visto questo prima e conosce una soluzione?TActionMainMenuBar e TActionToolbar perdono le impostazioni

D2007 Pro (tutti gli aggiornamenti applicati), D2010 Pro (tutti gli aggiornamenti applicati), Vista Home Premium 32 bit, NVidia GForce 8600 GT, ultimo driver installato.

Procedura per riprodurre:

  1. goccia un TActionManager e un TActionMainMenuBar su una forma
  2. Creare una categoria con alcune voci di menu
  3. categoria Trascinare ActionMainMenuBar
  4. Assegnare TwilightColorMap al ActionMainMenuBar
  5. Esegui programma
  6. Avvia IE9 o Photoshop CS5
  7. Guarda tutte le impostazioni predefinite scompaiono (si deve chiudere IE9 di nuovo per vedere l'effetto)

Se si avvia Photoshop o IE prima e poi il programma di Delphi, non succede nulla. Il bug è presente anche in modalità progettazione nell'IDE. Un altro sviluppatore ha già confermato il comportamento descritto per il suo sistema con Win7 Pro 32bit e ATI Radeon 9800 Pro.

Thx per qualsiasi commento/soluzioni

Phil

PS: Utilizzo di Photoshop CS3 non produce questo bug

+1

ouch, molto probabilmente un'impostazione del Registro di sistema ... prova a cercare il codice sorgente per Registry, vedi dove è l'implementazione "salva/carica" ​​e fai una soluzione ... – ComputerSaysNo

+0

Quando dici che ActionMainMenuBar "perde tutte le sue impostazioni 'ti riferisci a impostazioni di proprietà o immagini o gestori di eventi o qualcos'altro? –

+0

Sta perdendo le impostazioni delle proprietà, in questo caso i colori definiti nella mappa colori e le impostazioni del carattere. – Phil

risposta

7

Ecco un altro modo di riprodurre il problema:

  • Complete passaggi da 1 a 4 come nella domanda (compreso il rilascio di una TwilightColorMap).
  • Aggiungere un pulsante al modulo con il codice  Perform(WM_SETTINGCHANGE, 0, 0); nel relativo gestore di clic.
  • Eseguire l'applicazione e premere il pulsante.


Così ora sappiamo che una trasmissione WM_SETTINGCHANGE potrebbe essere la causa del problema, potremmo chiederci se il lancio di IE produce lo stesso:

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; 

Dopo corriamo la nostra applicazione e poi lanciare IE, alcuni secondi dopo il sotto compare nel memo:

0000, Software \ Microsoft \ Internet Explorer \ SearchScopes

Non ho idea di cosa IE debba dire al nostro modulo (e a tutte le altre finestre di primo livello) ad ogni avvio, e non so se lo sta facendo su tutte le finestre di Windows o solo sul mio e sul mio , ma evidentemente il ActionMainMenuBar non è in grado di gestirlo.


Un controllo di vittoria (il modulo), ricevendo un WM_WININICHANGE, esegue un CM_WININICHANGE e al momento del ricevimento trasmette lo stesso a tutti i suoi controlli. Il sotto è come viene gestito dalla barra dei menu:

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

Pensando che il tipo di carattere menu di sistema potrebbe essere stato modificato (il codice dovrebbe avere guardato per un 'WindowsThemeElement' o la sezione 'WindowMetrics' nel messaggio, ma comunque ..), viene riassegnato dall'aggiornato Screen.MenuFont. Il problema è che non lo stavamo usando esattamente.

Inoltre, ColorMap risponde a CM_WININICHANGE ripristinando i relativi colori chiamando il metodo UpdateColors. Questo è ancora documented:

UpdateColors viene chiamato automaticamente quando un componente ActionBand riceve un messaggio CM_WININICHANGE.


Quindi la soluzione comporterebbe decidere cosa fare e ignorando sia il comportamento, ho cercato di commentare la soluzione qui di seguito per questo che credo che sarebbe la soluzione giusta:

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. Bel lavoro da investigatore e risposta ben scritta. :) –

+1

Grazie a @Ken. Per quanto posso dire questo non sarà molto utile, in quanto ColorMap non è un controllo ampiamente utilizzato. Ma è stato divertente :). –

+0

Non si può mai dire ... Ci sono ancora molte persone che usano D7 e 2007 che non hanno accesso agli stili VCL che potrebbero usarli. Ancora un buon lavoro rintracciare il problema. :) –

3

Trovato ! Il problema era che la proprietà Colormap di ActionMainMenuBar1 viene reimpostata su ActionMainMenuBar1.DefaultColormap ogni volta che IE9 o Photoshop CS5 viene avviato/chiuso. Accetterò la soluzione di Sertac come risposta perché mi ha indirizzato nella giusta direzione su come risolvere questo problema.

Ecco il codice finale. Funziona perfettamente (per quanto ne so) con IE9 e Photoshop CS5 ora.

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. 

Grazie ancora a tutti per il vostro aiuto.

+0

Felice di averlo risolto :) e grazie per aver pubblicato la tua soluzione. –

+0

Sono finalmente riuscito a risolvere il problema della vernice sia per IE9 che per Photoshop CS5. Si prega di consultare il codice aggiornato sopra. Grazie. – Phil

+0

Non è ora GetControlClass non necessario? –

Problemi correlati