Mega Code Archive

 
Categories / Delphi / Examples
 

Save resources in tnotebooks, ttabbednotebooks and ttabsheets

NoteBooks, TTabbedNotebooks and TabSheets inhale a relatively large amount of a computer's resources. To free the resources of all components which are currently not displayed (because they are on a "hidden" page), place the following piece of code in the TNotebook's TTabset TabClick-Event: FOR i := 0 TO nbAdresses.Pages.Count-1 DO IF i <> nbAdresses.PageIndex THEN TfrmAdressForm(nbAdresses.Pages.Objects[i]).DestroyHandle; Because Delphi keeps the objects stored internally, all of them will nevertheless correctly be displayed when you change to the "cleaned" pages again. To accomplish a similar task with TTabbedNotebooks, put the following at the end of your tTabbedNotebook's onChange event (From Sid Gudes): IF AllowChange THEN BEGIN WITH TabbedNotebook1 DO BEGIN LockWindowUpdate(Handle); THintWindow(Pages.Objects[PageIndex]).ReleaseHandle; TWinControl(Pages.Objects[NewTab]).HandleNeeded; LockWindowUpdate(0); END; TabAt[nbPacket.PageIndex] := TabPacket.TabIndex; END; And to restore the handles: IF Sender is TTabbedNotebook THEN WITH TTabbedNotebook(Sender) DO BEGIN CurrentPage := TWinControl(Pages.Objects[PageIndex]); LockWindowUpdate(Handle); TWinControl(Pages.Objects[NewTab]).HandleNeeded; LockWindowUpdate(0); END; Some caveats on these methods: if you have any tComboBoxes with style of csDropDownList, you'll lose the values in them (csDropDown works OK); you can write some code to cycle through the components and save the values beforehand, then restore them afterwards. this frees resources as the user clicks through the pages/tabs, but at FormCreate time all pages will be created, so the resource hit will be high at the beginning. carefully watch the edit mode of the tables of the form - in my apps I always lost the edit mode after changing the pages/tabs and had to recall it. General speed issues Use BeginUpdate / EndUpdate when doing large screen operations ! (btw: Since WM_SETREDRAW and LockWindowUpdate seem to accomplish the same task, I think it is easier to stick with the BeginUpdate/EndUpdate Delphi methods than dropping to the Windows API. Not to mention the fact that LockWindowUpdate can cause horrendous flickering in any other apps visible on the screen :). ) General: saving resources Some tips which - for example - can help you prevent this hated message "Out of resources - can't create window" ... Avoid using Form-Autocreation ! If you create new forms for you project by selecting File..New.. with Delphi, it creates code in your project file (.DPR - you can open it by pressing Ctrl-F4), which will create each form automatically at the startup of your Application: USES MainForm in 'MainForm.pas', ChildFrm1 in 'ChildFrm1.pas', ChildFrm2 in 'ChildFrm2.pas', (..etc..); [..] BEGIN Application.CreateForm(TMainForm ,MainForm); Application.CreateForm(TChildFrm1,ChildFrm1); Application.CreateForm(TChildFrm2,ChildFrm2); (..etc..); END; This doesn't only slow down the startup, but also uses huge amounts of memory ! Instead, let Delphi create only your "Main-Form" automatically, and remove any other forms from the USES-clause, remove any other auto-creations from the project source and create those other forms in the source of the main-form "by hand" - and only where you really need it: procedure MyMainForm.mnuClientsClick(Sender: TObject); BEGIN ChildForm1 := TChildForm1.Create(Self); ChildForm1.ShowModal; { if it's a MDI-form, use ChildForm1.Tile; } ChildForm1.Release; { will save additional resources ! } END; Even applications less than 200kb in size use approx. 1 MB of RAM because the Delphi RTL obtains much of it's variant support from OLEAUT32.DLL. However, if you're not using OLE you can free those libs by putting FreeLibrary(GetModuleHandle('OleAut32')); in the OnCreate event of your MainForm or your project source. It will unload OleAut32.dll and OLE32.dll, which use about one meg. Release memory of closed forms by putting either MyForm1.Release; in the calling form (after closing it) or by placing the line Action := caFree; in the OnClose-Event of your Form. Check: in your program there should never be more than 4 or 5 windows opened at the same time. Each window consumes quite a lot of dynamic resources. Use TBevel's rather than TPanels ! The TPanel-component needs a separate window-handle whereas a TBevel is only a "painted" are on your form. So you can again save resources by just "painting" a Bevel on it instead of filling it with resource-eating Panels... Set "ParentFont=TRUE" on your forms ! By doing that, your app doesn't have to load and keep font-instances for each individual component anymore.