On Monday, October 06, 2008 12:29 PM Jesper Stenlund wrote: Subiect: Ang. RE: GUI-questions > > I have tried the "ActionBars" and "Actionlists" but I found them a bit > hard to work with and I also have some dynamic menuitems. > But I think I should try that solution once more to see if I can get it > to > work.
Turning "normal" menus into ActionBars works, and if it's done in a procedure (ie: not from the form's FormCreate) it can nicely handle changing menu structures. The trick here is to build the whole menu and then call the procedure to turn it into ActionBars so you can call it from FormCreate and from any other place after a menu structure change. To make things easier I used a custom action class (TMenuAction) that's linked to a TMenuItem and forwards the click. Here's the definition: <code> TMenuAction = class(TCustomAction) protected M:TMenuItem; procedure Notification(AComponent: TComponent; Operation: TOperation); override; public constructor Create(Owner:TComponent; Menu:TMenuItem);reintroduce; destructor Destroy;override; procedure MyClick(Sender:TObject); procedure MyUpdate(Sender:TObject); end; constructor TMenuAction.Create(Owner: TComponent; Menu: TMenuItem); begin inherited Create(Owner); M := Menu; if Assigned(M) then M.FreeNotification(Self); Caption := M.Caption; ImageIndex := M.ImageIndex; OnExecute := MyClick; OnUpdate := MyUpdate; end; </code> As you can see the TMenuAction implementation is truly "naive" but it works nice. Also notice the Constructor, it's designed so new TMenuAction's can be generated with little coding. It's just a simple wrapper that reroutes "OnExcute" calls to the menu item's OnClick and makes it so OnUpdate gets the "enabled" state from the initial menu item. Now I'll give you two other snippets of code from my own code. Hopefully those would be enough to get you started (even those the code is out-of-context and will probably fail to compile because of missing names): <code> function CreateMenuItem(const Base:TMenuItem; const Root:TActionClientItem; const Tag:Integer):TActionClientItem; begin if Assigned(Root) then Result := Root.Items.Add else Result := AM.ActionBars[0].Items.Add; Result.Caption := Base.Caption; Result.ImageIndex := Base.ImageIndex; Result.Visible := True; Result.Tag := Tag; end; function CreateTerminalItem(const Base:TMenuItem; const Root:TActionClientItem; Tag:Integer):TActionClientItem; var Actn:TMenuAction; begin if Base.Caption = '-' then begin // Building an separator if Assigned(Root) then Result := Root.Items.Add else Result := AM.ActionBars[0].Items.Add; Result.Caption := '-'; Result.Visible := True; Result.Tag := Tag; end else begin // Building an terminal node Actn := TMenuAction.Create(Self, Base); Actn.ActionList := AM; Actn.OnUpdate := Actn.MyUpdate; if Assigned(Root) then begin Root.Items.AutoHotKeys := False; Result := Root.Items.Add; end else begin AM.ActionBars[0].Items.AutoHotKeys := False; Result := AM.ActionBars[0].Items.Add; end; Result.Action := Actn; Result.Visible := True; Result.Tag := Tag; end; end; </code> I can't copy-paste the whole code out of my applications because it includes a lot of business logic, comments and function names in romanian. If you can't make it work with the tiny bits of code I managed to extract, just ask I'd be happy to code a demo that's free of business logic and is 100% english. > The components that's not rendered is a mystery. > It is a standard TEdit placed in a standard TGroupBox that is placed on > a > TTabSheet. > But a TPanel placed inside the same Groupbox is rendered just perfect. > > The problem also occurs on a TListBox placed inside a TGroupBox and a > TEdit placed directly on the tabsheet. > A derived ListView still have the old grey colour on the columnheaders. > I > think that colour should be a little bit more white. > > But if I create a new application and put the same type of components > on a > tabsheet it all looks perfect. > I have looked it over again and again and I can't figure out the > difference between the components in my "old application" and the > components in my new "test application". > > Tha actual PageControl is placed on a form that is derived in several > levels, but I can't see why that should be a problem? > My guess is that there's something wrong with the parent control. I have no idea how to fix it, but I can give you some debugging pointers. (1) Try to isolate the parent that's disabling theeming. To do this locate one form where the problem manifests itself (the form where you have a page control that's not rendering properly). Select the control, hit "escape" to select it's parent and place an TButton there. Use the escape key so you can place buttons on every parent at every hierarchical level until you reach the form. Run the application. Hopefully you'll see the control where buttons start loosing theeming. (2) Once you've got an control that's not theeming properly you may start looking for the problem. Look at the control's implementation (most likely in StdCtrls.pas) and start placing breakpoints in the procedures involved in painting: WMEraseBkgnd, CNCtlColorBtn, and other procedures that use the ThemeServices. Hopefully tracing the code would show you how the parent disables theeming and that in turn would make fixing the problem easy. -- Good luck, Cosmin Prund _______________________________________________ Delphi mailing list -> Delphi@elists.org http://lists.elists.org/cgi-bin/mailman/listinfo/delphi